This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR5994:具有 SPI 的 LIS2DH 加速计

Guru**** 2582405 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/614130/msp430fr5994-lis2dh-accelerometer-with-spi

器件型号:MSP430FR5994

大家好

我已经尝试过一段时间来使 LIS2DH 加速计(在 STEVAL-MKI135V1评估板上)正常工作。 我首先要读取谁是我的寄存器、这样我就可以确保 SPI 正常工作。 最近、我使用了以下链接中的答案尝试解决我的问题。  

https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/593640

以下代码使用上述链接中发布的解决方案,但在等待 TX 缓冲区准备就绪时仍停留在 spiTransfer()中。

//!
//! 在 MSP430FR5994上进行了测试
//! --------
//! /|\| |
//! || |
//! 主设备--+-|RST |
//! | |
//! | P5.0|->数据输出(UCB0SIMO)->SDA//
! | |
//! | P5.1|<-数据输入(UCB0SOMI)<- SDO
//! | |
//! | P5.2|->串行时钟输出(UCB0CLK)-> SCL
//!
//!
//! 此外、连接接地、电源和 I/O 电源
//! 也将 CS 接地
//!
//

#include "driverlib.h"

uint8_t RXData = 0;
uint8_t TXData = 0;

uint8_t spiTransfer (uint8_t writeData);

void setWriteMode (uint8_t addr);

void setReadMode (uint8_t addr);

void writeByte (uint8_t data);

uint8_t readByte (void);

void main (void)
{
volatile uint16_t i;

//停止看门狗计时器
WDT_A_HOLD (WDT_A_base);

//为 LFXIN 配置引脚
//将 PJ.4和 PJ.5设置为主模块功能输入。
/*

*选择端口 J
*将引脚4、5设置为输入主模块功能(LFXIN)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_PJ、
GPIO_PIN4 + GPIO_PIN5、
GPIO_PRIMARY_MODULE_FUNCTION
);

//设置 XT1的外部频率
cs_setExternalClockSource (32768、0);
//将 DCO 频率设置为最大 DCO 设置
CS_setDCOFreq (CS_DCORSEL_0、CS_DCOFSEL_3);
//选择 XT1作为不带分频器的 ACLK 的时钟源
CS_initClockSignal (CS_ACLK、CS_LFXTCLK_select、CS_Clock_divider);
//Start XT1、无超时
CS_TurnOnLFXT (CS_LFXT_DRIVE_0);

//配置 SPI 引脚
//为 UCB0CLK 配置引脚

/*

*选择端口5
*将引脚2设置为输入次级模块功能、(UCB1CLK)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_P5、
GPIO_PIN2、
GPIO_PRIMARY_MODULE_FUNCTION
);
//为 UCB1TXD/UCB1SIMO、UCB1RXD/UCB1SOMI 配置引脚
//将 P5.0、P5.1设置为辅助模块功能输入。
/*

*选择端口5
*将引脚0、1设置为输入次级模块功能(UCB1TXD/UCB1SIMO、UCB1RXD/UCB1SOMI)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_P5、
GPIO_PIN0 + GPIO_PIN1、
GPIO_PRIMARY_MODULE_FUNCTION
);

/*
*禁用 GPIO 上电默认高阻抗模式以激活
*先前配置的端口设置
*
PMM_unlockLPM5 ();

//初始化主设备
EUSCI_B_SPI_initMasterParam param ={0};
param.selectClockSource = EUSCI_B_SPI_CLOCKSOURCE_ACLK;
param.clockSourceFrequency = CS_getACLK ();
param.desiredSpiClock = 50000;
param.msbFirst = EUSCI_B_SPI_LSB_FIRST;
param.clockPhase = EUSCI_B_SPI_PHASE_DATA_Changed_ONFIRST_capted_on_next;
param.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTION_HIGH;
param.spiMode = EUSCI_B_SPI_3引脚;
EUSCI_B_SPI_initMaster (EUSCI_B1_BASE、&param);

//启用 SPI 模块
EUSCI_B_SPI_ENABLE (EUSCI_B1_BASE);

EUSCI_B_SPI_clearInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_Receive_interrupt
);

EUSCI_B_SPI_clearInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_TUSE_INTERRUPT
);

//启用 USCI_B0 RX 中断
EUSCI_B_SPI_enableInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_Receive_interrupt);

//启用 USCI_B0 TX 中断
EUSCI_B_SPI_enableInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_Transmit 中断);

setReadMode (0x0F);
RXData = readByte ();


}

uint8_t spiTransfer (uint8_t writeData)
{
while (!(UCB1IFG & UCTXIFG));//等待 TX 缓冲区就绪
UCA1TXBUF = writeData;
while (!(UCB1IFG & UCRXIFG));//等待 RX 缓冲区就绪
返回 UCA1RXBUF;
}

void setWriteMode (uint8_t addr)
{
spiTransfer (addr | 0x00);
}

void setReadMode (uint8_t addr)
{
spiTransfer (addr | 0x80);
}

void writeByte (uint8_t data)
{
spiTransfer (data);
}

uint8_t readByte ()
{
返回 spiTransfer (0xAA);
}

我还尝试在不调用函数的情况下实现该解决方案、如下所示。

//!
//! 在 MSP430FR5994上进行了测试
//! --------
//! /|\| |
//! || |
//! 主设备--+-|RST |
//! | |
//! | P5.0|->数据输出(UCB0SIMO)->SDA//
! | |
//! | P5.1|<-数据输入(UCB0SOMI)<- SDO
//! | |
//! | P5.2|->串行时钟输出(UCB0CLK)-> SCL
//!
//!
//!
//

#include "driverlib.h"

uint8_t RXData1 = 0;
uint8_t RXData2 = 0;
uint8_t TXData = 0;

void main (void)
{
volatile uint16_t i;

//停止看门狗计时器
WDT_A_HOLD (WDT_A_base);

//为 LFXIN 配置引脚
//将 PJ.4和 PJ.5设置为主模块功能输入。
/*

*选择端口 J
*将引脚4、5设置为输入主模块功能(LFXIN)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_PJ、
GPIO_PIN4 + GPIO_PIN5、
GPIO_PRIMARY_MODULE_FUNCTION
);

//设置 XT1的外部频率
cs_setExternalClockSource (32768、0);
//将 DCO 频率设置为最大 DCO 设置
CS_setDCOFreq (CS_DCORSEL_0、CS_DCOFSEL_3);
//选择 XT1作为不带分频器的 ACLK 的时钟源
CS_initClockSignal (CS_ACLK、CS_LFXTCLK_select、CS_Clock_divider);
//Start XT1、无超时
CS_TurnOnLFXT (CS_LFXT_DRIVE_0);

//配置 SPI 引脚
//为 UCB0CLK 配置引脚

/*

*选择端口5
*将引脚2设置为输入次级模块功能、(UCB1CLK)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_P5、
GPIO_PIN2、
GPIO_PRIMARY_MODULE_FUNCTION
);
//为 UCB1TXD/UCB1SIMO、UCB1RXD/UCB1SOMI 配置引脚
//将 P5.0、P5.1设置为辅助模块功能输入。
/*

*选择端口5
*将引脚0、1设置为输入次级模块功能(UCB1TXD/UCB1SIMO、UCB1RXD/UCB1SOMI)。
*
GPIO_setPeripheralModuleFunctionInputPin (
GPIO_PORT_P5、
GPIO_PIN0 + GPIO_PIN1、
GPIO_PRIMARY_MODULE_FUNCTION
);

/*
*禁用 GPIO 上电默认高阻抗模式以激活
*先前配置的端口设置
*
PMM_unlockLPM5 ();

//初始化主设备
EUSCI_B_SPI_initMasterParam param ={0};
param.selectClockSource = EUSCI_B_SPI_CLOCKSOURCE_ACLK;
param.clockSourceFrequency = CS_getACLK ();
param.desiredSpiClock = 50000;
param.msbFirst = EUSCI_B_SPI_LSB_FIRST;
param.clockPhase = EUSCI_B_SPI_PHASE_DATA_Changed_ONFIRST_capted_on_next;
param.clockPolarity = EUSCI_B_SPI_CLOCKPOLARITY_INACTION_HIGH;
param.spiMode = EUSCI_B_SPI_3引脚;
EUSCI_B_SPI_initMaster (EUSCI_B1_BASE、&param);

//启用 SPI 模块
EUSCI_B_SPI_ENABLE (EUSCI_B1_BASE);

EUSCI_B_SPI_clearInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_Receive_interrupt
);

//启用 USCI_B0 RX 中断
EUSCI_B_SPI_enableInterrupt (EUSCI_B1_BASE、
EUSCI_B_SPI_Receive_interrupt);

//发送读“谁是我”命令

//USCI_B0 TX 缓冲器准备好了吗?
while (!(UCB1IFG & UCTXIFG));//等待 TX 缓冲区就绪

//向从器件发送数据
UCB1TXBUF = 0x8F;

//USCI_B0 RX 缓冲器准备好了吗?
while (!(UCB1IFG & UCRXIFG));//等待 RX 缓冲区就绪

RXData1 = UCB1RXBUF;

//接收“谁是我”寄存器值

//USCI_B0 TX 缓冲器准备好了吗?
while (!(UCB1IFG & UCTXIFG));//等待 TX 缓冲区就绪

//向从器件发送数据
UCB1TXBUF = 0xAA;

//USCI_B0 RX 缓冲器准备好了吗?
while (!(UCB1IFG & UCRXIFG));//等待 RX 缓冲区就绪

RXData2 = UCB1RXBUF;
}

在该版本中、代码不会卡住、但我遇到与帖子作者类似的问题。 我始终接收0xFF;但是、在其他情况下、我根本不接收任何内容。 这可以通过简单地断开和重新连接电源、然后再次调试程序来改变。  

我之前发送了"READ"命令、并读取了下一个传入的8位、就像我认为的情况那样、而不是等待另一个 SPI 周期发送垃圾、然后接收结果。 这可以在随附数据表的第27页上看到。  

我们非常感谢您的任何帮助。

e2e.ti.com/.../LIS2DH.pdf

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、JSud、

    我注意到您在代码中使用了 driverlib API。 您是否使用 driverlib 来获取有关 SPI 示例项目的示例? 您应该确保所有相关模块、例如时钟系统、GPIO、中断以及 eUSCI_B SPI 模式都已正确配置。

    我发现您使用了 uint8_t spiTransfer (uint8_t writeData)函数的寄存器级代码。 您可以尝试使用下面的 driverlib API 通过 SPI 发送和接收数据。 请在 此处找到 driverlib 用户指南

    空 EUSCI B SPI 传输数据(uint16 t baseAddress、uint8 t transmitData)

    uint8 t eUSCI B SPI 接收数据(uint16 t baseAddress)  

    您是否检查了硬件连接以确认没有问题? 请确保 SPI 的两个器件具有公共接地连接。

    我还建议您对 SPI 线路的信号进行示波、并分析线路上的数据。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好,Wei

    很抱歉耽误你的回答、但我解决了我的问题。 在使用加速计时、我无法始终保持 CS 为低电平、我必须发送引脚为高电平才能完成 SPI 传输(愚蠢的我)。

    无论如何、感谢您的回复。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的新问题似乎是我无法读取 x、y 和 z 数据。 我有无限循环的数据收集。

    首先、我初始化传感器、以100Hz 的频率和8位的精度在+-2g 范围内收集数据。 在循环中、我通过检查 STATUS_REG 来检查新的 x、y 和 z 数据是否可用。 奇怪的是、ZYDXA 位被置位、但 ZDA 和 Zor 从未置位。

    接下来、我开始收集数据。 数据地址从0x28递增、若要读取递增数据、发送地址时必须将前两位置位、因此发送0xE8。 当我检查接收到的数据时、x 和 y 的高字节始终为128。 z 高字节会发生变化、但总的来说它是0x9D、表示为二进制补码左对齐。 如果我计算正确、它对应于-99g 的读数。 我对转换能力不太有信心、因此0x9D 可能是正确的、因为当我倾斜传感器时、它会发生变化(例如、在90度处为0xDB)。  

    请查找以下代码:

    while (1){
    
    check =0x00;
    while (!(check & 0b00001000)){//等待新数据可用
    //将 CS 引脚设置为低电平(P8.1)
    P8OUT &=~0x02;
    spiTransfer (0xA7);
    Check = spiTransfer (0xFF);
    //将 CS 引脚设置为高电平(P8.1)
    P8OUT |= 0x02;
    }
    
    //将 CS 引脚设置为低电平(P8.1)
    P8OUT &=~0x02;
    spiTransfer (0xE8);//按以下顺序请求数据:x 低字节、x 高字节、y LB、yhb、ZLB、 zhb
    XLB= spiTransfer (0xFF);//存储 x 低字节
    xHb = spiTransfer (0xFF);//存储 x 高字节
    yLB= spiTransfer (0xFF);//存储 y 低字节
    yHb= spiTransfer (0xFF);//存储 y 高字节
    ZLB= spiTransfer (0xFF);//存储 z 低字节
    zhb= spiTransfer (0xFF);//存储 z 高字节
    //将 CS 引脚设置为高电平(P8.1)
    P8OUT |= 0x02;
    }
    

    uint8_t spiTransfer (uint8_t writeData){
    while (!(UCB1IFG & UCTXIFG));//等待 TX 缓冲区就绪
    UCB1TXBUF = writeData;
    while (!(UCB1IFG & UCRXIFG));//等待 RX 缓冲区就绪
    返回 UCB1RXBUF;
    } 

    我非常希望得到任何帮助。