Part Number:MSP430FR5994Other Parts Discussed in Thread:LDC1612, TMP102,
我在使用库函数,430作为主机读取LDC1612从机的数据,当函数执行到EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);时一直处于卡在 while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG)) ;
我使用示波器查看了下,卡在这里时SCL一直处于拉低状态,但是我使用单个字节读取的函数一切是正常的。
以下是我的配置和正在调试的代码片段,其他的内容还包括一个UART和一个外部触发中断。
void IIC_init(void){ EUSCI_B_I2C_initMasterParam iic_param = {0}; iic_param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK; iic_param.i2cClk = CS_getSMCLK(); iic_param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS; iic_param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; iic_param.byteCounterThreshold = 1; EUSCI_B_I2C_initMaster(EUSCI_B2_BASE, & iic_param); //set slave address EUSCI_B_I2C_setSlaveAddress(EUSCI_B2_BASE, LDC_ADDRESS); //使能IIC EUSCI_B_I2C_enable(EUSCI_B2_BASE); //清除IIC中断 EUSCI_B_I2C_clearInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT); // //Enable master interrupt // EUSCI_B_I2C_enableInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0); while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE)); printf("I2C in Master mode initial finish!\r\n"); return; }
void IIC_Read_Bytes(uint8_t RegAddr, uint8_t length){ i2c_rx_buf_len = length; uint8_t data1,data2; while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE)); EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_MODE); EUSCI_B_I2C_masterSendSingleByte(EUSCI_B2_BASE, RegAddr); //receive EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_MODE); //Init iic send data and stati EUSCI_B_I2C_masterReceiveStart(EUSCI_B2_BASE); data1 = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE); data2 = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE); }
Susan Yang:
上传代码的话,请您使用该回复框下的“插入”–>代码 来插入,以方便阅读
另外您使用的是launchpad还是自己的板子?
之前有类似的讨论,您也可以先看一下
https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/437554/launchpad-msp430fr5969-i2c-driverlib-hangs-on-while-hwreg16-baseaddress-ofs_ucbxifg-ucrxifg
,
Huan Zhang:
新技能get,我所使用的是FR5994 launchpad, 一部分原因我找到了,在配置IIC的IO口时,我使用的是:
GPIO_setAsPeripheralModuleFunctionOuttPin(GPIO_PORT_P7, GPIO_PIN0+GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
应该配置为
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0+GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);
现在问题中
->EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);
已经可以执行完成了,但是在执行完这一行后,我认为主机应当释放IIC总线控制权,但是此时SCL一直是拉低的,第二次执行读取任务的时候就会卡在IIC BUSY的检测上。
附现在调试的代码
void IIC_Read_Bytes(uint8_t RegAddr, uint8_t length){ uint8_t data1,data2;
while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));
EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_MODE);
EUSCI_B_I2C_masterSendSingleByte(EUSCI_B2_BASE, RegAddr);
//receive
EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_MODE);
EUSCI_B_I2C_masterReceiveStart(EUSCI_B2_BASE);
data1 = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);
data2 = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);
printf("x%x,%x",data1,data2);
return ;
}
,
Susan Yang:
请您看一下下面的链接,和您的问题相似
https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/581257/ccs-msp430fr5969-problem-to-read-temperature-in-tmp102-using-i2c-usci_b?tisearch=e2e-sitesearch&keymatch=TMP102
若还是不能解决问题,请附上相关的代码和时序波形,我们具体看一下
,
Huan Zhang:
您好,对于上面链接中提到的,我都进行了尝试,但是都不成功,总结一个最接近成功的例子。
我使用MSP430FR5994读取LDC1612的manufacture_id,器件地址是0X2A,正常通信的话,第一个8bits返回0x54,第二个8bits返回0x49.
IIC配置代码如下:
void IIC_init(void){//set the I2C IOGPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0+GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);EUSCI_B_I2C_initMasterParam iic_param = {0};iic_param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;iic_param.i2cClk = CS_getSMCLK();iic_param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;iic_param.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;iic_param.byteCounterThreshold = 1;EUSCI_B_I2C_initMaster(EUSCI_B2_BASE, & iic_param);//set slave addressEUSCI_B_I2C_setSlaveAddress(EUSCI_B2_BASE, LDC_ADDRESS);//使能IICEUSCI_B_I2C_enable(EUSCI_B2_BASE);//清除IIC中断EUSCI_B_I2C_clearInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT); ////Enable master interrupt //EUSCI_B_I2C_enableInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));printf("I2C in Master mode initial finish!\r\n");return; }使用外部按键,以按键中断的方式读取一次数据。IIC的读取代码如下:
uint16_t IIC_Read_Bytes(uint8_t RegAddr, uint8_t length){i2c_rx_buf_len = length;uint8_t data1,data2;uint16_t data_test;while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_MODE);EUSCI_B_I2C_masterSendSingleByte(EUSCI_B2_BASE, RegAddr);//receiveEUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_MODE);EUSCI_B_I2C_masterReceiveStart(EUSCI_B2_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));data1 = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);data2 = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B2_BASE);EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));data_test = data1<<8 | data2;return data_test; }我测试了下,会出现两种错误:
此种状态下,第二帧数据直接不读取,但主机释放IIC,可以正常退出中断,读取的返回值是0x54,也就是只读取第一个8Bits数据。
还可能出现一种错误:
此种状态下,读取了第二帧数据,但是最后一帧的数据时钟缺两个,也没有NACK及STOP信号,IIC时钟直接没了,我打断点测试中间是卡在了这一行: data2 = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);
以上两种情况都可能发生
其他的例如使用上面提到的自己成功的代码:
uint16_t IIC_Read_Bytes(uint8_t RegAddr, uint8_t length){i2c_rx_buf_len = length;uint8_t data1,data2;uint16_t data_test;while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_MODE);EUSCI_B_I2C_masterSendSingleByte(EUSCI_B2_BASE, RegAddr);//receiveEUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_MODE);EUSCI_B_I2C_masterReceiveStart(EUSCI_B2_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));data1 = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B2_BASE);data2 = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B2_BASE);EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B2_BASE);EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);/*data1 = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE);data2 = EUSCI_B_I2C_masterReceiveMultiByteFinish(EUSCI_B2_BASE);EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B2_BASE);EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));*/data_test = data1<<8 | data2;return data_test; }第一种问题,接收的数据虽然是正常的,但是后面带尾巴,返回的数据不对。
第二种情况:波形是正常的,但是单片机直接死机,按复位都不行,只能强制断电重启才可以。
以上,IIC硬件使用4.7K电阻上拉。
,
Susan Yang:
谢谢您的详细反馈。由于条件限制,我这周都无法在实验室测试。若是您比较急的话,请您直接在英文E2E发帖
https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum
,
Huan Zhang:
非常感谢您,我先在E2E上提问试试,再用别的MCU尝试下,如果有进展的话我也会及时在此问题下更新。
,
Susan Yang:
谢谢您的理解,很抱歉未能帮到您。期待您的反馈!
,
Huan Zhang:
hello,我来交作业来了。
我再仔细的核对了下库函数和寄存器及例程,最后找到了一个比较稳定的解决方案。
首先说明问题,我在配置IIC的时候,设置的是没有不会自动产生STOP信号,所以在byteCounterThreshold设置了1,逻辑上似乎是不会产生问题,但是就是因为这个问题导致的接收只接收了MSB的数据而丢失了LSB的数据。以下是我修改后的设置。
void IIC_init(void){//set the I2C IOGPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P7, GPIO_PIN0+GPIO_PIN1, GPIO_PRIMARY_MODULE_FUNCTION);EUSCI_B_I2C_initMasterParam iic_param = {0};iic_param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;iic_param.i2cClk = CS_getSMCLK();iic_param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;iic_param.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;iic_param.byteCounterThreshold = 0x02;EUSCI_B_I2C_initMaster(EUSCI_B2_BASE, &iic_param);//set slave addressEUSCI_B_I2C_setSlaveAddress(EUSCI_B2_BASE, SLAVE_ADDRESS);//使能IICEUSCI_B_I2C_enable(EUSCI_B2_BASE);//清除IIC中断EUSCI_B_I2C_clearInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0 + EUSCI_B_I2C_BYTE_COUNTER_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT); ////Enable master interrupt //EUSCI_B_I2C_enableInterrupt(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));printf("I2C in Master mode initial finish!\r\n");return; }主要改动点是设置为接收2帧数据后自动产生STOP信号。
接收数据的代码修改为:
uint16_t IIC_Read_Bytes(uint8_t RegAddr, uint8_t length){i2c_rx_buf_len = length;uint8_t data1,data2;uint16_t data_test;while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));EUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_MODE);EUSCI_B_I2C_masterSendSingleByte(EUSCI_B2_BASE, RegAddr);//receiveEUSCI_B_I2C_setMode(EUSCI_B2_BASE, EUSCI_B_I2C_RECEIVE_MODE);EUSCI_B_I2C_masterReceiveStart(EUSCI_B2_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));data1 = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B2_BASE);data2 = EUSCI_B_I2C_masterReceiveSingle(EUSCI_B2_BASE);EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B2_BASE);EUSCI_B_I2C_masterIsStopSent(EUSCI_B0_BASE);while(EUSCI_B_I2C_isBusBusy(EUSCI_B2_BASE));data_test = data1<<8 | data2;return data_test; }我试过将autoSTOPGeneration 设置为 EUSCI_B_I2C_NO_AUTO_STOP
但是首次接收时,MSP多读取了一帧,虽然IIC释放了总线,但是后面读取的数据都是错误的。
此问题虽然没能彻底搞清楚,但至少暂时能继续前进了,非常感谢Susan。
,
Susan Yang:
很高兴您能解决问题,也非常感谢您的详细反馈!相信会对之后遇到类似问题的工程师有很大帮助