工具与软件:
之前、在以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);
}


