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.

[参考译文] TMS570LC4357:可以提供作为主器件发送和接收的 I2C 通信步骤吗?

Guru**** 2477665 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master

器件型号:TMS570LC4357

您好,

请在下面找到用于 I2C 通信的 TI 示例代码


/*用户代码开始(0)*/
/*用户代码结束*/

/*包含文件*/

#include "hL_sys_common.h"

/*用户代码开始(1)*/
#include "HL_i2c.h"
/*用户代码结束*/

/*用户代码开始(2)*/
#define DATA_COUNT 10.

#define Master_Address 0x26
#define Slave_Address 0x8
#define Slave_Word_address 0x00
#define RECEIVE_DATA_setup 0x1 // 1字地址

uint8_t TX_Data_Master[DATA_COUNT]={0x10、0x11、0x12、0x13、0x14、0x15、0x16、0x17、0x18、0x19};
uint8_t RX_Data_Master[DATA_COUNT]={0};

uint8_t TX_Data_Slave[10]={0x20、0x21、0x22、0x23、0x24、0x25、0x26、0x27、0x28、0x29};
uint8_t RX_Data_Slave[10]={0};

#define PCF8570_address 0x57 //在 PCF8570中所有 A0、A1、A2均连接到3.3V
uint32_t temp1、temp2;

/*用户代码结束*/

void main (void)

/*用户代码开始(3)*/

int repeat = 0;int delay = 0;

/*根据 GUI 进行 I2C 初始化
*模式=主设备-发送器
*波特率= 100KHz
*计数= 10
*位计数= 8位
*
i2cInit();

//主传输功能//

/*配置要与*/通话的从机地址
i2cSetSlaveAdd (i2cREG1、PCF8570_address);

/*将方向设置为发送器*/
/*注意:可选-在 Init 中完成*/
i2cSetDirection (i2cREG1、I2C_transmitter);

/*配置数据计数*/
/*数据计数+ 1 (字地址)*/
i2cSetCount (i2cREG1、data_count + 1);

/*将模式设置为主设备*/
i2cSetMode (i2cREG1、I2C_MASTER);

/*设置编程计数后停止*/
i2cSetStop (i2cREG1);

/*发送开始条件*/
i2cSetStart (i2cREG1);

/*发送字地址*/
i2cSendByte (i2cREG1、Slave_Word_address);

/*轮询模式下的 Transmit data_count 数据数量*/
i2cSend (i2cREG1、DATA_COUNT、TX_Data_Master);

/*等待总线忙被清除*/
while (i2cIsBusy (i2cREG1)=true);

/*等待直到检测到停止*/
while (i2cIsStopDetected (i2cREG1)=0);

/*清除停止条件*/
i2cClearSCD (i2cREG1);

/*在开始下一个块之前使用 Simple Dealya */
/*取决于从属设备准备就绪的速度*/
for (delay=0;delay<100000;delay++);


//主接收功能//

/********* /
/********* /

/*等待 MST 位被清零,这将进行
*清除总线忙后的几个周期*/
while (i2cIsMasterReady (i2cREG1)!= true);

/*配置要与*/通话的从机地址
i2cSetSlaveAdd (i2cREG1、PCF8570_address);

/*将方向设置为发送器*/
/*注意:可选-在 Init 中完成*/
i2cSetDirection (i2cREG1、I2C_transmitter);

/*配置数据计数*/
/*读取之前从器件地址+字地址写入操作*/
i2cSetCount (i2cREG1、receive_data_setup);

/*将模式设置为主设备*/
i2cSetMode (i2cREG1、I2C_MASTER);

/*设置编程计数后停止*/
i2cSetStop (i2cREG1);

/*发送开始条件*/
i2cSetStart (i2cREG1);

/*发送字地址*/
i2cSendByte (i2cREG1、Slave_Word_address);

/*等待总线忙被清除*/
while (i2cIsBusy (i2cREG1)=true);

/*等待直到检测到停止*/
while (i2cIsStopDetected (i2cREG1)=0);

/*清除停止条件*/
i2cClearSCD (i2cREG1);

/********* /
/********* /

/*等待 MST 位被清零,这将进行
*清除总线忙后的几个周期*/
while (i2cIsMasterReady (i2cREG1)!= true);

/*配置要与*/通话的从机地址
i2cSetSlaveAdd (i2cREG1、PCF8570_address);

/*将方向设置为接收器*/
i2cSetDirection (i2cREG1、I2C_RECEIVER);

/*配置数据计数*/
/*注:可选-在 Init 中完成,除非用户想要更改*/
i2cSetCount (i2cREG1、data_count);

/*将模式设置为主设备*/
i2cSetMode (i2cREG1、I2C_MASTER);

/*设置编程计数后停止*/
i2cSetStop (i2cREG1);

/*发送开始条件*/
i2cSetStart (i2cREG1);

/*轮询模式下的 Transmit data_count 数据数量*/
i2cReceive (i2cREG1、DATA_COUNT、RX_Data_Master);

/*等待总线忙被清除*/
while (i2cIsBusy (i2cREG1)=true);

/*等待直到检测到停止*/
while (i2cIsStopDetected (i2cREG1)=0);

/*清除停止条件*/
i2cClearSCD (i2cREG1);

asm (" nop");
asm (" nop");
asm (" nop");

while (1);

/*用户代码结束*/

/*用户代码开始(4)*/
/*用户代码结束*/

--------------------------------------------------

在此代码中,  

问题1:

/*发送开始条件*/
i2cSetStart (i2cREG1);  

高于 API i2cSetStart 发送启动条件吗?

问题2:

/*配置要与*/通话的从机地址
i2cSetSlaveAdd (i2cREG1、PCF8570_address);

API i2cSetSlaveAdd 只是配置从器件地址还是配置和传输从器件地址?

问题3:

/*将方向设置为发送器*/
/*注意:可选-在 Init 中完成*/
i2cSetDirection (i2cREG1、I2C_transmitter);

 i2cSetDirection API 只是 配置读/写位还是发送 读/写位?

问题4:

根据 I2C 协议,通信序列是

1) 1)启动条件

2) 2)发送从器件地址

3) 3)发送 R/W 控制位

4)数据字节

对吧?

上述代码如何遵循此通信序列?  

我需要使用以下序列从 RTC 芯片中写入和读取日期和时间  

写入模式:

1) 1)主器件发出"启动条件"
2) 2)主器件发出"从器件地址"、RV-3129-C3的 ACH;读/写模式的 R/W 位="0"
3) RV-3129-C3确认
4)主器件向 RV-3129-C3发送"页和字地址"
5) RV-3129-C3确认
6)主器件发出“数据”以写入步骤4中指定的地址)
7) 7) RV-3129-C3确认
8) 8)步骤6)和7)可在必要时重复。 在同一存储器页面中、RV-3129-C3将会
自动递增字地址
9) 9)主器件发出"停止条件"

读取模式:

1) 1)主器件发出"启动条件"
2) 2)主器件发出"从器件地址"、RV-3129-C3的 ACH;读/写模式的 R/W 位="0"
3) RV-3129-C3确认
4)主器件向 RV-3129-C3发送"页和字地址"
5) RV-3129-C3确认
6)主器件发出"停止条件"
7) 7)主器件发出"启动条件"
8) 8)主器件发出“从器件地址”、针对 RV-3129-C3的 ADH;针对读取模式的 R/W 位=“1”
9) 9) RV-3129-C3确认:
此时、主器件变为接收器、从器件变为发送器
10) 10) RV-3129-C3从步骤4中指定的“页面和字地址”发出“数据”)
11) 11)师父的感谢:
此时,“Page & Word”地址将自动递增1
12) 12)步骤10)和11)可在必要时重复。 在同一页地址内、将显示"字地址"
自动递增
13) 13)主器件寻址为接收器、可通过在上不生成一个确认来停止数据传输
从发送器发送的最后一个字节。 在这种情况下、必须使用从发送器
将数据线保持在高电平,使主器件能够生成“停止条件”
14) 14)主器件发出"停止条件"

 您是否有用于连接 RTC RV-3129-C3的 MS570LC4357的示例代码来设置日期和时间并读回它们?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="495032" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master "]

    问题1:

    /*发送开始条件*/
    i2cSetStart (i2cREG1);  

    高于 API i2cSetStart 发送启动条件吗?

    [/报价]

    它发送起始条件、salve 地址和读/写位。

    [引用 userid="495032" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master "]

    问题2:

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cREG1、PCF8570_address);

    API i2cSetSlaveAdd 只是配置从器件地址还是配置和传输从器件地址?

    [/报价]

    它只设置从器件地址、不会将地址发送到 I2C 总线。

    [引用 userid="495032" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master "]

    问题3:

    /*将方向设置为发送器*/
    /*注意:可选-在 Init 中完成*/
    i2cSetDirection (i2cREG1、I2C_transmitter);

     i2cSetDirection API 只是 配置读/写位还是发送 读/写位?

    [/报价]

    它只配置 R/W 位、不发送 R 或 T 位。

    [引用 userid="495032" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1029269/tms570lc4357-can-provide-i2c-communication-steps-for-transmit-and-receive-as-master "]

    问题4:

    根据 I2C 协议,通信序列是

    1) 1)启动条件

    2) 2)发送从器件地址

    3) 3)发送 R/W 控制位

    4)数据字节

    对吧?

    上述代码如何遵循此通信序列?  

    [/报价]

    对于大多数应用、它是正确的。  

    i2cSetStart (i2cREG1);将发送#1、#2和#3

    对于某些应用、在#3和#4之间、您必须发送寄存器地址和 R/W 位

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

    您好 、QJ Wang、

    感谢您澄清疑虑。

    我使用了以下代码

    /*从从属设备读取*/
    int I2C_READ_M (短从器件添加、短读添加、短计数、uint8 *缓冲区)

    int i、error、dummy;
    误差= 0;

    if ((i2cREG1->STR & I2C_BUSBUSY)=0)//测试忙线是否占线

    /*清除停止位*/
    i2cREG1->MDR &=~(I2C_STOP_COND);
    /*清除起始位*/
    i2cREG1->MDR &=~(I2C_START_COND);
    /*清除重复模式位*/
    i2cREG1->MDR &=~(I2C_REPEATMODE);

    /*将方向设置为发送器*/
    i2cSetDirection (i2cREG1、I2C_transmitter);
    /*将模式设置为主设备*/
    i2cSetMode (i2cREG1、I2C_MASTER);
    /*配置数据计数*/
    i2cSetCount (i2cREG1、0x01);//表示1字节读取地址

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cREG1、Slave_Add);

    /*发送读取地址*/
    i2cSendByte (i2cREG1、Read_Add);

    /*开始发送*/
    i2cSetStart (i2cREG1);//开始传输:
    //I2C 总线:起始地址-从地址-读取地址

    while (((i2cREG1->STR & I2C_NACK)=0)&&((i2cREG1->STR & I2C_ARDY)=0));

    if ((i2cREG1->STR & I2C_NACK)==0)//检查 Acknoledge 是否为正
    {//应用程序可以继续
    /*将模式设置为主模式,并将接收器设置为*/
    i2cSetMode (i2cREG1、I2C_MASTER);//切换到主接收器
    i2cSetDirection (i2cREG1、I2C_RECEIVER);
    /*设置重复启动模式*/
    i2cREG1->MDR |= I2C_REPEATMODE;

    /*开始发送*/
    i2cSetStart (i2cREG1);//I2C 总线:start--Slave Addr

    (i=0;<Count; i++)

    buff [i]= i2cReceiveByte (i2cREG1);//读取传入数据并存储在数组中
    if (i ==Count-2){
    i2cSetStop (i2cREG1);//生成停止



    其他

    虚拟= i2cREG1->IVR;//清除 NACK 标志
    i2cSetStop (i2cREG1);//生成停止
    error=-2;//将错误设置为 NoAck


    否则{
    错误=-1;//将错误设置为总线忙


    while ((i2cREG1->MDR & I2C_STOP_COND)==1);

    返回错误;



    /*写入从设备*/
    int I2C_Write_M (短从器件添加、短写入添加、短计数、uint8 *缓冲区)

    int 错误、虚拟;//返回代码
    错误= 0x00;//默认、无错误

    if ((i2cREG1->STR & I2C_BUSBUSY)=0)//测试忙线是否占线

    /*将方向设置为发送器*/
    i2cSetDirection (i2cREG1、I2C_transmitter);
    /*将模式设置为主设备*/
    i2cSetMode (i2cREG1、I2C_MASTER);

    /*清除起始位*/
    i2cREG1->MDR &=~(I2C_START_COND);
    /*设置编程计数后停止*/
    i2cSetStop (i2cREG1);

    /*清除 RM 位*/
    i2cREG1->MDR &=~(I2C_REPEATMODE);//不处于重复模式

    /*配置数据计数*/
    i2cSetCount (i2cREG1、Count+1);

    /*配置要与*/通话的从机地址
    i2cSetSlaveAdd (i2cREG1、Slave_Add);

    /*发送开始条件*/
    i2cSetStart (i2cREG1);//I2C 总线:启动-从器件地址

    /*发送写入地址*/
    i2cSendByte (i2cREG1、Write_Add);//发送数据到选择目标寄存器

    if ((i2cREG1->STR & I2C_NACK)==0)//检查 Acknoledge 是否为正

    /*轮询模式下的 Transmit data_count 数据数量*/
    i2cSend (i2cREG1、计数、缓冲器);

    否则{
    虚拟= i2cREG1->IVR;//清除 NACK 标志
    i2cSetStop (i2cREG1);//生成停止
    error=-2;//将错误设置为 NoAck


    否则{
    错误=-1;//将错误设置为总线忙


    while ((i2cREG1->MDR & I2C_STOP_COND)==1);

    返回错误;


    /*用户代码结束*/

    1) 1)写入时、执行卡在行以下

    /*SAFETYMCUSW 28 D MR:NA "找到可能无限的循环-执行序列的硬件状态检查"*/
    while (((i2c->STR &(UINT32) I2C_TX_INT)== 0U)

    }/*等待*/

    (在 void i2cSend (i2cBASE-t * i2c、uint32 length、uint8 * data)函数内)

    在此期间:i2c->STR 具有 100 0000 0000 (0x00000400十六进制),  

    这意味 着 I2C_XSMT    = 0x0400U、 //发送移位为空而不 是*/

    I2C_TX_INT   = 0x0010U、 //发送数据就绪  */

    发送数据准备就绪未被置位。

     I2CDXR 似乎无法应对
    发送移位寄存器。  

    为什么不将 I2CDXR 复制到 发送移位寄存器中???

    i2c->STR 的值在执行到以下行时为0x00000410 (i2cSendByte (i2cREG1、Write_Add);)。

    执行此行(i2cSendByte (i2cREG1、Write_Add);)后、i2c->STR 变为 100 0000 0000 0000 (0x00000400十六进制)

    /*发送写入地址*/
    i2cSendByte (i2cREG1、Write_Add);//发送数据到选择目标寄存器

    2)读取时、执行卡在行以下

    while (((i2cREG1->STR & I2C_NACK)=0)&&((i2cREG1->STR & I2C_ARDY)=0));

    由于这种情况 ((i2cREG1->STR & I2C_ARDY)=0)。  

    在此期间:i2c->STR 具有 100 0000 0000 (0x00000400十六进制),  

    这意味 着 I2C_XSMT    = 0x0400U、 //发送移位为空而不 是*/

     I2C_ARDY    = 0x0004U、 /*访问就绪        */*/

     未 设置访问就绪。

    1) 1) 这些问题的可能路由案例是什么?

    2) 2)是否存在 HAL Cogen 配置问题? 注:PINMUX 正常(无冲突)。

    3) 3)当我启用 中断方法时、执行停留在下面一行

    while (((i2c->STR &(UINT32) I2C_RX_INT)== 0U)

    }/*等待*/

    功能:

    uint8 i2cReceiveByte (i2cBASE-t * i2c)

    /*SAFETYMCUSW 28 D MR:NA "找到可能无限的循环-执行序列的硬件状态检查"*/
    while (((i2c->STR &(UINT32) I2C_RX_INT)== 0U)

    }/*等待*/
    /*用户代码开始(25)*/
    /*用户代码结束*/

    返回(uint8)i2c->DRR;

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

    Manoraj、您好!

    I2C SDA 和 SCL 为开漏。 也就是说、I2C 主设备和从设备只能将这些线路驱动为低电平或使其保持开路。  如果没有 I2C 器件将线路上拉至 Vccio (3.3V)、则外部上拉电阻器会将其下拉。  

    您是否会检查您的设置中是否上拉了 I2C 线路?  

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

    您好、Qj Wang、

    感谢您的澄清。

    I2C 现在工作正常