主题中讨论的其他器件:controlSUITE、 MOTORWARE
您好!
我正在配置 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 寄存器中读取、我认为这并不总是处于应读取的状态、因此会导致数据损坏。 如果轮询此标志、代码将挂起、等待它。
这里发生什么事了?