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.

[参考译文] TMS320F28069:RRDY 上的 I2C 挂起和其他问题

Guru**** 2349000 points
Other Parts Discussed in Thread: CONTROLSUITE, MOTORWARE
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/593534/tms320f28069-i2c-hang-on-rrdy-and-other-issues

器件型号:TMS320F28069
主题中讨论的其他器件:controlSUITEMOTORWARE

您好!

我正在配置 C2000 F2806x I2C 外设以从 MPU9250读取陀螺仪数据(实际上相当于更常见的 MPU6050)。 该代码集成到 MotorWare 示例项目布局中、因此寄存器访问与我之前看到的大多数其他 controlSUITE 示例代码稍有不同、寄存器位作为位字段进行访问。
我在重复启动模式下使用 I2C 外设来读取一系列寄存器值。 C2000的时钟频率为90MHz、我使用 IPSC = 8、ICCL=ICCH=45、在50%占空比下、对于100kHz SCL。 我已经了解到低电平周期应该是高电平长度的两倍(< 33%的占空比)、但还没有测试。

当器件已复位(I2CMDR = 0)时、我有一些代码配置 I2C 外设时钟、然后启用(i2c->I2CMDR |= I2C_I2CMDR_BIT)外设。 外设时钟已启用并配置相应的 GPIO 供 I2C 使用。
我已修改了[http://processors.wiki.ti.com/index.php/I2C_Tips]上提供的重复起始 I2C 示例代码 、如下所示:

extern int I2C_readBytes (I2C_Handle i2cHandle、uint16_t slaveaddr、uint16_t* write_data、uint16_t write_len、uint16_t* read_data、 uint16_t read_len){
I2C_Obj * i2c =(I2C_Obj *) i2cHandle;
int i;
//检查总线忙*/
while ((i2c->I2CSTR & I2C_I2CSTR_BB_BB));

//配置期间禁用 I2C */i2csr->I2Cdr
=


i2c = i2c 写入控制器;
i2c = i2c ic iDr_ iDr_ ic = i2c = iDr_ iDr_写入*
I2C->I2CMDR =(I2C_I2CMDR_IRS_BIT | I2C_I2CMDR_STT_BIT | I2C_I2CMDR_STL_BIT | I2C_I2CMDR_FREE_BIT);

//发送数据*/ for
(i = 0;i < WRITE_RDST_BIT

)| I2C_RDST_BIN+(I2+)

//如果发生 NACK,则 SCL 保持低电平,且 STP 位被清零
(如果(i2c->I2CSTR & I2C_I2CSTR_nack_bits){
i2c->I2CMDR = 0;//复位 I2C 使 SCL 不保持低
电平返回1;
}
i2c->I2CDXR = WRITE_DATA[i];
}

//在开始事务的读取阶段
之前等待 ARDY (!(i2c->I2CSTR & I2C_I2CSTR_ARDY_Bits));

//将 I2C 控制器设置为读取 len 字节*/
i2c->I2CNT = read_len;
i2c->I2CMDR =(I2C_I2CMDR


= I2C_BIT)| I2C_MDR_I2C_BIT | I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_BIT | I2C_0 | I2C_BIT | I2C_MDR_I2C_BIT | I2C_BIT i < read_len;i++){
//等待 I2C 读取数据或"ARDY "(如果我们收到 NACK
)(!(i2c->I2CSTR &(I2C_I2CSTR_RRDY_BITS | I2C_I2CSTR_ARDY_Bits)));

//发生 NACK 时、I2CSTR_I2CST_I2CMTR_0
位被清除且 I2CTR_I2CTR_I2CTR_BIT 被保持(如果 I2CST_I2CTR_I2CMTI 位为低电平)
;//重置 I2C 以便 SCL 不保持低
电平返回1;
}
//确保您获得 RRDY 信号
,同时(!(i2c->I2CSTR & I2C_I2CSTR_RRDY_BITS){};
READ_DATA[i]= i2c->I2CDRR;
}
返回0;
} 

此代码在检查总线忙状态时导致挂起- SCL 和 SDA 线路在启动时的当前状态分别为低电平和高电平。 在成功与以下替代读取函数通信后、我能够使其发送数据并立即进入 RRDY 位(通过示波器确认)等待的状态:


extern uint16_t I2C_ReadData (I2C_Handle i2cHandle、uint16_t addr、uint16_t reg){

I2C_Obj * iIRS =(I2C_Obj *) i2cHandle;

//释放总线上的保持
//重置
i2c->I2CMDR = 0x00;i2C_CSTR=I2C_BICSTR/ I2c



忙

时、I2C_I2CMDR
= I2C_BICSTR/ I2c = I2c / I2CSTR/ I2c
//等待停止状态清除
while (i2c->I2CMDR & I2C_I2CMDR_STP_BIT);

i2c->I2CISAR = addr;

//总线忙
时等待忙(i2c->I2CSTR & I2C_I2XR_BB_BB){};

i2c->I2CCNT =只写入一个字节;i2CSTR
= 1个字节;
//主控模式(MST)、发送(TRX)、发送开始(STT)、自由运行(免费)、
i2c->I2CMDR =(I2C_I2CMDR_STT_BIT | I2C_I2CMDR_ST_BIT | I2C_I2CMDR_IRS_BIT | I2C_FREE)
//应在主设备写入模式下将寄存器写入总线

//等待 XRDY 完成传输,或在 NACK 的情况下等待 ARDY
(!(i2c->I2CSTR &(I2C_I2CSTR_XRDY_BITS | I2C_I2CSTR_ARDY_Bits)));

if (i2C_I2CSTR_>I2CTR_I2CMDR_BIT_BINACK =/I2CST_BICTR_BIT_BICST_BIT_BIT = I2CST_BIT_BICTR/ I2CST_BINBIT_BIT
= I2CST_BIT_BIT = I2CST_NOT_BIT / I2CST_BIT_BIT = I2CST_BINACK
/ I2CST_NOT_





//在开始事务的读取阶段之前等待 ARDY
(!(i2c->I2CSTR & I2C_I2CSTR_ARDY_Bits);


//将外设更改为主 RX 模式并生成停止条件、重复启动条件
i2c->I2CNT = 1;//仅一个字节读取
iMST->I2CMT_BIC_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_MDR_I2C_BIT | I2C_BIT

//等待 RRDY 传输完成,或在 NACK 的情况下等待 ARDY
(!(i2c->I2CSTR &(I2C_I2CSTR_RRDY_BITS | I2C_I2CSTR_ARDY_Bits)));
if (i2c->I2CSTR & I2C_I2CSTR_R_Bits | I2CST_I2CMDR_BIT_BIT
);






= I2CST_I2CMDR_I2C/I2CMDR_I2T/ I2C/SION_I2T/ I2CMDR_I2T=/I2CMT_BIT / SIMP_I2R/ SIMP_I2R/ SIMP_I2R/ SIMP_I2R/ SIMP_I2R/ SIMP_I2R/ SIMP_I2R/ SIMP_NOT_R/
//在 CNT=0时设置 STP
//等待停止条件
// while (!(i2c->I2CSTR & I2C_I2CSTR_SCD_BITS){
//i2c->I2CMDR |= I2C_I2CMDR_STP_BIT;
//};

//等待新数据忙//
! 这似乎永远不会发生
//while (((i2c->I2CSTR & I2C_I2CSTR_RRDY_BITS)=0){};
返回 i2c->I2CDRR;//返回读取数据;

错误:{
//错误条件
返回0xFF;// TODO 修复此
}

此代码是根据在网络和此论坛上找到的信息进行黑客攻击的。 我可以多次调用此函数、它似乎与器件通信(读取包含16位陀螺仪数据的高字节和低字节寄存器以及包含已知常量世卫组织_am_i=0x71的寄存器)。 我看到数据事务发生在示波器上、但我看到的数据似乎不正确。 这可能是因为我对代码进行了更改、使其运行、这样它不会轮询 I2CSTR 中的 RRDY 标志。 似乎有数据从器件传回、然后总线被成功释放(生成了 ACK 和 STOP 条件)、但是这个标志永远不会被发出。 我觉得这种行为相当令人困惑。 我跳过这项检查并无论如何从 DRR 寄存器中读取、我认为这并不总是处于应读取的状态、因此会导致数据损坏。 如果轮询此标志、代码将挂起、等待它。


这里发生什么事了?

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

    好的、小小的更新。

    我在第一个函数中注释了第4-5行(检查总线忙状态)、它开始正常工作、我不确定原因。 我假定一个总线忙状态将被一个外设复位清除。 这也是我第一次看到 RRDY 标志的工作方式、正如我最初想象的那样。

    对于在从 MPU 器件读取轴数据的上下文中可能会看到这一点的其他人、只需将16位二进制补码测量的高字节和低字节读作无符号整数、并将结果汇编如下:

    uint16_t 高电平、低电平;
    int16_t 结果;
    
    高电平= I2CRead (...);
    低电平= I2CRead (...);
    
    结果=(int16_t)((高电平<< 8)|低电平); 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    卢卡斯
    我在看这个。 如果您发现其他内容、请进行更新。