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.

[参考译文] CCS/TMS320F28035:TMS320F28035 Piccolo I2C 通信从器件

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/648786/ccs-tms320f28035-tms320f28035-piccolo-i2c-communication-slave

器件型号:TMS320F28035

工具/软件:Code Composer Studio

大家好、我正在尝试在两个 Piccolo TMS320F28035 I2C 通信之间进行 I2C 通信。 我被困在了从机侧、该文档解释不多。 我很感谢你们的帮助。我很确定我做了一些错误的事情,但我不知道是什么。

P.S. :我现在不使用诸如轮询 BB、XRDY、RRDY 或 NACK 位之类的中断,只是为了使其保持简单。

以下是我的代码:

########## 主代码(只写)##############################

#define I2C_SLAVE_ADDR       0x0055

void main (void)


   InitSysCtrl();
   InitI2CGpio();\

bool 标志= true;

 I2CA_Init_master ();

for (;;)
   {

     while (GpioDataRegs.GPBDAT.bit.GPIO44 ==0 &&标志)
     {

       GREENLED_ON;
       I2CA_WriteData();
       GREENLED_OFF;
       flag = false;
       //delay_US (1000000);
     }
   }

void I2CA_Init_master (void)

   I2caRegs.I2CSAR = I2C_SLAVE_ADDR;      //从器件地址-
   I2caRegs.I2CPSC.all = 6;       //预分频器-模块时需要7-12MHz
   I2caRegs.I2CCLKL = 10;         //注意:必须为非零
   I2caRegs.I2CCLKH = 5;          //注意:必须为非零
   I2caRegs.I2CIER.ALL = 0;

   I2caRegs.I2CMDR.ALL = 0x0020;  //使 I2C 退出复位

   I2caRegs.I2CFFTX.ALL = 0x6000; //启用 FIFO 模式和 TXFIFO
   I2caRegs.I2CFFRX.ALL = 0x2040; //启用 RXFIFO、清除 RXFFINT、
   DELAY_US (10);
   返回;



void I2CA_WriteData (void){
    uint16 i;
 //  while (I2caRegs.I2CMDR.bit.STP = 1)
  //   {
  //   };
    I2caRegs.I2CSAR = I2C_SLAVE_ADDR;          //从地址寄存器
    I2caRegs.I2CCNT = I2C_NUMBYTES;    //数据计数为4字节
    I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式并复位 TX FIFO
    I2caRegs.I2CDXR = 0xf0;
    I2caRegs.I2CMDR.bit.TRX = 1;
    I2caRegs.I2CMDR.bit.MST = 1;
    I2caRegs.I2CMDR.bit.FREE = 1;
    I2caRegs.I2CMDR.bit.STP= 1;//创建一个停止条件将释放总线、从而使 BB = 0。
    I2caRegs.I2CMDR.bit.STT = 1;//一旦启动起始位、BB = 1再次变为繁忙状态。
    返回;

############################ 从机代码(只读)########################

void main (void){

   InitSysCtrl();
   InitI2CGpio();

  I2CASlave_init();
   DELAY_US (1000000);
 for (;;)
 {
   I2CA_ReceiveData();
 }
 }

void I2CASlave_init (void)


   I2caRegs.I2COAR = I2C_SLAVE_ADDR;      //从地址

   I2caRegs.I2CPSC.all = 6;       //预分频器-模块时需要7-12MHz
   I2caRegs.I2CCLKL = 10;         //注意:必须为非零
   I2caRegs.I2CCLKH = 5;          //注意:必须为非零

   I2caRegs.I2CIER.ALL = 0x00;    //启用 SCD、XRDY、RRDY、ARDY、 NACK 中断...抱歉、不启用任何内容
   I2caRegs.I2CMDR.bit.MST = 0;//进入从机模式
   I2caRegs.I2CMDR.bit.TRX = 0; //接收模式
   I2caRegs.I2CMDR.bit.FREE = 1                 ;//在自由模式下运行,将它设置为零,当数据被接收时将停止。l
   I2caRegs.I2CMDR.ALL = 0x0020;  //启用 IRS

 //          I2caRegs.I2CFFTX.ALL = 0x6000; //启用 FIFO 模式和 TXFIFO
 //          I2caRegs.I2CFFRX.ALL = 0x2040; //启用 RXFIFO、清除 RXFFINT、
   返回;


空 I2CA_ReceiveData (空)

   I2caRegs.I2COAR = I2C_SLAVE_ADDR;      //从地址- EEPROM 控制代码

   I2caRegs.I2CSAR = I2C_SLAVE_ADDR;          //从地址寄存器
   I2caRegs.I2CCNT = 1;//接收计数到4个字节

   //while (I2cRegs.I2CSTR.bit.RRDY = 0){};
   Receive_Data[0]= I2caRegs.I2CDRR;
   返回;

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

    在主器件侧、您在写入数据时不会检查 FIFO 是否已满、也不会检查前一个是否已完成、而尝试启动传输。 我不确定 I2C_NUMBYTES 是什么、但您似乎只向发送寄存器写入一个字节的数据。 它不止一个、在 I2C_NUMBYTES 实际被发送前、不会生成停止条件。

    从器件侧有类似的问题。 在读取 I2CDRR 寄存器之前、您不会检查是否已接收到数据(或者至少您已经注释掉了这样做的代码。)

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

    为此,我很抱歉,实际上我只是想发送1个字节。所以主设备的工作方式是:

    1.检查按钮是否被按下(GPIO44)  {使用标志、以便程序只运行一次}

    2.运行 LOOP /发送数据1字节

    3.停止

    因此、我不需要检查 FIFO 是否已满、如果我不使用 FIFO、我不应该初始化 FIFO、所以我将其取出。

    我参考了以下 TI 社区主题中的代码:

    ***** 大师****

    就主器件而言,我能够看到9个时钟脉冲,即一个开始条件,后跟7位地址,然后是 R/W。 但之后、我的时钟会挂起低电平、因为它会等待我的 Oscilloscope.e2e.ti.com/.../2703.Master.txt 上的 ACK (从未从器件处获得)

    ***** 从设备*****

    对于从器件侧、请找到代码 attached.e2e.ti.com/.../5873.Slave-RX.txt

    就从器件而言、我现在只是尝试接收。所以我将地址轮询为从器件位中断标志。 即 AAS 以检查是否需要它的1,它告诉我从属设备已与主设备建立联系,并且能够验证自己是否为从设备。 变量中的增量将有助于我验证相同的值。

    我知道我的代码有很多错误,但如果您能给我一个关于从代码的头,我将不胜感激。 我不知道我是否在正确的轨道上、因为从端的文档或示例很少。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您提供更多信息。 我不认为您的代码太远。

    如果您停止执行、您的代码在从器件端的什么位置? 它是否卡在检查 AAS 位的 while 环路上? 如果您在"Registers"窗口中查看 I2CSTR 寄存器的状态(在调试时在"View"->"Registers"下打开、并停止应用程序)、则该寄存器的状态是什么?

    惠特尼
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的,你是对的! 因此、我在闪存(F2035)中有主器件端程序、每当我尝试发送字节时、主器件都会在发送从器件地址后挂起、即时钟保持低电平(在示波器上观察)、因为它会等待确认。(完全没问题!)

    然后、在从器件端、如果从主器件接收到的从器件地址与 I2COAR 匹配(我假设)、则会生成一个 ACK。
    如果两个地址都与寻址为从机(AAS)标志匹配,则将设置该标志。 ***** 这是我的代码被卡住的地方,AAS 位永远不会被置位*****
    我认为设置 AAS 标志是 I2C 通信的第一步。

    就 I2CSTR 的状态而言、只有2个位被置位(1)-> XRDY 和 XSMT。 其余被清零。 我观察到这2个位始终置位,即使在 I2CASlave_init 之前也是如此,在 I2CSlave_init 之后也是如此。 当我尝试清除它们时、它不会接受这些值、并且会返回到1。 但我不确定它如何影响我的代码执行。

    我很确定我在从站方面是错的、您能向我推荐任何更改吗? 但我们非常感谢您的帮助。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果在写入 Receive_Data[0]的行上放置断点、它是否会被命中? AAS 可能会被一个停止条件再次设置和清除、因此只需停下来看看它是否在任何时间点停留在环路上并不一定有意义。

    如果在总线保持低电平的情况下等待从器件的 ACK、我有点惊讶、您没有看到 BB 位被置位。 您能否仔细检查 GPIO 配置和硬件连接? 您使用什么进行上拉? 仅器件上的内部还是外部?

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

    *下面是我针对从器件的更新代码。 这只包含 I2C_Slave_init()  和 I2C_ReceiveData()。我没有包含主 器件,因为它是相同的。
     *我很确定我的程序没有设置 AAS 标志、因为如果执行了该操作、变量"i"会递增、绿色 LED 会至少亮起一秒钟(这不是)。

    *是的、我的 BB 在一个开始位和发送的地址后被置位。 当主器件等待一个 ACK 时、时钟被拉至低电平并且 I2CSTR.bit.BB = 1、这表示总线忙。

    * STR 标志位 XSMT 和 XRDY 在之后置位、I2C 使能。 (发送前)
    *但是,发送一个字节后置1的 STR 位是 NACK、ARDY、 XSMT、BB,即全部为1,其余为0。(发送后)


    *对于外部上拉,SDA 和 SCL 线路上都有4.7K 电阻器。
    ################################ MASTER_Transmit ()############################################
    void I2CA_WriteData (void){

        I2caRegs.I2CSAR = I2C_SLAVE_ADDR;          //从地址寄存器

        //检查是否忙
        while (I2cRegs.I2CSTR.bit.BB = 1) {};

        I2caRegs.I2CCNT = 1;                                      //数据计数为1字节
     
        I2caRegs.I2CDXR = DataTransmit[1];      //数据传输是一个包含一些数据的数组
     
        I2caRegs.I2CMDR.bit.TRX = 1;
        I2caRegs.I2CMDR.bit.MST = 1;
        I2caRegs.I2CMDR.bit.FREE = 1;

        I2caRegs.I2CMDR.bit.STP= 1;                  //创建一个停止条件将释放总线、从而使 BB = 0。
        I2caRegs.I2CMDR.bit.STT = 1;                  //一旦启动起始位、BB = 1再次变为繁忙状态。

        返回;


    ********* 从机端 Init 和接收代码
    void I2C_Slave_init (void)

       I2caRegs.I2COAR = I2C_SLAVE_OAL_ADDR;      //从地址-

       I2caRegs.I2CPSC.all = 6;       //预分频器-模块时需要7-12MHz
       I2caRegs.I2CCLKL = 10;         //注意:必须为非零
       I2caRegs.I2CCLKH = 5;          //注意:必须为非零

       I2caRegs.I2CIER.bit.XRDY =1;
       I2caRegs.I2CIER.bit.RRDY=1;
       I2caRegs.I2CIER.bit.ARDY = 1;
       I2caRegs.I2CIER.bit.AAS = 1;    //仅启用寻址作为从机中断。

       I2caRegs.I2CMDR.bit.MST = 0;//进入从机模式//如果 MST = 0且 FDF = 0 TRX 是无关的。依赖 主机模块的命令作为一个 Rx 或 Tx 进行响应。
     
      //I2caRegs.I2CMDR.bit.TRX = 0; //receive mode ->注释、因为它处于无关状态、请参阅 I2C 的表7
       //I2caRegs.I2CMDR.bit.FREE = 1;      //在自由模式下运行,将其设置为零,当数据被接收时将停止。l
       
      I2caRegs.I2CMDR.bit.IRS = 1;  //启用 IRS
       I2caRegs.I2CSTR.ALL = 0;

       返回;


    空 I2CA_ReceiveData (空)

       uint16 i = 0;
       //while (!I2cRegs.I2CSTR.bit.RRDY);

       I2caRegs.I2COAR = I2C_SLAVE_OAL_ADDR;      //从地址
       I2caRegs.I2CCNT = 1;//接收计数到1个字节这一点无关紧要,因为它处于从接收器模式

       I2caRegs.I2CMDR.bit.MST = 0;
       I2caRegs.I2CMDR.bit.NACKMOD = 0;

       while (I2cRegs.I2CSTR.bit.AAS = 1){

           i++;
           Receive_Data[0]= I2caRegs.I2CDRR;
           GREENLED_ON;
           REDLED_OFF;
           Delay_cycles (FSYSCLK);      //等待1秒

       }

    (二

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很抱歉耽误你的回答。 正如我在前面的消息中所说的,AAS 被一个停止条件清除,所以除非您调用 I2CA_ReceiveData()时有完美的计时,否则您可能会错过正在设置的 AAS。 我认为您最好选择轮询 RRDY。

    您是否有示波器或逻辑分析仪捕捉 SDA 和 SCL 上发生的情况?

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

    在这个问题上有什么进展?

    编辑:由于我没有听到您的反馈、我将假定您已经解决了问题。 但是、如果情况并非如此、请随时拒绝回答并向主题添加新的回复!

    惠特尼