项目场景:

使用TMS320F28069的硬件I2C读取MPU6050的数据

问题描述

Uint16 I2CA_ReadBytes( Uint16 SlaveAddress, Uint16 RomAddress,Uint16 number, Uint16 *RamAddr)
{
Uint16 i,Temp;

if (I2caRegs.I2CSTR.bit.BB == 1) //返回总线忙错误状态
{
return I2C_BUS_BUSY_ERROR;
}
while(!I2CA_CheckTxReady());
I2caRegs.I2CSAR = SlaveAddress&0x00ff; //设备从地址
I2caRegs.I2CCNT = 1; //发送一个字节为要读取数据的寄存器地址
I2caRegs.I2CDXR = RomAddress&0x00ff;
I2caRegs.I2CMDR.all = 0x6620; //主机发送模式,自动清除停止位不产生停止信号
if (I2caRegs.I2CSTR.bit.NACK == 1) //送到无应答信号返回错误
return I2C_BUS_BUSY_ERROR;
DELAY_US(5);
while(!I2CA_CheckTxReady()); //调试过程中有时会卡在这一步,表示通讯不正常
I2caRegs.I2CSAR = SlaveAddress&0x00ff;
I2caRegs.I2CCNT = number;
I2caRegs.I2CMDR.all = 0x6C20; //主机接受模式,包含有停止信号
if (I2caRegs.I2CSTR.bit.NACK == 1)
return I2C_BUS_BUSY_ERROR;
for(i=0;i<number;i++)
{
while(!I2CA_CheckRecieveOk());
Temp = I2caRegs.I2CDRR;
if (I2caRegs.I2CSTR.bit.NACK == 1)
return I2C_BUS_BUSY_ERROR;
*RamAddr = Temp;
RamAddr++;
}
return I2C_SUCCESS; //接受数据成功
}
读取数据,调试单步调试代码运行正常,但是全速运行就一直卡在 while(!I2CA_CheckTxReady()); 这一句,或者返回I2C_BUS_BUSY_ERROR。

原因分析:

调试通过说明主从机的时序对上,在查询标志位的时候出错了。查看代码I2CA_CheckTxReady(),发现原来的写法是:
Uint16 I2CA_CheckTxReady(void)
{
Uint16 t,;
t = I2caRegs.I2CSTR.bit.XRDY; // IIC模块发送准备OK
return t;
}
我猜测可能是因为函数出入时间较短,导致I2caRegs.I2CSTR.bit.XRDY寄存器的数据总线一直被占用了,硬件无法更新该标志位。

解决方案:

降低查询速率
Uint16 I2CA_CheckTxReady(void)
{
Uint16 t,i;
t = I2caRegs.I2CSTR.bit.XRDY; // IIC模块发送准备OK
for(i=5;i>0;i–);//添加延时
return t;
}
对于函数I2CA_CheckRecieveOk()同理同样操作,bug就解决了

下面是IIC源码

//###########################################################################
// $ 函数名称:    void I2CA_Init(void)                            $
// $ 函数功能:    IIC模块初始化,设置IIC模块的功能引脚以及设置IIC的工作方式                             $
//###########################################################################
void I2CA_Init(void)
{I2caRegs.I2CMDR.all = 0x0000;   // 复位IICEALLOW;GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;    // 使能(SDAA)上拉GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;    // 使能 (SCLA)上拉GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3;  // 同步 (SDAA)GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;  // 同步 (SCLA)GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1;   // 配置 GPIO32为 SDAAGpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;   // 配置GPIO33 为SCLAEDIS;// 预分频——时钟模块的频率I2caRegs.I2CPSC.all = 7; // 预分频 IIC模块时钟需设置为7-12MHz,本实验设置为 (80/8 = 10MHz)I2caRegs.I2CCLKL = 10;   //时钟低电平时间值I2caRegs.I2CCLKH = 5;    //时钟高电平时间值I2caRegs.I2CMDR.all = 0x0020;   // IIC准备就绪DELAY_US(100000);
}//###########################################################################
// $ 函数名称:    Uint16    I2CA_CheckTxReady()                        $
// $ 函数功能:    IIC模块发送准备OK                              $
//###########################################################################
Uint16  I2CA_CheckTxReady(void)
{Uint16  t,i;t = I2caRegs.I2CSTR.bit.XRDY;   // IIC模块发送准备OKfor(i=5;i>0;i--);return t;
}//###########################################################################
// $ 函数名称:    Uint16    I2CA_CheckRecieveOk()                      $
// $ 函数功能:    IIC模块接收准备OK                              $
//###########################################################################
Uint16  I2CA_CheckRecieveOk(void)
{Uint16  t,i;t = I2caRegs.I2CSTR.bit.RRDY;   //  IIC模块接收准备OKfor(i=5;i>0;i--);return t;
}//###########################################################################
// $ 函数名称:    Uint16 I2CA_WriteBytes( Uint16  SlaveAddress, Uint16 RomAddress,Uint16 number, Uint8 *Wdata)        $
// $ 函数功能:    IIC写数据                                                       $
//###########################################################################
Uint16 I2CA_WriteBytes( Uint16 SlaveAddress, Uint16 RomAddress,Uint16 number, Uint8 *Wdata)
{Uint16 i;if (I2caRegs.I2CSTR.bit.BB == 1){return I2C_BUS_BUSY_ERROR;   //返回总线忙错误状态}while(!I2CA_CheckTxReady());      //等待数据发送就绪,XRDY=1,表明发送寄存器已经准备好接受新的数据I2caRegs.I2CSAR = SlaveAddress&0x00ff;    //设备从地址I2caRegs.I2CCNT = number + 1;   //需要发送的字节数I2caRegs.I2CDXR = RomAddress&0x00ff;    //第一个发送字节为发送数据的目标寄存器地址I2caRegs.I2CMDR.all = 0x6E20;    //发送起始信号,内部数据计数器减到0时,发送停止信号,主机发送模式,使能IIC模式,for (i=0; i<number; i++){while(!I2CA_CheckTxReady());   //等待数据发送就绪,发送下一个数据I2caRegs.I2CDXR = *Wdata&0xFF;Wdata++;if (I2caRegs.I2CSTR.bit.NACK == 1)    //送到无应答信号返回错误return    I2C_BUS_BUSY_ERROR;}return I2C_SUCCESS;         //发送成功
}//###########################################################################
// $ 函数名称:    Uint16 I2CA_ReadBytes( Uint16 SlaveAddress, Uint16 RomAddress,Uint16 number, Uint16  *RamAddr)       $
// $ 函数功能:    IIC读数据                                                       $
//###########################################################################
Uint16 I2CA_ReadBytes( Uint16 SlaveAddress, Uint16 RomAddress,Uint16 number, Uint16  *RamAddr)
{Uint16  i,Temp;if (I2caRegs.I2CSTR.bit.BB == 1)  //返回总线忙错误状态{return I2C_BUS_BUSY_ERROR;}while(!I2CA_CheckTxReady());I2caRegs.I2CSAR = SlaveAddress&0x00ff;      //设备从地址I2caRegs.I2CCNT = 1;        //发送一个字节为要读取数据的寄存器地址I2caRegs.I2CDXR = RomAddress&0x00ff;I2caRegs.I2CMDR.all = 0x6620;   //主机发送模式,自动清除停止位不产生停止信号if (I2caRegs.I2CSTR.bit.NACK == 1)    //送到无应答信号返回错误return  I2C_BUS_BUSY_ERROR;DELAY_US(5);while(!I2CA_CheckTxReady());                  //调试过程中有时会卡在这一步,表示通讯不正常I2caRegs.I2CSAR = SlaveAddress&0x00ff;I2caRegs.I2CCNT = number;I2caRegs.I2CMDR.all = 0x6C20;   //主机接受模式,包含有停止信号if (I2caRegs.I2CSTR.bit.NACK == 1)return  I2C_BUS_BUSY_ERROR;for(i=0;i<number;i++){while(!I2CA_CheckRecieveOk());Temp = I2caRegs.I2CDRR;if (I2caRegs.I2CSTR.bit.NACK == 1)return    I2C_BUS_BUSY_ERROR;*RamAddr = Temp;RamAddr++;}return I2C_SUCCESS;    //接受数据成功
}//###########################################################################
// $ 函数名称:    IICwriteBit(Uint16 slaveaddress, Uint16 regaddress, Uint8 bitNum, Uint8 data)       $
// $ 函数功能:    IIC向寄存器的某一位写数据                                                     $
//###########################################################################
void IICwriteBit(Uint16 slaveaddress, Uint16 regaddress, Uint8 bitNum, Uint8 data)
{Uint16 a;Uint8 b;DELAY_US(50);I2CA_ReadBytes(slaveaddress,regaddress,1,&a);b=(Uint8 )(a&0xff);b = (data != 0) ? (b | (1 << bitNum)) : (b & ~(1 << bitNum));DELAY_US(50);I2CA_WriteBytes(slaveaddress,regaddress,1,&b);
}//###########################################################################
// $ 函数名称:   IICwriteBits(Uint16 slaveaddress,Uint16 regaddress,Uint8 bitStart,Uint8 length,Uint8 data)      $
// $ 函数功能:    IIC向寄存器的某几位写数据                                                     $
//###########################################################################
void IICwriteBits(Uint16 slaveaddress,Uint16 regaddress,Uint8 bitStart,Uint8 length,Uint8 data)
{Uint8 b,mask;Uint16 a;DELAY_US(50);I2CA_ReadBytes(slaveaddress,regaddress,1,&a);b=(Uint8 )(a&0xff);mask = (0xFF << (bitStart + 1)) | 0xFF >> ((8 - bitStart) + length - 1);data <<= (8 - length);data >>= (7 - bitStart);b &= mask;b |= data;DELAY_US(50);I2CA_WriteBytes(slaveaddress,regaddress,1, &b);
}

TMS320F28069的硬件I2C一直卡在查询 I2caRegs.I2CSTR.bit.XRDY相关推荐

  1. STM32单片机硬件I2C驱动程序(查询方式)

    本文章原始地址:http://feotech.com/?p=69 本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与接收. 本例程中采用I2C ...

  2. STM32单片机硬件I2C驱动程序(软件轮询方式)---摘自:FeoTech

    感谢原作者:FeoTech   原文网址:http://feotech.com/?p=69 本程序主要用于驱动STM32单片机芯片的硬件I2C寄存器,实现通过使用芯片自带的I2C寄存器进行数据的发送与 ...

  3. STM8/STM32硬件I2C读取APDS9930程序代码

    STM的硬件I2C一直被各种吐槽,实际上只是用起来比较复杂而已,难点主要是在作为Master时的数据接收上,作为Slave时的数据发送没难度,正常用.重点是要真正掌握它里面设计的那个Data shif ...

  4. 联通物联卡流量查询、充值的操作方法

    联通物联网卡是近年来发展较好的物联网卡之一,它是中国联通专门为物联网而设计的一种专用设备卡.随着我国物联网应用的日益增多,如何查询和评价物联网卡的价值已成为许多用户面临的难题.那么中国联通物联卡流量查 ...

  5. 联通物联卡为什么没有网络_联通物联网卡怎么样?联通物联卡的查询官网是什么?...

    原标题:联通物联网卡怎么样?联通物联卡的查询官网是什么? 物联网时代的来临为我们生活中带来了许许多多的智能应用,移动物联网卡.电信物联网卡.联通物联网卡作为物联网最基础的通讯产品,在物联网应用中发挥着 ...

  6. 如何以物联网+硬件+物联卡方式构建新型智慧医疗管理体系?

    医疗事业的建设关系着我国人民的身体健康和生命安全,医疗体制改革一直以来都是国家战略布局的重点,医疗改革的本质就是改善医疗服务,提升病患就医体验,今天中创物联网将探讨如何通过物联网技术实现医疗改革和物联 ...

  7. STM32F10x_硬件I2C主从通信(轮询发送,中断接收)

    推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang Ⅰ.写在前面 ...

  8. STC8系列单片机硬件I2C使用教程(一)

    硬件I2C(查询方式)以STC8F2K08S2单片机为例 一.I2C相关的寄存器 ① I2C 配置寄存器 ② I2C 主机控制寄存器 ③ I2C 主机辅助控制寄存器 ④ I2C 主机状态寄存器 ⑤ I ...

  9. STM32F10x_硬件I2C读写EEPROM(标准外设库版本)

    Ⅰ.写在前面 上一篇文章是"STM32F10x_模拟I2C读写EEPROM",讲述使用IO口模拟I2C总线通信,对EEPROM(AT24Xxx)进行读写操作的过程. 上一篇文章主要 ...

最新文章

  1. 只因为离职报告多写这三个字,员工竟然倒赔公司2.9万!
  2. 用友u8cloud使用教程_四大ERP供应商SAP、Oracle、用友、金蝶哪个好
  3. 队列 集合的前n个元素
  4. python框架Flask学习笔记之get和post请求
  5. 随想录(怎么用source insight阅读kernel代码)
  6. 各种好用的开源库。快点进来,包你喜欢~^_^
  7. Flutter学习 — 实现滑动关闭、删除item
  8. vs2019编译的程序在win7环境上运行失败
  9. 安装CHD走过的一些坑
  10. MAC - macbook Ctrl键失灵的解决办法
  11. 俄罗斯计算机三进制优缺点,为什么我们没有用上三进制的计算机
  12. (11)向量组及其线性组合
  13. 2022 极术通讯-从CPU、DSA到软硬件融合
  14. WMP专辑封面显示不正常的问题(更新问题真实原因及完美解决方法)
  15. 如何更高效更系统地学习3D视觉?
  16. 果蔬超市管理系统的设计与实现
  17. 基于监督学习+自监督学习的智能抠图,精确到头发丝 | CVPR2020
  18. 关于如何定制开发Android第三方ROM,最全开发教程、原理阐述
  19. 前端文字转语音(tts+mp3拼接)
  20. 光纤光信号闪红灯_电信光纤猫光信号闪红灯怎么办 电信光纤猫光信号闪红解决方法...

热门文章

  1. Macbook pro lion系统打开trim支持
  2. OpenStack — Keystone
  3. 《众病之王——癌症传》读书笔记
  4. 如何查找自己的msn邮箱地址
  5. 360浏览器如何禁止切换到兼容模式[终极办法]
  6. wpa_supplicant的控制接口简单说明
  7. 算法题_求数列的某个数
  8. excel如何把1时20分30秒转换为分钟总数?
  9. leetcode环形链表
  10. C# 通过串口发送短信