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.
您好!
我正在使用 TMS320F28035作为微控制 器和组合 bq7694000DBT + BQ78350DBTR-R1开发电池管理系统。 我们已经开发出采用 MSP430的 BMS 版本、由于所有示例和专家都回答了我们的所有问题、它运行良好。
在测试 CAN 总线网络后、在项目的这个阶段、下一步是开发一个 I2C 接口。 对于此任务、我将"Example_2803xI2C_EEPROM.c"和该主题中的一些信息(https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/303750?tisearch=e2e-quicksearch&keymatch=i2c%20read#pi316717=3)作为信息资源。
我们将测试分为三个步骤:
1) 1)将操作写入 Microchip 的 EEPROM 24LC32AT-I/SN (下图)。 它似乎工作正常、因为我可以多次写入。
2) 2)对同一 EEPROM 存储器执行读取操作。 它似乎也正常工作。 检索到的数据是不同的、因为它是一个计数器。
3)写入后的写入和读取操作。 此时会出现问题。 我无法进行写入和读取、因为程序似乎卡在读取函数上。 我已经阅读了上面提到的 I2C 寄存器文档和示例,但我无法找到问题。 我似乎没有清楚一些旗帜或类似的东西。
我随附了该代码。 请、有人能帮您解决这个问题吗?
提前感谢您。
您好、Felipe、
对于您看到的问题、您说它卡在读取函数中、因此它永远不会返回? 您能看到调试时它在哪里卡住了吗? 您可能需要在读取功能中使用 I2CMDR 寄存器关闭自由模式才能成功进行调试。 在写入函数之后、您在示波器上没有看到任何内容吗? 可能有助于在写入函数之后的 CCS 表达式窗口中以及在读取函数的不同点调试 I2CSTR (状态寄存器)。
对于写入然后读取测试、您是否执行了以下操作?
错误= I2CA_WriteData (&I2cMsgOut1); 错误= I2CA_ReadData (&I2cMsgIn1);
最棒的
Kevin
尊敬的 Kevin:
感谢您的回复。
是的、我正在执行上述过程以进行写入和读取。
Watchig I2C 寄存器、当尝试读取时、I2C 状态寄存器内容为0x0410。 根据数据表、该寄存器值意味着未检测到下溢、同时数据已从 I2CDXR 复制到 I2CXSR。 假设 I2C 不处于复位状态、这是否意味着它正在等待 I2CDXR 寄存器的另一个负载?
此致、
Felipe。
您好、Felipe、
唯一的区别是 NACK SENT 位。 本应该在前面提到过、但在两种情况下(即写入之后和仅读取时)、在读取前后检查 I2CMDR 寄存器的值会很有用。 也许总线很忙?
I2caRegs.I2CSTR.bit.BB = 1.
在代码中、读/写函数返回错误、但在主循环中没有错误检查。 读取/写入函数中是否出现任何错误? 在写入后执行读取时、您是否可以看到任何波形? 我可能需要再次运行示例程序并查看生成的波形、但我相信您必须尝试多次读取 EEPROM 地址、然后才能成功、而您只有一次尝试。
最棒的
Kevin
尊敬的 Kevin:
经过一些测试后、总线很可能会像您一样忙。 我对代码进行了一些更改、并在 main 函数中放置了一些断点(在写入函数之后和读取函数之后)、我能够准确地看到这两个波形、这完全符合预期。 但是、如果我删除断点、代码就像以前一样直接写入。 似乎有一些标志或状态会阻止正确的总线功能。
因此、我在结束写入和读取函数之前执行了一个延迟函数、该函数需要进行一些调整。 这 不是一种优雅的方法、但正在发挥作用。 我不确定在最终项目中是否需要此任务(按顺序写入和读取)、但至少我有此选项。
您是否需要更好的方法?
我还附加了新代码。
您好!
Felipe。
您好、Felipe、
是的、初始写入通信可能尚未完成、I2C 外设也会被混淆。 我建议查看 C2000Ware 中的 Example_2803xI2C_EEPROM 示例程序如何使用 CurrentMsgPtr -> MsgStatus 处理其通信。
您的读取函数可能会在其中的某个位置产生错误。 您可能应该实施某种错误检查/处理代码。 我可以看到以下两项检查中的一项触发:
// //等待 STP 位从任何之前的主设备通信中清零。 //模块清除该位的操作被延迟到 SCD 位之后 //设置。 如果在启动新消息之前未选中此位 // I2C 可能会被混淆。 // IF (I2caRegs.I2CMDR.bit.STP==1) { 返回 I2C_STP_NOT _READY_ERROR; } // //检查总线是否占线 // IF (I2cRegs.I2CSTR.bit.BB = 1) { 返回 I2C_BUS_BUS_BUSY_ERROR; }
希望这对您有所帮助、
Kevin
尊敬的 Kevin:
我遵循了您的建议、我得到了下面的波形。 为了验证写入时间是否正确(最小值、幅度顺序相同)、我读取存储器数据表、发现最大写入时间周期为5ms、这与波形一致。 您认为这种支持是正确的吗?
我们可以看到、控制器写入数据、并尝试读回数据。 它在返回前多次尝试。 之后、它会验证恢复的数据是否等于发送的数据。 如果是,它将使用 pass()函数停止程序。 我阅读了固件并查找了一些文档、但我不确定它是否符合预期。 您是否知道这是正确的固件功能?
如果正确、下一步是将其用于其他器件。
感谢您的所有支持。
您好、Felipe、
是的、这一切听起来不错。 我相信我会先引导您指出错误方向、因为您的读取函数中可能会发生错误。
无法立即从 EEPROM 读取存储器的原因是地址设置部分未成功完成(即 EEPROM 未准备好发送请求的数据)。 正如您提到的、EEPROM 规范具有5ms 的最大写入周期时间、因此 epprom 最多需要5s 的时间来准备好将数据发送到 F2803x 主器件。
如果您查看 i2c_EEPROM 程序示例、I2CA_ReadData 函数会等待从存储器中读取、直到 I2C_MSGSTAT_RESTART 状态建立:
否则 if (msg->MsgStatus =I2C_MSGSTAT_RESTART) { I2caRegs.I2CCNT = msg->NumOfBytes;//设置预期的字节数 I2caRegs.I2CMDR.ALL = 0x2C20; //将重新启动作为主接收器发送 } 返回 I2C_Success;
一旦 I2C_ARDY_ISRC (寄存器准备好访问)中断源代码被检测到、这个状态在 i2c_int1a_ISR 内建立:
// //中断源=寄存器访问就绪 //此中断用于确定何时设置 EEPROM 地址 //读取数据通信的部分已完成。 因为没有停止位 //命令,此标志告诉我们何时发送了消息而不是消息 // SCD 标志。 如果接收到 NACK、清除 NACK 位并执行命令 A //停止。 否则、请转到通信的读取数据部分。 // 否则、IF (IntSource = I2C_ARDY_ISRC) { if (I2caRegs.I2CSTR.bit.nack = 1) { I2caRegs.I2CMDR.bit.STP= 1; I2caRegs.I2CSTR.All = I2C_CLR_Nack_bit; } 否则(CurrentMsgPtr -> MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr ->MsgStatus = I2C_MSGSTAT_RESTART; } }
否则、每次执行 ReadData 时都会检测到停止条件、并保持 I2C_MSGSTAT_SEND_NOSTOP 状态、这会导致 ReadData 函数内的 EEPROM 设置部分每次都保持运行:
// //中断源=检测到停止条件 // if (IntSource = I2C_SCD_ISRC) { (笑声) // //如果在地址设置部分收到 NACK 消息 //读取 EEPROM 时、下面的代码包含在中 //寄存器访问就绪中断源代码将生成停止 //条件。 在接收到停止条件后(此处)、设置 //要重试的消息状态。 用户可能希望限制该数字 //在生成错误之前重试次数。 // if (CurrentMsgPtr -> MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr ->MsgStatus = I2C_MSGSTAT_SEND_NOSTOP; } }
希望这对您有所帮助、
Kevin
编辑:是的,您对成功读取后使用 pass()函数暂停程序的理解是正确的。 该示例旨在仅从 EEPROM 读取2个字节、然后停止。