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.

[参考译文] MSP430F5529:I2C 停止标志时序问题

Guru**** 2595770 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1055085/msp430f5529-i2c-stop-flag-timing-issue

器件型号:MSP430F5529

我尝试通过 I2C 从温度传感器读取数据。 我设法启动并运行了通信、但我发现了一些奇怪的行为。  

我无法正确计时 STOP 标志、结果是我读取了大量数据。  

我的问题是,如何在第二个帧上发出停止标志,而不会因我 遇到的延迟而在第四个帧上发出停止信号?

上图显示了停止标志计时问题。 请注意、DIO2信号是在 STP 标志有效时发出的。 然后、在新的 I2C 事务开始时、我将 DIO2信号设置为零。  

为了清楚、我希望 I2C 结构如下所示:

| S |地址| R | A |数据| A |数据| NAK | P |

我要得到的结果:

| S |地址| R | A |数据| A |数据| A |不需要的数据| A |不需要的 数据| NAK | P |

代码:  

#include
#include

unsigned char RXData;
unsigned char TXData;
uint8_t RXByteCtr = 0;
uint8_t TXByteCtr = 0;

空 I2CInit (空)

P3REN |= 0x03;
P3OUT |= 0x03;
P3SEL |= 0x03;//将 I2C 引脚分配给 USCI_B0
UCB0CTL1 |= UCSWRST;//启用 SW 复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;// I2C 主器件、同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用 SMCLK、保持软件复位
UCB0BR0 = 10;// fSCL = SMCLK/10 = 100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x48;//从器件地址为048h
UCB0CTL1 &=~UCSWRST;//清除 SW 复位,恢复运行

空 I2CWriteInit (空)

UCB0CTL1 |= UCTR;
UCB0IFG &=~ UCTXIFG;
UCB0IE &=~ UCRXIE;
UCB0IE |= UCTXIE;

空 I2CReadInit (空)

UCB0CTL1 &=~ UCTR;
UCB0IFG &=~ UCRXIFG;
UCB0IE &=~ UCTXIE;
UCB0IE |= UCRXIE;

空 ReadTemp (空)

while (UCB0STAT 和 UCBBUSY);
P1OUT &=~BIT6;
RXByteCtr = 2;
I2CReadInit();
UCB0CTL1 |= UCTXSTT;

空 SetRegPtr (空)

while (UCB0STAT 和 UCBBUSY);
TXByteCtr = 1;
TXData = 0x00;
I2CWriteInit();  
UCB0CTL1 |= UCTXSTT;  

int main (空)

WDTCTL = WDTPW + WDTHOLD;

I2CInit();

P1DIR |= BIT6;
P1OUT &=~BIT6;


_enable_interrupt ();

SetRegPtr ();

while (1)

ReadTemp();

#pragma vector = USCI_B0_vector
_interrupt void USCI_B0_ISR (void)

switch (__evo_in_range (UCB0IV、12))

案例10:
IF (RXByteCtr -)  

RXData = UCB0RXBUF;  

其他  

UCB0CTL1 |= UCTXSTP;  
P1OUT |= BIT6;

中断;  
情况12:  
IF (TXByteCtr)  

UCB0TXBUF = TXData;  
TXByteCtr --;  

其他  

UCB0CTL1 |= UCTXSTP;  
UCB0IFG &=~UCTXIFG;

中断;
默认值:break;

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

    您有几个问题。 第一个是使用 RXByteCtr 上的后减量模式。 在第三个中断之前、if()不会选择您的 TXSTP 代码。

    第二个是读取 RXBUF 会释放硬件以继续、从而读取第四个字节。

    因此、在从 RXBUF 读取数据的最后一个字节之前、使用预递减并设置 TXSTP。

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

    就在 David 的钱上、感谢您的帮助。

    对中断进行的代码校正:

    案例10:
    IF (-RXByteCtr)

    UCB0CTL1 |= UCTXSTP;//<-这
    P1OUT |= BIT6;

    P1OUT |= BIT5;
    RXData = UCB0RXBUF;//<-在最后一帧之前
    中断;

    证明:

    我错过的 ROM 用户指南(p1007):

    "置位 UCTXSTP 会产生一个停止条件。 置位 UCTXSTP 后、在从器件接收到数据后会产生一个 NACK、然后是一个停止条件、如果 USCI 模块当前正在等待 UCBxRXBUF 被读取、则会立即产生一个 NACK。"