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:在不使用中断的情况下重复启动读取多个字节的数据 i2c

Guru**** 2549060 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/589712/msp430fr5969-read-multiple-bytes-of-data-i2c-with-repeated-start-and-without-interrupts

器件型号:MSP430FR5969

我构建了两个函数、用于使用 eusci i2c 接口读取和写入单个字节。
我找不到任何不使用中断的示例、因此我构建自己的中断。
我使用逻辑分析仪进行了很多调试、但现在它们工作正常。

OID i2c_init(){

P1SEL1 |= BIT6 | BIT7; //配置 I2C 引脚
P1SEL0 &=~(BIT6 | BIT6); //配置 I2C 引脚

// I2C 默认使用 SMCLK
UCB0CTL1 |= UCSWRST; //将 eUSCI_B 置于复位状态
UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;// I2C、主器件、SYNC
UCB0BRW = 0x000A; //波特率= SMCLK / 10 = 100kHz
UCB0CTL1 &=~UCSWRST; // eUSCI_B 处于运行状态
}

void i2c_write (uint8_t SLV_addr、uint8_t reg_addr、uint8_t data){

while (UCB0STAT 和 UCBBUSY);

UCB0I2CSA = SLV_addr; //设置从器件地址
UCB0CTLW0 |= UCTR | UCTXSTT; //发送器模式和启动条件。

while (UCB0CTLW0和 UCTXSTT);
UCB0TXBUF = REG_addr;
while (!(UCB0IFG & UCTXIFG0));
UCB0TXBUF =数据;
while (!(UCB0IFG & UCTXIFG0));

UCB0CTLW0 |= UCTXSTP;
while (UCB0CTLW0和 UCTXSTP); //等待停止
}

uint8_t i2c_read (uint8_t SLV_addr、uint8_t reg_addr){

uint8_t data = 0;

while (UCB0STAT 和 UCBBUSY);
UCB0I2CSA = SLV_addr; //设置从器件地址
UCB0CTLW0 |= UCTR | UCTXSTT; //发送器模式和启动条件。

while (UCB0CTLW0和 UCTXSTT);
UCB0TXBUF = REG_addr;
while (!(UCB0IFG & UCTXIFG0));

UCB0CTLW0 &=~UCTR; //接收器模式
UCB0CTLW0 |= UCTXSTT; //起始条件

while (UCB0CTLW0和 UCTXSTT); //确保已清除启动
UCB0CTLW0 |= UCTXSTP; //停止条件
while (!(UCB0IFG & UCRXIFG0));
数据= UCB0RXBUF;

while (UCB0CTLW0和 UCTXSTP);

返回数据;
} 

我发现调试一次读写操作时、所有"指令"都应按照正确的顺序工作、使其稳定。
但是、某些传感器要求您在不使用中间停止的情况下读取多个寄存器。
因为如果您尝试逐字节读取它们、那么在读取第一个字节后、新数据将存储在寄存器中。

根据我的理解:
-停止和重复启动都会自动发送一个 NACK,而不是 ACK
- while (UCB0STAT 和 UCBBUSY);只要总线忙、就等待。 (因此不应使用重复启动来检查此项?)

我应该如何修改我的单个读取函数、以便它能够读取多个字节?
我尝试了一些操作、但应该何时发送重复起始? 在与 STOP 相同的位置?  

理想情况下、我希望具有如下函数:

uint8_t i2c_read_multi(uint8_t SLV_addr、uint8_t reg_addr、uint8_t l、uint8_t arr*){}

l 表示要读取的字节数,arr*表示大小为 l 的数组的指针

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

    我自己弄明白了。

     当您希望读取新字节时、不需要发送重新启动。

    读取后、每个传感器都会自动递增寄存器地址。

    因此、只需在环路中进行读取:

    void i2c_read_multi(uint8_t SLV_addr、uint8_t reg_addr、uint8_t l、uint8_t *arr){
    
    uint8_t i;
    
    while (UCB0STAT 和 UCBBUSY);
    
    UCB0I2CSA = SLV_addr; //设置从地址
    
    UCB0CTLW0 |= UCTR | UCTXSTT; //发送器模式和启动条件。
    
    while (UCB0CTLW0 & UCTXSTT);
    
    UCB0TXBUF = reg_addr;
    
    while (!(UCB0IFG & UCTXIFG0));
    
    UCB0CTLW0 &=~UCTR; //接收器模式
    
    UCB0CTLW0 |= UCTXSTT; //起始条件
    
    while (UCB0CTLW0 & UCTXSTT); //确保已清除
    
    (i = 0;i < l;i++){的启动
    
    while (!(UCB0IFG & UCRXIFG0));
    
    if (i = l - 1){
    
    UCB0CTLW0 |= UCTXSTP; //停止条件
    
    }
    
    ARR[i]= UCB0RXBUF;
    
    }
    
    while (UCB0CTLW0 & UCTXSTP);
    
    } 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我很高兴看到您找到了问题的答案、感谢您跟进并发布解决方案。

    此致、
    Ryan