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.

[参考译文] TMS320F28P650DK:F28P650DK6PTP 的 I2CA 无法与 HE24C64SOH 通信

Guru**** 2874030 points

Other Parts Discussed in Thread: C2000WARE

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1635601/tms320f28p650dk-i2ca-of-f28p650dk6ptp-failed-to-communicate-with-he24c64soh

器件型号: TMS320F28P650DK
主题: C2000WARE 中讨论的其他器件

尊敬的专家:  
我目前正在使用 TMS320F28P650DK6 与 HE24C64SOH 进行通信。 在 CPU 发出启动条件和 0xA0 地址后、当 HE24C64SOH 以 NACK 响应时、CPU 一直将 I2CA SCL 线路保持为低电平、仅在 CPU 发送停止条件时才恢复到高电平。 在调试模式下、当我在超时代码定义处添加一个断点时、可以观察到 SCL 保持低电平。 我想问、这可能是什么原因。 下面是代码、SYSCFG 配置、原理图和波形。  
此致! image.png

 

image.png

image.pngaf56ddbcf57e7d9a71d31453d37f156a.jpg

HE24C64SOH.PDF 

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

    您好 Steve、

    看起来发生了时钟延展。 我建议在 ARDY 轮询循环中检查 NACK、并确定 EEPROM 发送 NACK 的原因。 发出写入命令后、您可以在发出下一条命令之前轮询 ACK。 可能还需要一些延迟。

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    感谢您的回答。我已经找到了上述问题的原因。 这是因为寄存器检测中的 NACK 和 XRDY 位定义不正确。 更正后、即可正常发送和接收数据。

    但现在我遇到了两个新问题。 具体现象如下:

    FRIST、以下函数用于对 HE24C64SOH 的页写入。

    uint8_t HE24C64SOH PageWriteBytes (uint16_t 地址、const uint8_t *data、uint8_t data_len)

    uint8_t status = HE24C64SOH Success;
    uint8_t TX_DATA[34]={0};//最大支持32字节写入
    uint8_t i = 0;

    // 1。 参数验证 μ s
    if (data == NULL){
    返回 HE24C64SOH PARAM_ERROR;
    }

    if (data_len == 0 || data_len > 32){
    返回 HE24C64SOH PARAM_ERROR;
    }

    //计算结束地址
    uint32_t end_address =(uint32_t) address + data_len - 1;

    //检查地址范围
    if (address >= HE24C64SOH TOTAL_SIZE || END_ADDRESS >= HE24C64SOH TOTAL_SIZE){
    返回 HE24C64SOH ADDR_ERROR;
    }

    //检查是否跨页
    uint16_t start_page = address /HE24C64SOH page_size;
    uint16_t END_PAGE = END_ADDRESS / HE24C64SOH PAGE_SIZE;

    if (start_page != end_page){
    返回 HE24C64SOH page_error;
    }

    // 2. 等待总线空闲 μ s
    状态= HE24C64SoH_WaitForBusIdle (1000);
    if (status != HE24C64SoH_Success){
    返回状态;
    }

    // 3. 准备数据 μ s
    起始条件时硬件会自动发送设备地址、所以不需要在tx / data中包含设备地址
    TX_DATA[0]=(地址>> 8)& 0x1F;//地址高字节
    TX_DATA[1]=地址和 0xFF;//地址低字节

    //拷贝用户数据
    对于 (i = 0;i < data_len;i++){
    TX_DATA[2 + i]= DATA[i];
    }

    // 4. 配置发送模式 μ s
    I2C_setConfig (HE24C64SOH I2C_BASE、I2C_CONTROLLER_SEND_MODE);
    I2C_setDataCount (HE24C64SOH I2C_BASE、DATA_len + 2);//地址字节数 (2)+数据字节数 μ s

    // 5. 发送START条件 μ s
    I2C_sendStartCondition (HE24C64SoH_I2C_BASE);

    //检查XRDY和ACK
    状态= HE24C64SoH_WaitForTransfer (HE24C64SoH_I2C_BASE、1000);
    if (status != HE24C64SoH_Success){
    I2C_sendStopCondition (HE24C64SoH_I2C_BASE);
    返回状态;
    }
    DEVICE_DELAY_US (100);

    // 6. 发送所有数据 μ s
    对于 (i = 0;i < data_len + 2;i++){
    I2C_putData (HE24C64SoH_I2C_BASE、TX_DATA[i]);

    状态= HE24C64SoH_WaitForTransfer (HE24C64SoH_I2C_BASE、1000);
    if (status != HE24C64SoH_Success){
    I2C_sendStopCondition (HE24C64SoH_I2C_BASE);
    返回状态;
    }

    //在每次发送完一个字节、检查完成XRDY和ACK后增加延时100us
    DEVICE_DELAY_US (100);
    }

    // 7. 发送STOP条件 μ s
    I2C_sendStopCondition (HE24C64SoH_I2C_BASE);

    // 8. 等待总线空闲 μ s
    状态= HE24C64SoH_WaitForBusIdle (1000);
    IF (STATUS != HE24C64SoH_Success)

    I2C_sendStopCondition (HE24C64SoH_I2C_BASE);
    返回状态;
    }

    // 9. 轮询等待写入完成 μ s
    状态= HE24C64SoH_PollForWriteComplete();

    返回状态;
    }

    在 main 函数中、我有以下调试代码:

    DINT;

    DRTM;

    状态= HE24C64SOH PageWriteBytes (0x0013、WRITE_DATA、13);

    DEVICE_DELAY_US (5000);

    STATUS = HE24C64SOH PageWriteBytes (0x0020、WRITE_data1、32);

    EINT;

    ERTM;

    我已经测试了单次写入的页面写入功能、可以写入 1~32 字节。 然而、在连续写入期间、经过 5ms 延迟后、当单步执行程序进行调试时、当程序第二次进入页面写入功能时、I2CA MDR 寄存器的 STT 和 STP 位从 0 更改为 1、MDR 寄存器值从 0x4220 更改为 0x6A20。 此更改会导致在第二页写入中的数据最后一个字节之后应发送的停止条件成为开始条件、然后程序就会错误运行。 在 5ms 延迟期间、MDR 寄存器值保持在 0x4220、并且示波器显示总线通常处于高电平。 I2CA FIFO 和中断未启用。 我的问题是、MDR 寄存器的 STT 和 STP 位为什么会自动更改、在什么情况下可以更改?

    其次、在页面写入函数中、在发送单字节的间隔内有一个延迟代码“device_delay_US (100);“。 当我在 main.c 中运行该代码时、延迟时间为 100us、但使用示波器观察到、单字节之间的延迟有时为 10us、有时仅为 500ns(与没有增加延迟的波形一致)。 这是什么原因?

    期待您的答复。

    此致、

    Steve

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

    Steve、

    在检查 I2C BUSY 位和读取 I2C 状态并继续执行其余代码之前、您还必须检查停止条件。 否则、 代码会无意中在前一个事务完全完成之前写入 I2CMDR、如 TRM 中所述。

    while(I2C_getStopConditionStatus(base));

    关于延迟函数、您的代码是否从闪存执行?  您能否确保在器件初始化文件中正确初始化 device_delay_US 函数(例如,您有正确的预定义符号)?

    此致、

    Aishwarya

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

    Aishwarya

    1.“上一个事务尚未完全完成时“是否意味着 5 毫秒的延迟不足以完成第一页的写入? 我正在执行分步调试、这意味着在执行第一个页面写入函数后、直到至少几十秒后、程序才会第二次执行页面写入函数。 到那时、第一页写入事务应该已经完成、对吧?
    2、关于“代码无意写入数据“的问题,这是由代码中的逻辑错误引起的,还是由芯片硬件本身独立运行逻辑所触发的,超出了代码的控制范围?
    3.在什么情况下可以触发“代码无意写入数据“? 我可以做些什么来防止这种情况发生?
    4、“代码无意写入数据“的范围是什么? 它是只修改 I2CA MDR 的 STT 和 STP 位、还是也可以修改其他寄存器值? 它甚至可以扩展到 I2CA 之外吗?
    5、代码从闪存执行,在主函数和 I2CA 页面写入函数中执行时,相同代码段的行为有所不同。 这不能是由不正确的初始化引起的、对吧? main 函数中的延迟与 100us 代码延迟相匹配、该延迟表明初始化和延迟函数正确。

    期待您的答复。

    此致、

    Steve

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

    Steve、

    让我在一天左右的时间内回复您。

    此致、

    Aishwarya

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

    Steve、

    1. “上一个事务尚未完全完成时“是否意味着 5 毫秒的延迟不足以完成第一页的写入? 我正在执行分步调试、这意味着在执行第一个页面写入函数后、直到至少几十秒后、程序才会第二次执行页面写入函数。 到那时、第一页写入事务应该已经完成、对吧?

    5ms 延迟是可以的、但您也应该先轮询 SCD、以确认确实发生了什么。 试一下、让我知道结果有什么不同。  

    4. “代码无意写入数据“的范围是什么? 它是只修改 I2CA MDR 的 STT 和 STP 位、还是也可以修改其他寄存器值? 它甚至可以扩展到 I2CA 之外吗?

    如果您阅读了我之前的陈述、这很可能是一个计时问题、应该只会影响这些位。 此概念与其他寄存器/位无关。 更多信息、请参阅寄存器说明。

    [quote userid=“694431" url="“ url="~“~/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1635601/tms320f28p650dk-i2ca-of-f28p650dk6ptp-failed-to-communicate-with-he24c64soh/6314407 该代码从闪存执行、并且当在主函数中执行与在 I2CA 页写入函数中执行时、同一代码段的行为有所不同。 这不能是由不正确的初始化引起的、对吧? main 函数中的延迟与 100us 代码延迟相匹配、这表示初始化和延迟函数正确。

    能否就此提供更多详情? 我认为初始化应该很好,假设所有延迟函数都一致(即使用 sysctl_delay()) 以实现一致的行为。

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    1.我已经找到改变寄存器值的原因。 在“//9 处的写函数中。 轮询并等待写入完成
    状态= HE24C64SoH_PollForWriteComplete ();“、发送启动条件、然后检查 ACK 和 ARDY 以验证发送是否完成。 验证完成后、将发送停止条件。 由于在该代码之前发送了停止条件、因此停止条件将 CNT 设置为 0。 因此、在轮询函数中、不会执行启动和停止条件、并且它将保持为 1、直到 CNT 设置为 1 以进行执行。
    2.关于延迟函数,附加的源代码文件和说明内容如下:

    ...

    ...

    ...

    ...

    ...

    期待您的答复。

    此致、

    Steve

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

    e2e.ti.com/.../he24c64soh.he2e.ti.com/.../he24c64soh.ce2e.ti.com/.../1321.empty_5F00_driverlib_5F00_main.c

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

    Steve、

    您可以尝试使用 SysCtl_delay () 函数,但只要您始终使用其中一个函数,就可以了。  

    我已经提供了调试此问题所需的初始指导和信息 、但尚未收到这些建议。 此时、我强烈建议查看 C2000WARE EEPROM 示例、这些示例正好符合您尝试实现的目标+我们讨论了类似主题的其他 E2E:

    • C:\ti\c2000\C2000Ware_26_00_00\driverlib\f28p65x\examples\c28x\i2c\i2c_ex2_eeprom.c
    • C:\ti\c2000\C2000Ware_26_00_00\driverlib\f28p65x\examples\c28x\i2c\i2c_ex4_eeprom_polling.c
    • C:\ti\c2000\C2000Ware_26_00_00\driverlib\f28p65x\examples\c28x\i2c\i2c_ex6_eeprom_interrupt

    此致、

    Aishwarya

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

    尊敬的 Aishwarya:

    首先让我澄清一下:我昨天的答复是对你的部分的答复:“你能提供更多有关这方面的细节吗? 我认为初始化应该很好,假定延迟函数都是一致的(即使用 sysctl_delay ()) 来实现一致的行为。“

    第二,关于你的建议'(即使用 SysCtl_delay () 为一致的行为)',我相信我的代码一直这样做。 在昨天的回复中、我提到我使用的是“Device_delay_US ()“、这是一个 TI 库函数、不是我编写的。 屏幕截图包括此函数的定义、它使用“sysCtl_delay()“。 因此,我没有使用 sysctl_delay () 进行测试;我直接回复了屏幕截图,以排除这种可能性。 如果我误解了、请指出、我将按照您的指导进行测试。

    第三、我已经查看了上述示例、使用的延迟函数与我使用的延迟函数相同、如下面的屏幕截图所示。

    第四、有关您的回复中提到的其他 E2E 主题、您能否附上具体的链接?

    第五、让我再次澄清:在我的代码中、main.c 和库文件都使用“device_delay_US ()“、因此可以保证一致性。 使用示波器进行检查时、main.c 中的延迟函数显示了与代码匹配的延迟时间、但使用示波器进行检查时、库文件中的延迟函数显示了与代码不匹配的延迟时间。

    期待您的答复。

    此致、

    Steve

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

    Steve、

    让我明天回应你。

    此致、

    Aishwarya

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

    您好 Steve、

    是的、理解的、确认这一点很有帮助。 我认为延迟代码看起来很合适。 我从未见过示波器与延迟函数不匹配。 由于 我们之前讨论的内容、您可能会看到差异。

    如 我的一些回复中所述、您确实需要检查停止条件和其他状态位、而不仅仅是添加延迟来确保 I2C 状态机正常运行。  请 查看并模拟该示例中的函数、例如 ControllerTransmitter、ControllerReceiver 等  

    此致、

    Aishwarya