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.

[参考译文] MSP430F5242:I2C Driverlib、重复启动条件

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/733018/msp430f5242-i2c-driverlib-repeated-start-condition

器件型号:MSP430F5242

您好!

我尝试切换到 USCI_B I2C Driverlib、我注意到我无法重现干净的重复启动条件(例如、从从器件读取一个字节)。 如果我用示波器观察波形、我可以看到 SDA 线路在上升和下降、甚至没有达到3V3电平。 也许对于我正在使用的 i2c 从器件来说已经足够了(它可以正常工作、我接收到正确的字节)、但我正在尝试确定这是否代表潜在的错误原因。

以下是代码段(带和不带 driverlib):

   

//测试 RGB (制造商 ID = 0xE0)
   USCI_B_I2C_setSlaveAddress (USCI_B0_BASE、RGBFR_ADDR);

   IF (USCI_B_I2C_masterSendSingleByteWithTimeout (USCI_B0_BASE、Manufacturer_ID、20000))
   {
       IF (USCI_B_I2C_masterReceiveSingleStartWithTimeout (USCI_B0_BASE、20000))
       {
           receivedMsg = USCI_B_I2C_masterReceiveSingle (USCI_B0_BASE);
       }
   }
   if (receivedMsg=0xE0) peripherals |= RGB_FRECCE;
   receivedMsg=0;

这是我在没有 driverlib 的情况下生成的函数、被称为"I2C_Receive_Single_Byte (RGBFR_ADDR、Manufacturer_ID)"

char I2C_Receive_Single_Byte (char Slave_Address、char RegAddr)

   char received_data=0x00;

   UCB0I2CSA = Slave_Address;                     //地址分配
   UCB0IFG &=~ UCTXIFG;                           //标志清零
   UCB0CTL1 |= UCTR + UCTXSTT;                    // I2C TX、启动条件
   while (!(UCB0IFG&UCTXIFG));                     // while Flag=0 (UCTXIFG=1当生成 START 时、可以写入数据)
   UCB0IFG &=~ UCTXIFG;                           //标志清零

   UCB0TXBUF = RegAddr;                           //数据(要读取的寄存器)加载

   while (((UCB0CTL1&UCTXSTT)                      )// while start not ack'ed
   {
       if (UCB0IFG&UCNACKIFG)                      // if NACK,发出 STOP 和 EXIT
       {
           UCB0IFG &=~ UCNACKIFG;
           UCB0CTL1 |= UCTXSTP;
           返回1;
       }
   }

   UCB0CTL1 &=~ UCTR;             //准备接收
   UCB0IFG &=~(UCTXIFG+UCRXIFG); //标志清零
   UCB0CTL1 |= UCTXSTT;           //发出重复起始


   while (UCB0CTL1&UCTXSTT)        // while start not ack'ed
   {
       if (UCB0IFG&UCNACKIFG)      // if NACK,发出 STOP 和 EXIT
       {
           UCB0CTL1 |= UCTXSTP;
           返回1;
       }
   }

   UCB0CTL1 |= UCTXSTP;
   while (!(UCB0IFG&UCRXIFG));     //未接收字节
   Received_data = UCB0RXBUF;     //读取并保存

   _delay_cycles (10000);
   返回 Received_data;          //自描述


我是否应该在 driverlib 中引入某种额外的轮询? 我什么都不担心?

谢谢!

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

    您好!

    您能否分享示波器图? 通常、SDA 线路应具有1kOhm 至10kOhm 的上拉电阻器。 通常、我们建议使用4.7kOhm。 如果您说 SDA 未达到3.3V、则 SDA 上似乎有太大的电容。 您能检查一下吗?  

    您的发射频率是多少?

    您已将哪些上拉电阻连接到 SDA/SCL?

    请查看我们 的应用手册:" MSP430TM MCU 上常见 eUSCI 和 USCI 串行通信问题的解决方案"

    第5章介绍 I2C 通信。  

    此致、

    Andre

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

    很抱歉,现在我不能采取措施,但我记得我看到的情况。 我认为问题是 driverlib 函数设置 STP 位而不是起始位、从而产生奇怪的齿状、而不是重复的起始条件。

    这不是您可以看到的上拉问题(4k7)、我可能是误用了 driverlib

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

    这里是波形

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

    USCI_B_I2C_masterSendSingleByteWithTimeout ()执行一个完整的 μ I²C 传输、即、它生成一个停止条件。

    对于重复起始,您必须发送第一个字节,同时进行以下预处理(USCI_B_I2C_masterSendMultiByteStartWithTimeout ()),然后 在不先停止的情况下,只需开始接收 (USCI_B_I2C_masterReceive* Receive())。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢克莱明! 此代码工作正常、但我必须在内部添加延迟。 是否有可以替代延迟的轮询?

    IF (USCI_B_I2C_masterSendMultiByteStartWithTimeout (USCI_B0_BASE、Manufacturer_ID、20000))

    虚拟= 100;
    while (虚拟->5);
    IF (USCI_B_I2C_masterReceiveSingleStartWithTimeout (USCI_B0_BASE、20000))

    receivedMsg = USCI_B_I2C_masterReceiveSingle (USCI_B0_BASE);



    如果我移除延迟、i2c 模块输出的唯一波形为:START - 0x38 (SlaveAddr)- 0xFF (???????) -停止;其中0xFF 应为0x92。 我猜是因为第二个 USCI Driverlib 函数会在数据传输完成之前设置起始位。

    尝试轮询 UCBUSY 不起作用、也不使用 USCI_B_I2C_isBusy ()。 关于最后一个函数、在可以访问模块时、标志是否未设置、与之相反(如此处所示)? 我的意思是、如果 UCTXIFG 被置位、指南会说、如果它被置位、我可以在 UCxTXBUF 中写入另一个数据字节、 但是、如果我在使用此函数时不知道它的作用(我想可能会发生在某人身上)、我会遇到与我的意图相反的情况、例如:

    IF (USCI_B_I2C_masterSendMultiByteStartWithTimeout (USCI_B0_BASE、Manufacturer_ID、20000))

    while (USCI_B_I2C_isBusy ());
    IF (USCI_B_I2C_masterReceiveSingleStartWithTimeout (USCI_B0_BASE、20000))

    receivedMsg = USCI_B_I2C_masterReceiveSingle (USCI_B0_BASE);




    uint8_t USCI_B_I2C_isBusy (uint16_t baseAddress)

    //返回忙状态。
    if ((HWREG8 (baseAddress + OFS_UCBxIFG)&(UCTXIFG + UCRXIFG))){
    返回(USCI_B_I2C_BUS_BUS_BUSY);
    }否则{
    返回(USCI_B_I2C_BUS_NOT 忙);



    我弄错了吗? 再次感谢您、

    Mirco
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    简而言之、driverlib 函数中的标志是否反相? 我无法理解...

    谢谢!
    Mirco
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很明显、轮询 uctxifg 可以解决这个问题...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    置位 UCTXSTT 不会中止当前的传输(请参阅用户指南的图41-12)。

    isBusy()函数确实看起来是错误的。

    没有其他功能;等待 TXIFG 的唯一方法是手动执行。 (很明显、这是 driverlib 假定您正在使用中断的情况。)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    明白了!

    但为什么
    "如果我移除延迟、i2c 模块输出的唯一波形为:START - 0x38 (SlaveAddr)- 0xFF (???????) -停止;其中0xFF 应为0x92。" 然后
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好!


    我无法在这里评论确切的 DriverLib 配置、但如果您要传输0xFF 而不是所需的数据、则会发生以下三种情况之一。

    1) 1)您在 TxBuff 中放置0xFF 时不会意识到它
    2)在正确填充 TxBuff 及其传输其最后发送的内容之前,您传输的时间太短了
    3)您很快就填充了 TxBuff,并且可能会在缓冲区被发送出去之前损坏缓冲区。

    正如 Clemens 前面提到的、DriverLib 假定您正在为 I2C 使用中断、因此您需要等待 TXIFG 发生、以便正确填充 TxBuff。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好、Mirco、

    您对此主题还有其他疑问吗? 如果没有、请单击解决您问题的主题上的"已解决"按钮。

    此致、
    Andre