您好!
我已经编写了自己的代码、用于通过 i2c 读取和写入单个字节(不使用中断)、这是可以正常工作的。
对于某些传感器、您需要连续读取多个寄存器而不会停止、否则数据将被丢弃。
我遇到以下问题:
-首次(编程后)当一个多次读取被执行时、它还在 RXBUF 中存储一个额外的字节。
那么、假设我要读取寄存器0x01直到0x04、它还会将0x05中的字节存储在 RXBUF 中。
这会导致我的代码在第一次多次读取后读取"错误"字节。
下一次单次读取将读取仍存储在 RXBUF 中的错误"旧"字节。
因此、如果是单次读取、则第一次多读之后的所有读取都是错误的、如果是多读、则从错误的字节开始移位。
我通过在成功停止后额外读取 RXBUF 来修复此问题。
这对我来说真的很奇怪、如果没有"修复"、只会读取第一个多读操作的额外字节。
我的代码中是否存在故障或此修复是否确实必要???
#include #include #include "eusci_b0_i2c.h" void 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); 返回数据; } void i2c_read_multi(uint8_t SLV_addr、uint8_t reg_addr、uint8_t l、uint8_t *arr){ uint8_t i; volatile uint8_t del; 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); //第一次使用多读时,返回一个额外的寄存器字节。 //这会连续读取、读取"旧"数据。 if (UCB0IFG & UCRXIFG0){ DEL = UCB0RXBUF; } }