|
【NXP Rapid IoT评测】I2C程序小bug
[复制链接]
上一篇 解决了I2C死锁解除的方法,
【NXP Rapid IoT评测】触摸按键没有反应——I2C死锁解除方法
https://bbs.eeworld.com.cn/forum ... 1480&fromuid=194541。
但是总线上挂载的外设多时,有时会遇到外设失灵的情况,后来深入分析代码,出现问题在于
ATMO_Platform_I2C_Master_Transfer 这个函数上
- static ATMO_I2C_Status_t ATMO_Platform_I2C_Master_Transfer(
- i2c_direction_t direction, kI2C_Blocking_t blocking, uint32_t instance,
- uint16_t slaveAddress, const uint8_t* cmdBytes, uint16_t numCmdBytes,
- uint8_t* dataBytes, uint16_t numDataBytes) {
- status_t platformStatus = kStatus_Fail;
- i2c_master_transfer_t masterStructure;
- uint32_t cmd;
- if (instance > MK64F_NUM_I2C_INSTANCES) {
- return ATMO_I2C_Status_NotSupported;
- }
- if (ATMO_Platform_I2C_Peripheral[instance].operatingMode
- == ATMO_I2C_OperatingMode_Slave) {
- return ATMO_I2C_Status_Invalid;
- }
- if (numCmdBytes > 4) {
- return ATMO_I2C_Status_NotSupported;
- }
- if ((dataBytes == NULL) || (numDataBytes == 0)) {
- return ATMO_I2C_Status_Invalid;
- }
- // if either cmdBytes or numCmdBytes is null/zero then set both to null/zero
- if (cmdBytes == NULL) {
- numCmdBytes = 0;
- } else if (numCmdBytes == 0) {
- cmdBytes = NULL;
- }
- if (numCmdBytes == 1) {
- cmd = cmdBytes[0];
- } else if (numCmdBytes == 2) {
- cmd = (cmdBytes[0] << 8) | cmdBytes[1];
- } else if (numCmdBytes == 3) {
- cmd = (cmdBytes[0] << 16) | (cmdBytes[1] << 8) | cmdBytes[2];
- } else if (numCmdBytes == 4) {
- cmd = (cmdBytes[0] << 24) | (cmdBytes[1] << 16) | (cmdBytes[2] << 8)
- | cmdBytes[3];
- }
- masterStructure.flags = kI2C_TransferDefaultFlag;
- masterStructure.slaveAddress = slaveAddress;
- masterStructure.direction = direction;
- masterStructure.subaddress = cmd;
- masterStructure.subaddressSize = numCmdBytes;
- masterStructure.data = dataBytes;
- masterStructure.dataSize = numDataBytes;
- if (blocking == kI2C_Blocking) {
- //ATMO_PLATFORM_DebugUsbPrint("ATMO_Platform_I2C_Master_Transfer kI2C_Blocking\r\n");
- [color=#ff0000] platformStatus = I2C_MasterTransferNonBlocking(peripheralBase[instance],
- &masterHandle[instance], &masterStructure);
- uint32_t timeoutCounter = ATMO_I2C_TIMEOUT;
- for (int i = 0; i < 1000; i++) {
- }
- while ((peripheralBase[instance]->S) & I2C_S_BUSY_MASK
- && (timeoutCounter > 0)) {
- timeoutCounter--;[/color]
- }
- if (timeoutCounter == 0) {
- //ATMO_PLATFORM_DebugUsbPrint("ATMO_Platform_I2C_Master_Transfer ATMO_I2C_Status_Timeout\r\n");
- return ATMO_I2C_Status_Timeout;
- }
- } else {
- platformStatus = I2C_MasterTransferNonBlocking(peripheralBase[instance],
- &masterHandle[instance], &masterStructure);
- }
- //ATMO_PLATFORM_DebugUsbPrint("I2C_Master_Transfer Address:%d Status:%d \r\n",slaveAddress,platformStatus);
- return ATMO_Platform_I2C_Convert_Status_PlatformToAtmo(platformStatus);
- }
复制代码
在kI2C_Blocking 读写模时 并非是阻塞式等待I2C结果的,仅仅是延时等等吧了for (int i = 0; i < 1000; i++) {
}对于120Mhz 的系统时钟,对于100Kpb的I2C实在时太少了。
同时(peripheralBase[instance]->S) & I2C_S_BUSY_MASK语句仅用共同启动I2C时才会出现。
所以代码,应该修改成如下
- if (blocking == kI2C_Blocking) {
- //ATMO_PLATFORM_DebugUsbPrint("ATMO_Platform_I2C_Master_Transfer kI2C_Blocking\r\n");
- nakFlag[instance] = false;
- completionFlag[instance] = false;
- platformStatus = I2C_MasterTransferNonBlocking(peripheralBase[instance],
- &masterHandle[instance], &masterStructure);
- #if 0
- uint32_t timeoutCounter = ATMO_I2C_TIMEOUT;
- for (int i = 0; i < 1000; i++) {
- }
- while ((peripheralBase[instance]->S) & I2C_S_BUSY_MASK
- && (timeoutCounter > 0)) {
- timeoutCounter--;
- }
- if (timeoutCounter == 0) {
- //ATMO_PLATFORM_DebugUsbPrint("ATMO_Platform_I2C_Master_Transfer ATMO_I2C_Status_Timeout\r\n");
- return ATMO_I2C_Status_Timeout;
- }
- #else
- /* wait for transfer completed. */
- while ((!nakFlag[instance]) && (!completionFlag[instance])) {
- }
- nakFlag[instance] = false;
- if (completionFlag[instance] == true) {
- completionFlag[instance] = false;
- //ATMO_PLATFORM_DebugUsbPrint(" 0x%x", masterXfer.slaveAddress);
- } else {
- return ATMO_I2C_Status_Timeout;
- }
- #endif
- }
复制代码
同时在中断回调函数上添加以下代码
- static void ATMO_Platform_I2C_Master_Callback(I2C_Type* base,
- i2c_master_handle_t* handle, status_t status, void* userData) {
- ATMO_I2C_MasterTransfer_t masterXfer;
- uint32_t instance = I2C_GetInstance(base);
- ATMO_I2C_Master_Callback_t callback =
- ATMO_Platform_I2C_Peripheral[instance].cbFunc;
- size_t xferCount;
- /* Signal transfer success when received success status. */
- if (status == kStatus_Success) {
- completionFlag[instance] = true;
- if ((handle->transfer.direction == kI2C_Read)
- && (status == kStatus_Success)) {
- I2C_MasterTransferGetCount(base, handle, &xferCount);
- masterXfer.event = ATMO_I2C_MasterEvent_Complete;
- masterXfer.data = handle->transfer.data - xferCount;
- masterXfer.dataSize = xferCount;
- if (callback != NULL) {
- callback(&masterXfer, userData);
- }
- } else {
- if (callback != NULL) {
- callback(&masterXfer, userData);
- }
- }
- }
- /* Signal transfer failure when received any other status. */
- if ((status == kStatus_I2C_Nak) || (status == kStatus_I2C_Addr_Nak)
- || (status == kStatus_I2C_ArbitrationLost)
- || (status == kStatus_I2C_Timeout)) {
- nakFlag[instance] = true;
- }
- }
复制代码
实现阻塞为读写。
同时提供一个扫描I2C总线上设备的代码
- ATMO_I2C_Status_t ATMO_I2C_Scan(ATMO_DriverInstanceHandle_t instance)
- {
- uint8_t cmdBuf[2]={0};
- uint8_t readBuf[1]={0};
- uint8_t slaveAddress=0;
- ATMO_I2C_Status_t status=ATMO_I2C_Status_Unknown;
- ATMO_PLATFORM_DebugUsbPrint("Driver On I2C%d Line:\r\n ",instance);
- for(slaveAddress= 0x00;slaveAddress<=0x0f;slaveAddress++){
- ATMO_PLATFORM_DebugUsbPrint(" %02x",slaveAddress);
- }
- //ATMO_PLATFORM_DebugUsbPrint("\r\n __",0);//slaveAddress == 0; 不存在
- for(slaveAddress= 0x00;slaveAddress<=0x7f;slaveAddress++){
- status = ATMO_I2C_MasterRead(instance,slaveAddress,cmdBuf,0,readBuf,1,1000);
- //status = ATMO_I2C_MasterWrite(instance,slaveAddress,cmdBuf,0,readBuf,1,1000);
- if(slaveAddress%16==0){
- ATMO_PLATFORM_DebugUsbPrint("\r\n0x%02X",(slaveAddress/16)*16);
- }
- if(status != ATMO_I2C_Status_Success){
- ATMO_PLATFORM_DebugUsbPrint(" __");
- }else{
- ATMO_PLATFORM_DebugUsbPrint(" %02x",slaveAddress);
- }
- }
- ATMO_PLATFORM_DebugUsbPrint("\r\n");
- return ATMO_I2C_Status_Success;
- }
复制代码
挂在总线上的外设都能正常读取地址
MPL3115Pressure 0x60
TSL2572AmbientLight 0x39
CCS811AirQuality 0x5A
SX9500Touch 0x28
FXAS21002Gyroscope 0x20
ENS210TemperatureHumidity 0x43
FXOS8700AccelerometerMagnetometer 0x1E
此内容由EEWORLD论坛网友dvd1478原创,如需转载或用于商业用途需征得作者同意并注明出处
|
|