大家好
我已经尝试过一段时间来使 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、¶m); //启用 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、¶m); //启用 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页上看到。
我们非常感谢您的任何帮助。