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.

[参考译文] TMS320F28378S:用于连接 RTC MCP7904 的 I2C 第一个字节写入问题的 7 位

Guru**** 2513185 points
Other Parts Discussed in Thread: C2000WARE, TMS320F28378S

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1551164/tms320f28378s-i2c-7-bit-of-first-byte-write-issue-for-interfacing-with-rtc-mcp7904

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

工具/软件:

TI 团队大家好、

我使用示例程序 i2c_ex6_eeprom_interrupt 来 连接 RTC MCP7904。

C:\ti\c2000\C2000Ware_6_00_00\driverlib\f2837xs\examples\cpu1\i2c

当我将第一个字节写入 RTC 时、会导致问题的第一个字节的第 7 位、其他字节读取和写入操作正常工作。

对于硬件电路测试、如果我通过 Arduino 板写入相同的字节、那么它工作正常、这意味着 TI TMS320F28378S 而非 RTC 硬件接口电路的编程方面出现了问题。

我需要 TI 团队的帮助、了解导致此错误操作或 I2C 所需的任何库更新的原因。 编程如下所示。

//
//包含的文件
//
#include “driverlib.h"</s>“
#include “device.h"</s>“

#include “i2cLib_FIFO_MASTER_INTERRUPT_h"</s>“

//
//定义
//
#define EEPROM_SLAVE_ADDRESS 0x6F

//! ------------------------------------
//! 信号| I2CA | EEPROM
//! ------------------------------------
//! SCL | GPIO105 | SCL
//! SDA | GPIO104 | SDA
//! ------------------------------------

//
//全局
//
结构 I2CHandle EEPROM;
结构 I2CHandle 温度传感器;

struct I2CHandle *currentResponderPtr;//用于中断中

uint16_t passCount = 0;
uint16_t failcount = 0;

uint16_t AvailableI2C_Slave[20];

uint16_t TX_MsgBuffer[MAX_BUFFER_SIZE];
Uint16_t RX_MsgBuffer[MAX_BUFFER_SIZE];
uint32_t ControlAddr;
uint16_t status=0;

//
//函数原型
//

中断 void i2cFIFO_ISR (void);
中断无效 i2c_isr (void);


void fail (void);
void pass (void);
void initI2CFIFO (void);
void verifyEEPROMRead (void);

void I2C_GPIO_init (void);
void I2Cinit (void);

//
//主要
//
void main (void)

//
//初始化器件时钟和外设
//
设备初始化 ();

//
//禁用引脚锁定并启用内部上拉电阻。
//
device_initGPIO();

//
//初始化 I2C 引脚
//
I2C_GPIO_init ();

//
//初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
//
interrupt_initModule();

//
//使用指向 shell 中断的指针初始化 PIE 向量表
//服务例程 (ISR)。
//
Interrupt_initVectorTable();

I2Cinit();
//
//本示例中使用的中断被重新映射到 ISR 函数
//在该文件中找到。
//
INTERRUPT_REGISTER (INT_I2CA_FIFO、&i2cFIFO_ISR);

INTERRUPT_ENABLE (INT_I2CA_FIFO);

INTERRUPT_REGISTER (INT_I2CA、&i2c_ISR);

INTERRUPT_ENABLE (INT_I2CA);


//
//启用全局中断 (INTM) 和实时中断 (DBGM)
//
EINT;
ERTM;

//连接到 I2CA 的 I2C 将在 AvailableI2C_Slave 缓冲区中找到
//运行 I2CBusScan 功能后。
uint16_t *pAvailableI2C_Slave = AvailableI2C_Slave;
状态= I2CBusScan (I2CA_BASE、pAvailableI2C_Slave);

uint16_t i;

currentResponderPtr =&EEPROM;

EEPROM.currentHandlePtr =&EEPROM;
EEPROM.SlaveAddr = EEPROM_SLAVE_ADDRESS;
EEPROM.WriteCycleTime_in_us = 10000;EEPROM 为//6ms 此代码经过测试
EEPROM.BASE = I2CA_BASE;
EEPROM.pControlAddr =&ControlAddr;
EEPROM.NumOfAddrBytes = 2;

//示例 1:EEPROM 字节写入
//将 11 写入 EEPROM 地址 0x0
ControlAddr = 0x0;//要写入的 EEPROM 地址
EEPROM.NumOfDataBytes = 1;
TX_MsgBuffer[0]= 0x80;
EEPROM.PTX_MsgBuffer = TX_MsgBuffer;

状态= I2C_MasterTransmitter (&EEPROM);

//等待 EEPROM 写入周期时间
//此延迟不是必需的。 用户可以改为运行其应用程序代码。
//但在启动之前等待 EEPROM 写入周期时间很重要
//另一个读取/写入事务
DEVICE_DELAY_US (EEPROM.WriteCycleTime_in_us);

//示例 2:EEPROM 字节读取
//确保将 11 写入 EEPROM 地址 0x0
ControlAddr = 0;
EEPROM.pControlAddr =&ControlAddr;
EEPROM.prx_MsgBuffer = RX_MsgBuffer;
EEPROM.NumOfDataBytes = 1;

状态= I2C_MasterReceiver (&EEPROM);

while (I2C_getStatus (EEPROM.BASE) 和 I2C_STS_BUS_BUSY);

verifyEEPROMRead ();

//示例 3:EEPROM 字(16 位)写入
// EEPROM 地址 0x1 = 22 且 0x2 = 33
ControlAddr = 1;//要写入的 EEPROM 地址
EEPROM.NumOfDataBytes = 2;
TX_MsgBuffer[0]= 0x11;
TX_MsgBuffer[1]= 0x22;
EEPROM.PTX_MsgBuffer = TX_MsgBuffer;
状态= I2C_MasterTransmitter (&EEPROM);

//等待 EEPROM 写入周期时间
//此延迟不是必需的。 用户可以改为运行其应用程序代码。
//但在启动之前等待 EEPROM 写入周期时间很重要
//另一个读取/写入事务
DEVICE_DELAY_US (EEPROM.WriteCycleTime_in_us);

//示例 4:EEPROM 字(16 位)读取
//确保 EEPROM 地址 1 具有 0x11、2 具有 0x22
ControlAddr = 1;
EEPROM.pControlAddr =&ControlAddr;
EEPROM.prx_MsgBuffer = RX_MsgBuffer;
EEPROM.NumOfDataBytes = 2;

状态= I2C_MasterReceiver (&EEPROM);

verifyEEPROMRead ();


//示例 5:EEPROM 页面写入
//程序地址=地址 64 中的数据模式

for (I=0;I<MAX_BUFFER_SIZE;I++)

TX_MsgBuffer[i]= i+64;
}

ControlAddr = 64;//要写入的 EEPROM 地址
EEPROM.NumOfDataBytes = MAX_BUFFER_SIZE;
EEPROM.PTX_MsgBuffer = TX_MsgBuffer;
状态= I2C_MasterTransmitter (&EEPROM);

//等待 EEPROM 写入周期时间
//此延迟不是必需的。 用户可以改为运行其应用程序代码。
//但在启动之前等待 EEPROM 写入周期时间很重要
//另一个读取/写入事务
DEVICE_DELAY_US (EEPROM.WriteCycleTime_in_us);

//示例 6:EEPROM 字分页读取
ControlAddr = 64;
EEPROM.pControlAddr =&ControlAddr;
EEPROM.prx_MsgBuffer = RX_MsgBuffer;
EEPROM.NumOfDataBytes = MAX_BUFFER_SIZE;

状态= I2C_MasterReceiver (&EEPROM);

verifyEEPROMRead ();

IF (STATUS)

fail();
}
暴露

pass();
}

}

//
// pass — 如果写入的数据与读取的数据匹配,则要调用的函数
//
Void
通过 (void)

asm(“ ESTOP0“);
for(;;);
}

//
//失败 — 写入的数据与读取的数据不匹配时将调用的函数
//
void 失败 (void)

asm(“ ESTOP0“);
for(;;);
}

void verifyEEPROMRead (void)

uint16_t i;
while (I2C_getStatus (EEPROM.BASE) 和 I2C_STS_BUS_BUSY);

for (I=0;I<EEPROM.NumOfDataBytes;I++)

if (RX_MsgBuffer[i]!= TX_MsgBuffer[i])

//传输的数据与接收到的数据不匹配
//失败条件。 PC 不应到达此处
ESTOP0;
fail();
}
}
}

中断无效 i2c_isr (void)

uint16_t MasterSlave = HWREGH (currentResponderPtr->base + I2C_O_MDR);

handleI2C_ErrorCondition (currentResponderPtr);

IF (MasterSlave 和 I2C_MDR_MST)

I2C_enableInterrupt (currentResponderPtr->base、I2C_INT_RXFF);
I2C_clearInterruptStatus (currentResponderPtr->base、(I2C_INT_RXFF));
}
INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_group8);
}

中断无效 i2cFIFO_ISR (void)

currentResponderPtr (Write_Read_);

INTERRUPT_CLEARACKGROUP (INTERRUPT_ACK_group8);
}


void I2C_GPIO_init (void)

// I2CA 引脚 (SDAA/SCLA)
GPIO_setDirectionMode (DEVICE_GPIO_PIN_SDAA、GPIO_DIR_MODE_IN);
GPIO_setPadConfig (DEVICE_GPIO_PIN_SDAA、GPIO_PIN_TYPE_PULLUP);
GPIO_setMasterCore (DEVICE_GPIO_PIN_SDAA、GPIO_CORE_CPU1);
GPIO_setQualificationMode (DEVICE_GPIO_PIN_SDAA、GPIO_QUAL_ASYNC);

GPIO_setDirectionMode (DEVICE_GPIO_PIN_SCLA、GPIO_DIR_MODE_IN);
GPIO_setPadConfig (DEVICE_GPIO_PIN_SCLA、GPIO_PIN_TYPE_PULLUP);
GPIO_setMasterCore (DEVICE_GPIO_PIN_SCLA、GPIO_CORE_CPU1);
GPIO_setQualificationMode (DEVICE_GPIO_PIN_SCLA、GPIO_QUAL_ASYNC);

GPIO_setPinConfig (DEVICE_GPIO_CFG_SDAA);
GPIO_setPinConfig (DEVICE_GPIO_CFG_SCLA);
}

void I2Cinit (void)

//myI2CA 初始化
I2C_disableModule (I2CA_BASE);
I2C_initMaster (I2CA_BASE、DEVICE_SYSCLK_FREQ、100000、I2C_DUTYCYCLE_50);
I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
I2C_setSlaveAddress (I2CA_BASE、80);
I2C_setOwnSlaveAddress (I2CA_BASE、0x6F);//I2CA 地址
I2C_disableLoopback (I2CA_BASE);
I2C_setBitCount (I2CA_BASE、I2C_BITCOUNT_8);
I2C_setDataCount (I2CA_BASE、2);
I2C_setAddressMode (I2CA_BASE、I2C_ADDR_MODE_7BITS);
I2C_enableFIFO (I2CA_BASE);
I2C_clearInterruptStatus (I2CA_BASE、I2C_INT_ARB_LOST | I2C_INT_NO_ACK);
I2C_setFIFO InterruptLevel (I2CA_BASE、I2C_FIFO_TXEMPTY、I2C_FIFO_RX2);
I2C_enableInterrupt (I2CA_BASE、I2C_INT_ADDR_SLAVE | I2C_INT_ARB_LOST | I2C_INT_NO_ACK | I2C_INT_STOP_Condition);
I2C_setEmulationMode (I2CA_BASE、I2C_EMULATION_FREE_RUN);
I2C_enableModule (I2CA_BASE);
}

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

    您好 Shri:

     发送的预期数据与实际数据是什么? 第一个数据是 ACKd 还是 NACKd? 是否已识别启动/停止条件? 范围分析的结果是什么?

    虽然我不一定要逐行分析代码行、但我注意到了以下几点。 我看到两个中断标志正在被清除、但四个被启用。 我建议清除您计划使用的所有中断状态。  

    此致、

    Aishwarya

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

    尊敬的  Aishwarya:

    除了器件地址 0x6F 和 0 地址处的数据字节 (0x81) 之外、代码中没有任何更改。 我在 0 地址发送了 0x81 数据、在地址 0 接收了数据 0x81。 我在 路径 C:\ti\c2000\C2000Ware_6_00_00\driverlib\f2837xs\examples\cpu1\i2c 处使用示例 i2c_ex6_eeprom_interrupt。 我在 仅第一个字节的第 7 位、第一个 字节的 0 至第 6 位以及所有其他字节读取和写入操作都正常工作时遇到问题。 根据您的建议、我 根据使能中断清除了所有中断状态 、但问题是一样的。 请共享工作代码、或者我需要在示例程序中更改什么内容才能正确设置第一个字节。

    此致、

    Shri Ram

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

    Shri

    感谢您的确认、让我明天再回到您这里。

    此致、

    Aishwarya

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

    Shri

    对总线进行覆盖时、是否在第一个数据帧看到了正确的地址 (0x6F)?

    此示例是为  AT24C256 EEPROM 编写的、遵循以下方案:

    MCP7940M 数据帧看起来略有不同。 您是否已经考虑过这一点?

    此致、

    Aishwarya

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

    您好  Aishwarya、

    现在、我使用了相同 driverlib 路径的轮询示例 i2c_ex4_eeprom_polling。

    我检查了在第一个字节处找到器件地址 0x6F 的范围、

    I write 0x85 (第一个字节)在 0 地址处。

    但通过 MCU 传输的数据 为 I2C 0x00 0x00 0x00 0x85 (在范围上检查)。

    请参阅写入操作

    我读取了它应该出现的第一个字节 0x85

    但 I2C 接收 来自零地址的第一个字节中的数据 0x05 0x10  (在范围上检查。

    请参阅读取操作

    是、您是正确的。此示例程序似乎用于访问 EEPROM 的双字节寄存器地址。

    我需要您的帮助来转换此驱动程序文件、以便用于 RTC 或的一字节寄存器地址传输

    请分享任何器件一个字节寄存器地址的其他工程工作示例。

    此致、

    Shri Ram

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

    通过更改代码解决了我的问题

    删除此代码

    /*

     for (I=I2C_Params->NumOfAddrBytes-1;I>=0;I-)

    I2C_putData (base、(temp >>(I*8U))& 0xFF);

     }*/

    类型转换临时变量类型 uint32_t 到  unsigned char

     I2C_putData(base、(无符号字符)temp);