工具与软件:
之前、在以8MHz 的频率使用内部生成的时钟的 I2C 外设时、该外设没有问题、从我的可观察用例来看、它按预期运行。
切换到使用16MHz 的外部 HFXT 输入、设置 SMCLK 和 MCLK 以使用具有2分频因子的 HFXT 输入。 (8MHz)。 我的 I2C 外设不再可靠工作。
在初始化后执行以下序列时出现此问题:
注意:
下面显示的宏是针对目标寄存器的读取和写入位
// First write to slave device WRITE_REG(hi2c_.reg->I2CSA, dev_address); // Send start, and configure to send slave address SET_BIT(hi2c_.reg->CTLW0, UCTR + UCTXSTT); // Wait until address has been sent while (READ_BIT(hi2c_.reg->CTLW0, UCTXSTT)) ;
上面的代码片段 会发送 从器件 IC 地址和块、直到发送启动条件为止
之后、我会尝试在发送地址后向总线写入一个字节。
WRITE_REG(instance->reg->TXBUF, (uint8_t)(reg_address & (uint16_t)0x00FF)); while (READ_BIT(instance->reg->IFG, UCTXIFG0) == 0);
这是尝试在 I2C 外设停止工作的地址之后写入一个字节的情况。
在探测线路时、每次都正确发送地址。
监控 STATW 寄存器、我确实看到在预期的运行下、它会报告以下内容
已传输1字节
UCSCLLOW 被激活
UCBBUSY 忙
请求通过 I2C 总线发送的所有序列字节也会进行发送、而不会出现任何问题。
OFF 的标称行为显示了相反的情况
传输0字节
UCSCLLOW 未激活
UCBBUSY 未忙
时钟设置代码
void setup_clock() { // Configure DCO to 8 MHz (CPU clock speed) WRITE_REG(CSCTL0_H, CSKEY >> 8); // Unlock CS registers WRITE_REG(CSCTL3, DIVA__1 | DIVS__2 | DIVM__2); WRITE_REG(CSCTL1, DCOFSEL_2 | DCORSEL); // Set DCO to 8 MHz // Enable external HXFT operation and configure LFXT to not be utilized SET_BIT(CSCTL4, HFXTBYPASS | HFXTDRIVE_3 | HFFREQ_2 | LFXTOFF); // Configure ACLK = VLOCLOCK ~ 10kHz, SMCLK = HFXT, MCLK = HFXT WRITE_REG(CSCTL2, SELA__VLOCLK | SELM__HFXTCLK | SELS__HFXTCLK); // Ensure to configure HFXT to use external input clock CLEAR_BIT(CSCTL4, HFXTOFF); // Disable startup fault counter for both HFXT and LFXT CLEAR_BIT(CSCTL5, ENSTFCNT2 | ENSTFCNT1); // Test oscillator fault flag, wait till HFXT clock switch over is complete while (SFRIFG1 & OFIFG) { CSCTL5 &= ~(HFXTOFFG | LFXTOFFG); // Clear XT1 and XT2 fault flag SFRIFG1 &= ~OFIFG; } CLEAR_REG(CSCTL0_H); // Lock CS registers }
void i2c_b1_init(PIL::I2C_t *instance) { /* * P3DIR P3SEL1 P3SEL0 * P3.1 SDA X 0 1 * P3.2 SCL X 0 1 */ P3SEL0 |= BIT1 | BIT2; instance->reg = (PIL::MSP430FR5989_I2C_reg_t *)eUSCI_B1_BASE_ADDRESS; // Disable peripheral WRITE_REG(instance->reg->CTLW0, UCSWRST); // see family user guide example 32-1 SET_BIT(instance->reg->CTLW0, UCMST | UCMODE_3 | UCSSEL__SMCLK | UCSYNC); // Desired output frequency 100khz WRITE_REG(instance->reg->BRW, 0x4F); // Enable peripheral CLEAR_BIT(instance->reg->CTLW0, UCSWRST); }