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.

[参考译文] TMS320F28335:I2C 停止条件

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/646785/tms320f28335-i2c-stop-condition

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

你(们)好

我想使用 i2c 连接外部 EEPROM。  我更喜欢使用 Rm=1、并且我使用 ARDY 和 NACK 中断来控制传输。 我可以 选择器件、设置页地址 和发送 所有页字节(256)、但此时如果我通过在 CMDR 寄存器中设置 STP=1发送停止条件、我会收到仲裁失败中断和 NACK 中断? 我出什么问题了吗?

此致

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

    以下是示例代码:

    typedef 枚举

       Wait_for_CMD、
       select_device、
       SEND_HI_ADDRESS、
       SEND_LO_ADDRESS、
       START_READ_DATA、
       Read_data、
       SEND_STOP、
       完成、
       Write_data、
       WRITE_STOP、
       start_write_pool、
       Write_Pool、
       DEVICE_NACK
    } I2C_FSM_States;

    typedef 枚举

       I2C_NO_CMD、
       I2C_WRITE_EEPROM、
       I2C_READ_EEPROM
    } I2C_COMMAND_VALUES;

    typedef 结构

       I2C_FSM_States 状态;
       I2C_COMMAND_VALUES cmd;
       易失性 bool 完成;
       易失性 bool NACK;
       uint32_t 地址;
       int16_t n_Reads;
       int16_t n_writes;
       uint16_t SAR;
       int16_t TRx_counter;
       int16_t 重试;
    } I2C_DATA_TAG;

    I2C_DATA_TAG i2c;

    /*====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
       函数名称:
       目的:
       描述:
       域:
       精度:
       注:
     ==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== *
    中断空 i2c_int1a_isr (空)

    //设置中断优先级:
    volatile uint16_t TempPIEIER = PieCtrlRegs.PIEIER8.all;
    uint16_t tmp;

       IER |= M_INT8;
       IER &= MINT8;
       PieCtrlRegs.PIEIER8.ALL &= MG81;
       PieCtrlRegs.PIEACX.ALL = 0xFFFF;
       asm (" NOP");
       EINT;

       //在此处插入 ISR 代码...
       tmp = I2caRegs.I2CISRC.ALL;
       交换机(tmp & 0x3)
       {
       情况 I2C_NO_ISRC:
           tmp = 0;
           中断;

       案例 I2C_ARB_ISRC:
           tmp = 0;
           中断;

       I2C_Nack_ISRC 案例:
           I2C.nack = true;
           中断;

       I2C_ARDY_ISRC 案例:
           I2c.done = true;
           中断;

       I2C_RX_ISRC 案例:
           tmp = 0;
           中断;

       I2C_TX_ISRC 案例:
           tmp = 0;
           中断;

       I2C_SCD_ISRC 案例:
           tmp = 0;
           中断;

       案例 I2C_AAS_ISRC:
           tmp = 0;
           中断;
       }

       //恢复保存的寄存器:
       Dint;
       PieCtrlRegs.PIEIER8.ALL = TempPIEIER;

    /*====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
       函数名称:
       目的:
       描述:
       域:
       精度:
       注:
     ==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== *
    void i2c_fSM (void)

       交换机(i2c.state)
       {
       案例 WAIT_TO_CMD:
           if (i2c.cmd!= I2C_NO_CMD)
           {
               // 准备 SAR
               I2C.SAR =(i2c.address 和0x3FFFF)>> 16;
               I2C.SAR = i2c.SAR << 1;
               I2C.SAR =(i2c.SAR | DSC_Musk)>> 1;
               // 下一状态
               I2C.state = select_device;
           }
           中断;

       案例 select_device:
           //
           I2C.DONE = false;
           I2C.nack = false;
           // 开始操作
           I2caRegs.I2CMDR.bit.MST = 1;
           I2caRegs.I2CMDR.bit.RM = 1;
           I2caRegs.I2CMDR.bit.TRX = 1;
           I2caRegs.I2CSAR = i2c.SAR;
           I2caRegs.I2CMDR.bit.STT = 1;
           // 下一状态
           I2C.state = SEND_HI_ADDRESS;
           中断;

       案例 SEND_HI_ADDRESS:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CDXR =(i2c.address >> 8)& 0xFF;
                   // 下一状态
                   I2C.state = SEND_LO_ADDRESS;
               }
           }
           中断;

       案例 SEND_LO_ADDRESS:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CDXR = i2c.address & 0xFF;
                   交换机(i2c.cmd)
                   {
                   I2C_WRITE_EEPROM 案例:
                       I2C.TRx_COUNTER = 0;
                       // 下一状态
                       I2C.state = write_data;
                       中断;

                   I2C_READ_EEPROM 案例:
                       I2C.TRx_COUNTER = 0;
                       // 下一状态
                       I2C.state = start_read_data;
                       中断;

                   默认值:
                       中断;
                   }
               }
           }
           中断;

       案例 start_read_data:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CMDR.bit.TRX = 0;
                   I2caRegs.I2CMDR.bit.STT = 1;
                   // 下一状态
                   I2C.state = read_data;
               }
           }
           中断;

       案例 READ_DATA:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   READ_DATA[i2c.TRx_COUNTER++]= I2caRegs.I2CDRR;
                   if (i2c.TRx_counter =i2c.n_Readses)
                   {
                       // 下一状态
                       I2C.state = send_stop;
                   }
                   其他
                   {
                       // 下一状态
                       I2C.state = read_data;
                   }
               }
           }
           中断;

       案例 SEND_STOP:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CMDR.bit.STP= 1;
                   // 下一状态
                   I2C.state =完成;
               }
           }
           中断;

       案例完成:
           如果(i2c.done)
           {
               I2C.DONE = false;
               I2C.cmd = I2C_NO_CMD;
               // 下一状态
               I2C.state = WAIT_TO_CMD;
           }
           中断;

       案例 WRITE_DATA:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CDXR = WRITE_DATA[i2c.TRx_COUNTER++];
                   if (i2c.TRx_counter =i2c.n_writes)
                   {
                       // 下一状态
                       I2C.state = WRITE_STOP;
                   }
                   其他
                   {
                       // 下一状态
                       I2C.state = write_data;
                   }
               }
           }
           中断;

       案例 WRITE_STOP:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   // 下一状态
                   I2C.state = device_nack;
               }
               其他
               {
                   I2caRegs.I2CMDR.bit.STP= 1;
                   // 下一状态
                   I2C.state =完成;
               }
           }
           中断;

       案例 start_WRITE_POOL:
           如果(i2c.done)
           {
               I2C.DONE = false;
               I2C.nack = false;
               I2C.RETRY = 0;
               I2caRegs.I2CMDR.bit.MST = 1;
               I2caRegs.I2CMDR.bit.RM = 1;
               I2caRegs.I2CMDR.bit.TRX = 1;
               I2caRegs.I2CSAR = i2c.SAR;
               I2caRegs.I2CMDR.bit.STT = 1;
               // 下一状态
               I2C.state = write_pool;
           }
           中断;

       案例 Write_Pool:
           如果(i2c.done)
           {
               I2C.DONE = false;
               if (i2c.nack)
               {
                   I2C.RETRY ++;
                   I2caRegs.I2CMDR.bit.MST = 1;
                   I2caRegs.I2CMDR.bit.RM = 1;
                   I2caRegs.I2CMDR.bit.TRX = 1;
                   I2caRegs.I2CSAR = SAR;
                   I2caRegs.I2CMDR.bit.STT = 1;
                   // 下一状态
                   I2C.state = write_pool;
               }
               其他
               {
                   I2caRegs.I2CMDR.bit.STP= 1;
                   // 下一状态
                   I2C.state =完成;
               }
           }
           中断;

       案例 DEVICE_NACK:
           中断;

       默认值:
           中断;
       }

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

    只要您发送 STP 位命令、就会出现此问题? 我看到您的程序在三种情况下发送 STP 命令。

    您能否尝试在程序的不同状态下检查 I2CMDR 和 I2CSTR 寄存器? 在发送 STP 条件之前和之后比较他们的值、看看您是否可以对问题有一些了解。 另请尝试检查 I2CISRC 寄存器中正在设置的 INTCODE。

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

    大家好、Kevin

    我使用另一种方法来使用 I2C 来解决问题... 但如果收到 NACK、我会遇到问题、似乎无法在收到 NACK 后恢复正确的通信。 那么、管理 NACK 的最佳方式是什么? 我应该复位 I2C 外设吗?

    此致

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

    尊敬的 Luca:

    C2000ware 中的 I2C 示例可能会对您有所帮助。

    目录:C:\ti\c2000Ware_1_00_02_00\device_support\F2833x\examples\i2c_eeprom

    您可能需要与以下代码部分类似的内容:

    //
    //中断源=寄存器访问就绪
    //此中断用于确定何时设置 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;
    }
    } 

    如果在初始从器件寻址之后接收到 Nacks、则示例代码的另一部分会处理 Nacks。

    希望这对您有所帮助、

    Kevin