This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F2.8069万:I2C写读过运行问题

Guru**** 2589245 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/658159/tms320f28069-i2c-write-read-over-run-problem

部件号:TMS320F2.8069万

大家好 ,我正在使用TMS320F2.8069万上的I2C来写入和读取多个器件,例如I2C到一个线桥,I2C到IO扩展器等。我想按以下方式写入和读取。

S AD,WR [A] WCFG [A] CF [A] SR AD,RD,[A][CF] A\ P

//[]表示从机

//WCFG -写入配置寄存器地址

// cf -要写入的配置字节

// AD -地址

// SR -重复开始

当我用out Rd单独书写时,即  

S AD,WR [A] WCFG [A] CF [A] A] A\ P

通过SDA发送的数据是完美的

但当我这样做时  

S AD,WR [A] WCFG [A] CF [A] SR AD,RD,[A][CF] A\ P

写后读写将写入 I2caRegs.I2CDXR寄存器。 我尝试在写和读之间设置延迟。 它只是被忽略了,而过度的权利继续存在。 请就要检查的内容给出一些想法或建议。

代码为  

void I2CAInit (void){

//初始化I2C
I2caRegs.I2CSAR = 0x0050;
I2caRegs.I2CPsc.all = 10;//预分频器-需要7-12 MHz的模块clk,此处= 30M/(6+1)= 4.28 MHz
I2caRegs.I2CCLKL = 10;//指定空间,必须为非零
I2caRegs.I2CCLKH = 10;//指定标记,必须为非零
I2caRegs.I2CIER = 0x24;//启用SCD和ARDY中断
I2caRegs.I2CMDR.ALL = 0x0020;//从重置中取出I2C
//暂停时停止I2C
I2caRegs.I2CFFTX.ALL = 0x6021;//启用FIFO模式和TXFIFO
I2caRegs.I2CFFTX.bit.TXFFIENA = 1;
I2caRegs.I2CFFRX.ALL = 0x2040;//启用RXFIFO,清除RXFFINT

//I2caRegs.I2CFFTX.ALL = 0x0000;//禁用FIFO模式和TXFIFO
//I2caRegs.I2CFFRX.ALL = 0x0000;//禁用RXFIFO,清除RXFFINT,
返回;
}

Int16 B1WWrConfig (UINT16配置){
//写入配置(案例A)
// S AD,0 [A] WCFG [A] CF [A] SR AD,1 [A][CF] A\ P
//[]表示从机
//要写入的CF配置字节

I2C.MsgBuffer[0]=B1W_WCFG;
I2C.MsgBuffer[1]=配置;
I2C.NumOfBytes=2;//数据字节的数目,不包括地址
I2CAWrite (&I2C);
毫秒(100);
I2C.MsgStatus = I2C_MSGSTAT_RESTART;
I2C.NumOfBytes=1;
I2CARead (&I2C);
毫秒(5);
IF(I2C.MsgBufferRX[0]==(Config&0x0F)))return(0);
else返回(-1);
}


UINT16 I2CAWrite(I2CMSG *msg){
UINT16 I;
//等待STP位从以前的任何主通信中清除。
//模块清除此位的时间延迟到SCD位之后
//设置。 如果在启动新消息之前未检查此位,则
// I2C可能会混淆。
//IF (I2caRegs.I2CMDR.bit.STP == 1)
//返回I2C_STP_NOT_READY_ERROR;
while (I2caRegs.I2CMDR.bit.stp);
MSG->WrDone = 1;
I2caRegs.I2CSAR = msg->SlaveAddress;

//检查总线是否繁忙
如果(I2caRegs.I2CSTR.bit.BB == 1)返回I2C_BUS_BUSY_ERROR;
I2caRegs.I2CCNT = msg->NumOfBytes;
I2caRegs.I2CFFTX.Bit.TXFFIL = msg->NumOfBytes;
用于(i=0; i<msg->NumOfBytes; i++){
I2caRegs.I2CDXR =*(msg->MsgBuffer+I);
}
//作为主发送器发送启动
IF (msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP){

}
//I2caRegs.I2CMDR.ALL = 0x6E20;//运行空闲,发送开始,停止,主模式,传输模式,模块已启用
I2caRegs.I2CMDR.All = 0x6E20;//运行空闲,发送开始,停止,主模式,传输模式,模块已启用
//I2caRegs.I2CMDR.bit.rm=1;//重复模式
//I2caRegs.I2CMDR.bit.stp = 1;
//while (I2caRegs.I2CSTR.bit.XRDY == 1){}
//while (I2caRegs.I2CSTR.bit.BB == 1){}
//while (msg->WrDone);
返回I2C_SUCCESS;
}

UINT16 I2CARead (I2CMSG *消息){
//等待STP位从以前的任何主通信中清除。
//模块清除此位的时间延迟到SCD位之后
//设置。 如果在启动新消息之前未检查此位,则
// I2C可能会混淆。
//IF (I2caRegs.I2CMDR.bit.STP == 1)
//返回I2C_STP_NOT_READY_ERROR;
while (I2caRegs.I2CMDR.bit.stp);
I2caRegs.I2CSAR = msg->SlaveAddress;
MSG->RdDone = 1;
IF (msg->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP){
//检查总线是否繁忙
如果(I2caRegs.I2CSTR.bit.BB == 1)返回I2C_BUS_BUSY_ERROR;
I2caRegs.I2CCNT = msg->NumOfBytes;
I2caRegs.I2CDXR = 0;
I2caRegs.I2CMDR.All = 0x2620;//发送数据至设置EEPROM地址
}
否则,如果(msg->MsgStatus == I2C_MSGSTAT_RESTART){
I2caRegs.I2CCNT = msg->NumOfBytes;//设置预期的字节数
I2caRegs.I2CDXR = 0;
I2caRegs.I2CMDR.All = 0x2C20;//作为主接收器发送重启
}
//while (I2caRegs.I2CSTR.Bit.BB == 1 || I2caRegs.I2CSTR.Bit.XRDY ==0)
//while (I2caRegs.I2CSTR.bit.BB == 1);
//while (I2caRegs.I2CSTR.bit.RRDY == 1);
//while (msg->RdDone);
返回I2C_SUCCESS;
}

中断void i2c_int1a_isr(void){
UINT16 IntSource,I;

//读取中断源
IntSource = I2caRegs.I2CISRC.ALL;

//中断源=检测到停止条件
IF (I2caRegs.I2CFFTX.Bit.TXFFINT){
I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;
I2C.WrDone = 0;
}
IF (IntSource == I2C_SCD_ISRC){
//如果已完成的消息正在写入数据,请将消息重置为非活动状态
IF (I2C.MsgStatus == I2C_MSGSTAT_WRITE _BUSY){
I2C.MsgStatus = I2C_MSGSTAT_INACTIVE;
}
否则{
//如果消息在的地址设置部分收到nack
// EEPROM读取,以下代码包含在寄存器访问就绪中
//中断源代码将生成停止条件。 停止后
//条件已接收(此处),请将消息状态设置为重试。
//用户可能希望在生成错误之前限制重试次数。
IF (I2C.MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_SEND_NOSTOP;
}
//如果已完成消息正在读取EEPROM数据,请将消息重置为非活动状态
//并从FIFO读取数据。
否则,如果(I2C.MsgStatus == I2C_MSGSTAT_READ_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_INACTIVE;
对于(i=0;i < I2C.NumOfBytes;i++){
I2C.MsgBufferRX[i]= I2caRegs.I2CDRR;
}
}
//检查收到的数据
对于(i=0;i < I2C.NumOfBytes;i++){
I2C.MsgBufferRX[i]= I2caRegs.I2CDRR;
}
I2C.RdDone = 0;
}
}
//中断源=寄存器访问就绪
//此中断用于确定的EEPROM地址设置部分的时间
//读取数据通信已完成。 由于没有命令停止位,所以此标志
//告诉我们邮件已发送,而不是SCD标志。 如果是一个nack
//已收到,请清除nack位并命令停止。 否则,继续阅读
//通信的数据部分。
否则IF (IntSource == I2C_ARDY_ISRC){
IF (I2caRegs.I2CSTR.bit.nack == 1){
I2caRegs.I2CMDR.bit.stp = 1;
I2caRegs.I2CSTR.All = I2C_CLR_nack_bit;
}
否则IF (I2C.MsgStatus == I2C_MSGSTAT_send_NOSTOP_BUSY){
I2C.MsgStatus = I2C_MSGSTAT_RESTART;
}
}//注册访问结束就绪

//启用未来的I2C (PIE组8)中断
PieCtrlRegs.PIEACK.ALL = PIEACK_group8;
}

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Jawwad,
    您是否通读了此AppNote? www.ti.com/.../slva704.pdf。这是I2C基础知识。 我想你可能已经过去了,但如果你觉得它有用,我已经分享了。

    -您是否在两组传输过程中确定了总线范围? 所有的ACK和转换是否符合您的期望?
    -我不确定我是否理解读取时DXR寄存器是如何被覆盖的。 I2C具有单独的发送和接收数据缓冲区,在没有CPU干预的情况下,不应该有任何数据在这些寄存器之间移动。您在代码中的何处可以看到DXR数据被覆盖?

    谢谢!
    标记
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢Mark。
    是的,我已经阅读了I2C TMS320x2802x,2803x Piccolo Inter-Integrated Circuit (I2C)模块的这篇文章和应用说明。 我正在使用I2C EEPROM示例中的基本代码。

    是的,我已检查了示波器上的传输,它可以检查所有ACK。 例如,当我只写而不写rd时,范围就会显示这一点
    S AD,WR [A] WCFG [A] CF [A] A] A\ P

    但是,当写入后按rd并重新启动时,即
    S AD,WR [A] WCFG [A] CF [A] SR AD,RD,[A][CF] A\ P

    我只能达到WCFG [A]之后,我看不到CF,而是SDA上的0。

    当我观察I2C寄存器时也会发生同样的情况。

    是否有线索?

    此致
    Jawwad
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Mark,您好!
    感谢你的帮助。
    我解决了问题。 罪魁祸首是
    I2caRegs.I2CDXR = 0;
    在功能中
    UINT16 I2CARead (I2CMSG *消息);

    它来自I2C EEPROM应用示例,其中它设置了地址,这是读取函数内的写入。 有点困惑。

    但感谢您的帮助

    谢谢
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我很高兴你能弄清楚这一点。

    请不要犹豫,以后再发布问题!