工具与软件:
我在 F28335中使用 I2C。
I2C 连接到三个 IO 扩展器 IC - TCAL9539-Q1。
我将共享我正在使用的 I2C 代码、如下所示。
我将在主循环中按顺序使用这种读写函数。
在读取功能期间、我面临问题。
当我在调试模式下运行代码时、逐步操作- 我正在正确获取数据。 但是、当我持续运行代码时、数据并不正确、正如我在观察窗口中分析过的那样。
我还想验证轮询方法的读取和写入函数。
请验证代码并让我知道可能的解决方案。
提前感谢您。
/**
*@简介: I2C C GPIO 的初始化
*@param[in]
*@param[out]
*/
void vInitI2CMPIO (void)
{
EALLOW;
//
//启用所选引脚的内部上拉
//用户可以启用或禁用上拉。
//这将启用指定引脚的上拉。
//注释掉其他不需要的行。
//
GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;//启用 GPIO32的上拉(SDAA)
GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;//启用 GPIO33的上拉(SCLA)
//
//将所选引脚的鉴定设置为仅异步
//这将为所选引脚选择异步(无限定条件)。
//注释掉其他不需要的行。
//
GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3;//异步输入 GPIO32 (SDAA)
GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;//异步输入 GPIO33 (SCLA)
//
//使用 GPIO 寄存器配置 SCI 引脚
//指定可能的 GPIO 引脚将是 I2C 功能引脚
//引脚。 注释掉其他不需要的行。
//
GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 1;//将 GPIO32配置为 SDAA
GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;//将 GPIO33配置为 SCLA
EDIS;
}
/**
*@简介:特殊功能寄存器的 I2C 初始化
*@param[in]
*@param[out]
*/
void vI2CaInitSFR (void)
{
//默认值-对于150MHz SYSCLKOUT
I2caRegs.I2CPS.all = 14;//预分频器-需要在模块时钟上支持7-12MHz (150/(14+1)= 10MHz)
I2caRegs.I2CCLKL = 15;//注意:必须为非零//10/(I2CCLKL+I2CCLKH)= i2c 速度
I2caRegs.I2CCLKH = 10;//注意:必须为非零
I2caRegs.I2CIER = 0;//启用 SCD 和 ARDY 中断
I2caRegs.I2CMDR.all = 0x0020;//使 I2C 退出复位
//挂起时停止 I2C
}
/**
*@简介:阅读 I2C 函数
*@param[in]: uint16_t ui16SlaveAddress 是从设备地址
* uint16_t ui16CmdAddress、命令地址
* uint16_t * pui16ReadBuffer、读取数据缓冲区
* uint16_t i16Nbyte -字节数
*@param[out]: true 或 false
*/
bool bReadI2C (uint16_t ui16SlaveAddress、uint16_t ui16CmdAddress、uint16_t * ui16ReadBuffer、uint8_t ui8Nbyte)
{
uint16_t i;
//等待从任何之前的事务中停止
while (I2caRegs.I2CMDR.bit.stp);
//设置从地址
I2caRegs.I2CSAR = ui16SlaveAddress;
//检查总线是否繁忙
while (I2caRegs.I2CSTR.bit.bb);
//写入寄存器地址(启动条件)**
I2caRegs.I2CCNT = 1;//一个字节(寄存器地址)
I2caRegs.I2CMDR.all = 0x6620;//主发送模式、启动条件
while (!I2caRegs.I2CSTR.bit.XRDY);//等待 TX 就绪
I2caRegs.I2CDXR = ui16CmdAddress;//发送寄存器地址
while (!I2caRegs.I2CSTR.bit.ARDY);//等待事务完成
//**确保在读取之前停止条件**
I2caRegs.I2CMDR.bit.stp = 1;
while (I2caRegs.I2CMDR.bit.stp);
//重新启动读取(重复启动)**
I2caRegs.I2CCNT = ui8Nbyte;//要读取的字节数
I2caRegs.I2CMDR.all = 0x6C20;//主接收模式、重复启动
对于(i = 0;i < ui8N 字节;i++)
{
while (!I2caRegs.I2CSTR.bit.RRDY);//等待 RX 就绪
pui16ReadBuffer[i]= I2caRegs.I2CDRR;//从从器件读取数据
}
I2caRegs.I2CMDR.bit.stp = 1;// Send stop condition (发送停止条件)
返回 true;
}
/**
*@简介:编写 I2C 函数
*@param[in]: uint16_t ui16SlaveAddress, Slave Device address
* uint16_t ui16CmdAddress、命令地址
* uint16_t * pui16WriteBuffer、写入缓冲区地址
* uint8_t ui8nbyte -字节数
*@param[out]: true 或 false
*/
bool bWriteI2C (uint16_t ui16SlaveAddress、uint16_t ui16CmdAddress、uint16_t * ui16WriteBuffer、uint8_t ui8nbyte)
{
uint16_t i = 0;
//在发送新数据之前清除先前的错误
I2caRegs.I2CSTR.bit.nack = 1;// Clear NACK bit (清除 NACK 位)
I2caRegs.I2CSTR.bit.bb = 1;//如果卡住、则清除总线忙
I2caRegs.I2CSTR.bit.ARDY = 1;// Clear ARDY (事务完成)标志
//如果 I2C 总线卡滞、请将其复位
如果(I2caRegs.I2CSTR.bit.BB = 1)
{
I2caRegs.I2CMDR.bit.stp = 1;// Send stop (发送停止)以释放总线
I2caRegs.I2CMDR.all = 0x0020;// Reset I2C module.
}
//设置从机地址
I2caRegs.I2CSAR = ui16SlaveAddress;
//配置传输
I2caRegs.I2CCNT = ui8nbyte + 1;//发送的总字节数(命令+数据)
I2caRegs.I2CDXR = ui16CmdAddress;//发送命令
//发送启动条件
I2caRegs.I2CMDR.all = 0x6E20;// STT=1 (启动)、TRX=1 (发送)、MST=1 (主器件)、IRS=1 (I2C 启用)
//等待 TX 就绪(XRDY)
while (I2caRegs.I2CSTR.bit.XRDY = 0);
//发送数据字节
对于(i = 0;i < ui8nbyte;i++)
{
I2caRegs.I2CDXR = pui16WriteBuffer[i];//加载数据到传输缓冲区
//等待 TX 就绪(XRDY)
while (I2caRegs.I2CSTR.bit.XRDY = 0);
}
//发送停止条件
I2caRegs.I2CMDR.bit.stp = 1;
//检查 I2C 是否已确认
如果(I2caRegs.I2CSTR.bit.nack == 1)
{
返回 false;
}
返回 true;