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.

[参考译文] MSP430FR5969:USCIB0 SPI 驱动程序问题

Guru**** 2049300 points
Other Parts Discussed in Thread: MSP430FR5969, LDC1101
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/915825/msp430fr5969-uscib0-spi-driver-issue

器件型号:MSP430FR5969
主题中讨论的其他器件: LDC1101

Hiiyyaa 论坛专家,
我为 LDC1101编写了一个基本 SPI 驱动程序。 因此、为了进行测试、我将尝试写入一个寄存器并从中读取。 但我遇到的问题是、它无法使 CS 引脚变为高电平、光标被吸入。 如果你能解决我的问题,我将对此表示感谢。 顺便说一下、我使用的是 MSP430FR5969开发板和 LDC1101。 那么、这是我的代码:
我将 USCIB0用于 SPI
///////////////////////////////////////////////////////////
#define SLAVE_CS_OUT   P1OUT
#define SLAVE_CS_DIR   P1DIR
#define SLAVE_CS_PIN   BIT3

#define ENABLE_SPI_TX_INT ()     {UCB0IE |= UCTXIE;}
/*启用接收中断*/
#define ENABLE_SPI_RX_INT ()     {UCB0IE |= UCRXIE;}

/*禁用接收中断*/
#define DISABLE_SPI_RX_INT ()    {UCB0IE &=~UCRXIE;}


空 initClockTo8MHz()

   //根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
   //在配置时钟系统之前在8MHz 以上运行。
   FRCTL0 = FRCTLPW | NWAITS_1;

   //时钟系统设置
   CSCTL0_H = CSKEY >> 8;                   //解锁 CS 寄存器
   CSCTL1 = DCORSEL | DCOFSEL_4;            //将 DCO 设置为16MHz
   CSCTL2 = SELA_VLOCLK | SELESS__DCOCLK | SELM_DCOCLK;
   CSCTL3 = DIVA__2 | DIVM__2;    //设置所有分频器

   CSCTL0_H = 0;                            //锁定 CS 寄存器

空 initGPIO()

   //LED
   P1OUT = 0x00;                            //针对 LED 和复位输出设置 P1
   P1DIR |= BIT0 + BIT4;

   P4DIR |= BIT6;
   P4OUT &=~(BIT6);
   
   P3DIR |= BIT4;
   P3SEL1 |= BIT4;                          //输出 SMCLK

   //配置 SPI 引脚
   P2SEL1 |= BIT2;                          //clk    
   P1SEL1 |= BIT6 | BIT7;                //配置 MISO/MOSI 引脚    

   SLAVE_CS_DIR |= SLAVE_CS_PIN;            // STE 引脚
   SLAVE_CS_OUT |= SLAVE_CS_PIN;            // STE 引脚使能

   //禁用 GPIO 上电默认高阻抗模式以激活
   //先前配置的端口设置
   PM5CTL0 &=~LOCKLPM5;


空 WriteUCB0Data (uint8_t val)

   while (!(UCB0IFG 和 UCTXIFG));             // USCI_B0 RX 缓冲区准备好了吗?
   UCB0TXBUF = val;

SPI_Mode SPI_Master_WriteReg (uint8_t reg_addr、uint8_t reg_data、uint8_t count)

   TransmitRegAddr = reg_addr;
   TransmitBuffer = reg_data;
   UCB0_TxComplete =真;
   //将寄存器数据复制到 TransmitBuffer
   //memcpy ((void *) TransmitBuffer、(const void *) reg_data、sizeof (reg_data));

   TXByteCtr =计数;

   ENABLE_CHIPSELECT ();
   ENABLE_SPI_TX_INT ();
   WriteUCB0Data (TransmitRegAddr);

   _bis_SR_register (LPM0_bits + GIE);             //输入 LPM0、带中断
   
   while (UCB0_TxComplete!= true)                 //我的程序存根请帮助我解决此问题
     disable_CHIPSELECT ();
   返回 MasterMode;


SPI_Mode SPI_Master_ReadReg (uint8_t reg_addr、uint8_t count)

   TransmitRegAddr = reg_addr;
   RXByteCtr =计数;
   TXByteCtr = 0;
   ReceiveIndex = 0;
   TransmitIndex = 0;

   Slave_CS_OUT &=~(SLAVE_CS_PIN);
   WriteUCB0Data (TransmitRegAddr);

   _bis_SR_register (CPUOFF + GIE);             //输入 LPM0、带中断

   SLAVE_CS_OUT |= SLAVE_CS_PIN;
   返回 MasterMode;



////////////////////////////////////////////////////////////////////////////////////////////////
int main (void){
   WDTCTL = WDTPW | WDTHOLD;  //停止看门狗计时器

   initClockTo8MHz();
   initGPIO();
   initspi();
   
   SPI_Master_WriteReg (RP_SET、0x45、WRITE_COUNT);
   SPI_Master_ReadReg (RP_SET、READ_COUNT);
   _bis_SR_register (LPM0_bits + GIE);      // CPU 关闭、启用中断
   /*
   
   
   必须在此处添加用于电感式感应的逻辑
   
   
   
   *
   //while (1)
     __no_operation();

   返回0;
}    


//////// SPI 中断//////////////
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=USCI_B0_vector
_interrupt void USCI_B0_ISR (void)
#Elif defined (_GNU_)
void __attribute__((中断(USCI_B0_vector)) USCI_B0_ISR (void)
其他
错误编译器不受支持!
#endif

   uint8_t ucb0_rx_val = 0;
 IF (((UCB0IE 和 UCTXIE)&&(UCB0IFG 和 UCTXIFG))
 {
   IF (TXByteCtr)
   {
     //WriteUCB0Data (TransmitBuffer[TransmitIndex++]);
     WriteUCB0Data (TransmitBuffer);
     TXByteCtr --;
   }
   其他
   {
     //传输完成
     MasterMode = IDLE_MODE;
     _BIC_SR_REGISTER_ON_EXIT (CPUOFF);     //退出 LPM0
   }
   UCB0IFG &=~UCTXIFG;      /*清除发送中断标志*/
   UCB0_TxComplete =错误;
 }

 if (((UCB0IE 和 UCRXIE)&&(UCB0IFG 和 UCRXIFG))        //此处出现检查并显示残桩
 {
   IF (RXByteCtr)
   {
     ReceiveBuffer[ReceiveIndex++]= ucb0_Rx_val;
     //发送虚拟
     RXByteCtr---;
   }
   IF (RXByteCtr = 0)
   {
     MasterMode = IDLE_MODE;
     _BIC_SR_REGISTER_ON_EXIT (CPUOFF);     //退出 LPM0
   }
   其他
   {
     WriteUCB0Data (虚拟);
                   }
   /*清除接收中断标志*/
   UCB0IFG &=~UCRXIFG;
 }
 }
 

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

    Manish、您好!

    我找不到  initSPI()函数,我看一下您的代码,发现您应该使用3线 SPI。  

    我想您可以阻止其他代码来仅测试此 P1.3引脚。

    此致

    Johnson

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

    你(们)好,约翰逊

    请原谅我

    空 initSPI()

       //时钟极性:无效状态为高电平
       //MSB 优先、8位、主器件、3引脚模式、同步
       UCB0CTLW0 = UCSWRST;                      //**将状态机置于复位状态**
       UCB0CTLW0 |= UCCKPL + UCMSB + UCSYNC + UCMODE_0
                   + UCMST + UCSSEL_SMCLK;     // 3引脚8位 SPI 从器件
       UCB0BRW = 0x20;
       //UCB0MCTLW = 0;                           //无调制
       UCB0CTLW0 &=~UCSWRST;                    //**初始化 USCI 状态机(禁用软件复位**)
       ENABLE_SPI_TX_INT ();                         //启用 USCI0 TX 中断


    请查看并确定我的错误

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

     >while (UCB0_TxComplete!= true)                 //我的程序存根请帮助我解决此问题
     >   disable_CHIPSELECT ();

    1) 1) ISR 会在完成时设置此变量=false、因此我不太确定它在等待什么。

    2) 2)由于 LPM、一旦到达该点、该变量的值将永远不会改变、因此循环不会执行任何操作、或者它将永远旋转。

    3) 3)该循环重复取消使/CS 无效、但实际上只希望它在操作完成后执行此操作。 (您是否缺少";"?)

    4) 4) ISR 在所有位被发送前唤醒 WriteReg ()。 在取消对/CS 的置为有效之前、您应该使用 UCBUSY。

    5) 5)该变量应声明为"volatile"。

    尝试如下操作:

    > while (UCB0_TxComplete)/* empty*/;  //等待 ISR 清除 TxComplete (可能已经发生)

    > while (UCB0STAT & UCBUSY)/* empty*/;//等待最后一位被发送

    > disable_CHIPSELECT ();  

    未经请求:LDC1101在其 SPI 上能够达到8MHz。 我建议您提高 SPI 时钟(BRW)的速度、并使用自旋环路(无中断)进行事务。 这将会更快、更容易正确。

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

    Hry Bruce、谢谢您让我尝试这种方法

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

    大家好、Bruce 和 Jhinson、

    您能不能说我的配置是否正确、我不需要确认一次。 请快速回复您可以在此处找到我的更新代码我已经解决了我之前的问题、但现在我可以将一些数据写入 LDC 寄存器、但无法从中读取。 请查看我随附的 codee2e.ti.com/.../3000.new-2.h

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

    根据 LDC1101数据表(SNOSD01D)图1-2、您的 SPI 配置看起来不错。

    使用 SPI、您可以准确地接收发送的字节数。 所以:  

    >RXByteCtr =计数;
    >TXByteCtr = 0;

    通过这种组合、您的 ISR 将永远不会传输任何内容、因此不会接收任何内容。 我看到您的 ISR 发送虚拟字节、但仅在收到字节时。 您可能需要调整代码结构以使其正常工作。

    > UCB0IFG &&~UCTXIFG;//清除发送中断标志*/

    写入 TXBUF 会清零 TXIFG、因此您不应该自行将其清零。 如果您没有任何要发送的内容、请清除 TXIE。 与 RXBUF/RXIFG 类似。

    [编辑:同样、在取消对/CS 的置位之前、您还没有等待(UCBUSY -见上面)所有要发送的位。 由于您的 SPI 太慢、这很可能会导致问题。]

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

    Bruce、您好!

    您建议我提高 SPI 的时钟速度、但我在查看用户指南时发现、我无法知道我应该为使 SPI 速度更快而设置的值。 您能不能就此向我提出建议

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

    BRW 是 SMCLK 的简单整数分频器(在您的情况下)。 您已将 SMCLK 配置为从外部晶振(HFXT)运行、因此我不知道它的运行速度有多快。 假设 HFXT 以8MHz 运行、BRW=2会将 SPI 时钟设置为(8MHz/2)=4MHz。

    未经请求:您正在从 DCO 运行 MCLK、而从 HFXT 运行 SMCLK。 除非您有特定用途、否则我建议您对两者使用相同的源(DCO 或 HFXT)。 从理论上讲、您所拥有的一切都可以正常工作、但系统的某些角落会有所不同、(我怀疑)这不是您现在想要做的实验。

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

    大家好、Bruce 和所有论坛专家、

    如果有任何人有 LDC1101的演示代码、您可以给我一个链接、因为我在这件事上遇到了很多问题、所以这对我很有帮助。 如果有人想开发某种产品、应将源代码提供给公共部门或其他将 LDC 与定制 PCB 搭配使用的人员。

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

    感谢您的回复和 Aslo 的建议

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

    如果您愿意放弃使用中断(您也希望加快 SPI 速度、尽管这并非严格要求)、我建议您使用此处讨论的"spix()"(SPI-exchange)函数:

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/758000/2800722