TI中文支持网
TI专业的中文技术问题搜集分享网站

MSP430FR5994: 使用库函数时硬件IIC主机接收多个数据问题。

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:

很高兴您能解决问题,也非常感谢您的详细反馈!相信会对之后遇到类似问题的工程师有很大帮助

赞(0)
未经允许不得转载:TI中文支持网 » MSP430FR5994: 使用库函数时硬件IIC主机接收多个数据问题。
分享到: 更多 (0)

© 2024 TI中文支持网   网站地图 鲁ICP备2022002796号-1