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.

[参考译文] TMS320F28035:中断驱动的 I2C 块写入

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/570044/tms320f28035-interrupt-driven-i2c-block-write

器件型号:TMS320F28035

我正在尝试从 示例_2803xI2C_EEPROM 程序执行、该程序发送4个字节、但不发送完整的块。 我的程序无法在中断中旋转足够长的时间来发送64个字符。 我正在更改中断例程、因此当缓冲区中的四个字节被发送时、中断例程将发送下一个4字节、直到整个块被发送。

任何示例或提示

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

    我建议使用 FIFO 模式。 您可以设置发送中断级别、以便在 FIFO 为空时触发另一个中断。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我正在使用 FIFO 模式。 问题在于发送了前4个字节后、我重新加载 I2CDXR、接下来的4个字节和字节4 - 7被发送。 之后不会发生 TXFFINT。 关于为什么我在第三次加载 FIFO 后没有收到中断的任何建议
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    那么、您只会得到一个中断? 是否清除中断的 PIEACK 位? 您的 TX 中断级别设置为什么?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在 i2c_int1a_ISR 中断结束时、我会看到这种情况
    "//启用未来的 I2C (PIE 组8)中断"
    " PieCtrlRegs.PIEACK.all = PIEACK_group8;"
    并将 TX 中断级别设置为1。
    我注意到该示例设置了 I2C cmd、就像 I2caRegs.I2CMDR.all = 0x6E20;并且正是这样设置来理解设置的内容。
    I2caRegs.I2CMDR.bit.BC = 0;//位计数= 0、设置8位字节
    I2caRegs.I2CMDR.bit.FDF = 0;//自由数据格式关闭
    I2caRegs.I2CMDR.bit.STB = 0;//起始字节关闭
    I2caRegs.I2CMDR.bit.IRS = 0;//复位 I2C
    I2caRegs.I2CMDR.bit.IRS = 1;//从复位中释放 I2C
    I2caRegs.I2CMDR.bit.DLB = 0;//数字回路模式关闭
    I2caRegs.I2CMDR.bit.RM = 0;//重复模式关闭
    I2caRegs.I2CMDR.bit.XA = 0;//扩展地址模式关闭、7位寻址
    I2caRegs.I2CMDR.bit.TRX = 1;//发送模式打开
    I2caRegs.I2CMDR.bit.MST = 1;//主控模式打开
    I2caRegs.I2CMDR.bit.STP= 1;//在内部数据计数器达到0时生成一个停止条件
    I2caRegs.I2CMDR.bit.STT = 1;//生成一个启动条件
    I2caRegs.I2CMDR.bit.FREE = 0;//让 I2C 保持运行
    I2caRegs.I2CMDR.bit.NACKMOD = 0;//正常 ACK 模式。

    此格式是否正常?

    为了帮助进行调试、我已将代码剥离、只需发送一个64字节的块。 我不熟悉 TI 论坛。 是否可以发布我的代码?

    感谢你的帮助。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、请发布您的代码。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    此代码被剥离、只需发送一个具有 START 和 STOP 的64字节代码块。 我在每次运行代码之前都复位硬件。 我删除了读取支持、只是尝试发送64个字节一次。

    //######################################################################################################################
    //
    //! 添加到组 F2803x_example_list
    //!

    I2C EEPROM (i2c_EEPROM)


    //!
    //! 此程序需要连接外部 I2C EEPROM
    //! 地址0x50处的 I2C 总线。
    //! 该程序将1-14个字写入 EEPROM 并将其读回。
    //! 写入的数据和写入的 EEPROM 地址都包含在其中
    //! 在消息结构中,\b I2cMsgOut。 数据读回将是
    //! 包含在消息结构中\b I2cMsgIn1。
    //!
    //! 注意此程序仅适用于具有板载 I2C EEPROM 的套件。
    //! (例如 F2803x eZdsp)
    //!
    //! b 监视\b 变量\n
    //! I2cMsgIn1
    //! I2cMsgOut
    //
    //######################################################################################################################
    //$TI 版本:F2803x C/C++头文件和外设示例 V130 $
    //$Release Date:2015年5月8日$
    //版权所有:版权所有(C) 2009-2015 Texas Instruments Incorporated -
    // http://www.ti.com/ 保留所有权利$
    //######################################################################################################################

    #include "DSP28x_Project.h" //设备头文件和示例包括文件
    #include "feTypes.h"
    //注:此示例中使用的 I2C 宏可在中找到
    // DSP2803x_I2C_defines.h 文件

    //此文件中找到的函数的原型语句。

    _interrupt void i2c_int1a_isr (void);
    void pass (void);
    失效失效(失效);
    extern void EepromWP_ClrVal (void);//未受写保护
    extern void EepromWP_SetVal (void);//受写保护;
    extern void I2CA_Init (void);
    extern void InitI2cGpio (void);
    extern bool I2C_EE_CheckBus (void);


    #define I2C_ERROR 0xFFFF
    #define I2C_ARB_LOW_ERROR 0x0001
    #define I2C_Nack_error 0x0002
    #define I2C_BUS_BUS_BUSY_ERROR 0x1000
    #define I2C_STP_NOT_READY_ERROR 0x5555
    #define I2C_NO_FLAGS 0xAAAA
    #define I2C_SUCCESS 0x0000

    //清除状态标志
    #define I2C_CLR_AL_BIT 0x0001
    #define I2C_CLR_Nack_bit 0x0002
    #define I2C_CLR_ARDY_BIT 0x0004
    #define I2C_CLR_RRDY_BIT 0x0008
    #define I2C_CLR_SCD_BIT 0x0020

    //中断源消息
    #define I2C_NO_ISRC 0x0000
    #define I2C_ARB_ISRC 0x0001
    #define I2C_Nack_ISRC 0x0002
    #define I2C_ARDY_ISRC 0x0003
    #define I2C_RX_ISRC 0x0004
    #define I2C_TX_ISRC 0x0005
    #define I2C_SCD_ISRC 0x0006
    #define I2C_AAS_ISRC 0x0007

    // I2CMSG 结构定义
    #define I2C_NO_STOP 0
    #define I2C_Yes_stop 1.
    #define I2C_Receive 0
    #define I2C_Transmit 1.
    #define I2C_MAX_buffer_size 4.

    // I2C 从机状态定义
    #define I2C_NOTSLAVE 0
    #define I2C_ADDR_AS_SLAVE 1.
    #define I2C_ST_MSG_READY 2.

    // I2C 从接收器消息定义
    #define I2C_SND_msg1
    #define I2C_SND_msg2

    // I2C State 定义
    #define I2C_IDLE 0
    #define I2C_SLAVE_RECEIVER 1
    #define I2C_SLAVE_TRANSMTER 2.
    #define I2C_MASTER_RECEIVER 3.
    #define I2C_MASTER_TRANSMER 4.

    // I2CMSG 结构的 I2C 消息命令
    #define I2C_MSGSTAT_INACTIVE 0x0000
    #define I2C_MSGSTAT_SEND_WITHSTOP 0x0010
    #define I2C_MSGSTAT_WRITE_BUSY 0x0011
    #define I2C_MSGSTAT_SEND_NOSTOP 0x0020
    #define I2C_MSGSTAT_SEND_NOSTOP_BUSY 0x0021
    #define I2C_MSGSTAT_RESTART 0x0022
    #define I2C_MSGSTAT_READ_BUSY 0x0023


    #define I2C_SLAVE_ADDR 0x50
    #define I2C_EEPROM_HIGH_ADDR 0x00
    #define I2C_EEPROM_LOW_ADDR 0x30
    #define FIFO_SIZE(4)
    #define packet_size(64)


    /* 16位寄存器(大端字节序)*/

    typedef 结构{
    uint8 MsgCommand;
    uint8 MsgSlaveAddress;
    uint8 NumBytesToSend;
    uint8数字字节 Sent;
    uint8 SendBuffer[packet_size];
    } I2CMSG_OUT;
    I2CMSG_OUT I2cMsgOut;

    uint16 EEpromWriteDataBlock (void);

    void main (void)

    uint16错误;
    uint16 i;

    I2cMsgOut.MsgCommand = I2C_IDLE;
    I2cMsgOut.MsgSlaveAddress = I2C_SLAVE_ADDR;
    I2cMsgOut.NumBytesToSend = packet_size;
    I2cMsgOut.NumBytesSent = 0;
    for (i = 0;i < packet_size;i++)

    I2cMsgOut.SendBuffer[i]= i;




    //步骤1. 初始化系统控制:
    // PLL、安全装置、启用外设时钟
    //此示例函数位于 DSP2803x_SYSCTRL.c 文件中。
    InitSysCtrl();

    //步骤2. 初始化 GPIO:
    //此示例函数位于 DSP2803x_GPIO.c 文件和中
    //说明了如何将 GPIO 设置为其默认状态。
    // InitGpio();
    //仅针对 I2C 功能设置 GP I/O
    InitI2CGpio();

    EepromWP_SetVal ();
    //在 GPIO7上启用 GPIO 输出、将其设置为高电平
    //步骤3. 清除所有中断并初始化 PIE 矢量表:
    //禁用 CPU 中断
    Dint;

    //将 PIE 控制寄存器初始化为默认状态。
    //默认状态为禁用所有 PIE 中断和标志
    //被清除。
    //此函数位于 DSP2803x_PIECTRL.c 文件中。
    InitPieCtrl();

    //禁用 CPU 中断并清除所有 CPU 中断标志:
    IER = 0x0000;
    IFR = 0x0000;

    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //这将填充整个表,即使是中断也是如此
    //在本例中未使用。 这对于调试很有用。
    //可以在 DSP2803x_DefaultIsr.c 中找到 shell ISR 例程
    //此函数可在 DSP2803x_PieVect.c 中找到
    InitPieVectTable();

    //此示例中使用的中断被重新映射到
    //此文件中的 ISR 函数。
    EALLOW;//这是写入 EALLOW 受保护寄存器所必需的
    PieVectTable.I2CINT1A =&i2c_int1a_ISR;
    EDIS;//这是禁止写入 EALLOW 受保护寄存器所必需的

    //步骤4. 初始化 I2C 外设:
    I2CA_Init();



    //启用此示例所需的中断

    //在 PIE:组8中断1中启用 I2C 中断1
    PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

    //启用连接到 PIE 组8的 CPU INT8
    IER |= M_INT8;
    EINT;

    I2caRegs.I2CMDR.bit.IRS = 0;
    I2caRegs.I2CMDR.bit.IRS = 1;//复位 I2C

    I2cMsgOut.MsgCommand = I2C_MSGSTAT_SEND_WITHSTOP;

    //////////////////////////////////////////////////////////////////////
    //将数据写入 EEPROM 部分//
    //////////////////////////////////////////////////////////////////////

    //检查外发消息是否应发送。
    //在本例中,初始化后发送一个停止位。
    if (I2cMsgOut.MsgCommand =I2C_MSGSTAT_SEND_WITHSTOP)

    错误= EEpromWriteDataBlock();
    //如果通信已正确启动,请将 msg 状态设置为忙
    //并更新中断服务例程的 CurrentMsgPtr。
    //否则,不执行任何操作,然后重试下一个循环。 发送一条消息
    //启动后、I2C 中断将处理其余中断。 搜索
    // i2c_EEPROM_ISR.c 文件中的 i2c_int1a_ISR。
    如果(错误= I2C_Success)


    //I2cMsgOut.MsgCommand = I2C_MSGSTAT_WRITE_BUSY;

    }//写入段结束
    for (;;)

    i++;

    ////////////////////////////////////////////////////////////////////////
    //从 EEPROM 部分读取数据//
    ////////////////////////////////////////////////////////////////////////

    }// main 结束

    #define CLEAR_FFRX_REG(0)
    #define CLEAR_FFTX_REG(0)
    #define TX_FF_INT_LEVEL(1)

    空 InitI2CGpio()

    EALLOW;

    /*为所选引脚启用内部上拉*/
    //用户可以启用或禁用上拉。
    //这将启用指定引脚的上拉电阻。
    GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;//启用 GPIO32的上拉电阻(SDAA)
    GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;//启用 GPIO33的上拉电阻器(SCLA)


    /*将所选引脚的限定条件设置为仅异步*/
    //这将为所选引脚选择异步(无限定条件)。


    GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3;//异步输入 GPIO32 (SDAA)
    GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;//异步输入 GPIO33 (SCLA)

    /*使用 GPIO 寄存器配置 I2C 引脚*/
    GpioCtrlRegs.GPBMUX1.bit.GPIO32=1;//将 GPIO32配置为 SDAA 操作
    GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;//为 SCLA 操作配置 GPIO33


    //在 GPIO17上启用 GPIO 输出、将其设置为高电平
    GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;//启用 GPIO17上的上拉
    GpioDataRegs.GPASET.bit.GPIO17 = 1;//加载输出锁存器
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0;// GPIO17 = GPIO17
    GpioCtrlRegs.GPADIR.bit.GPIO17 = 1;// GPIO17 =输出


    EDIS;



    uint16 EEpromWriteDataBlock( void )

    uint8 i;

    // I2CFFRx = 0
    I2caRegs.I2CSAR = I2cMsgOut.MsgSlaveAddress;

    //检查总线是否占线
    IF (I2cRegs.I2CSTR.bit.BB = 1)

    返回 I2C_BUS_BUS_BUSY_ERROR;



    I2caRegs.I2CCNT = packet_size;

    I2cMsgOut.MsgCommand = I2C_MSGSTAT_SEND_WITHSTOP;
    EepromWP_SetVal ();

    I2caRegs.I2CMDR.bit.BC = 0;//位计数= 0、设置8位字节
    I2caRegs.I2CMDR.bit.FDF = 0;//自由数据格式关闭
    I2caRegs.I2CMDR.bit.STB = 0;//起始字节关闭
    I2caRegs.I2CMDR.bit.IRS = 0;//复位 I2C
    I2caRegs.I2CMDR.bit.IRS = 1;//从复位中释放 I2C
    I2caRegs.I2CMDR.bit.DLB = 0;//数字回路模式关闭
    I2caRegs.I2CMDR.bit.RM = 0;//重复模式关闭
    I2caRegs.I2CMDR.bit.XA = 0;//扩展地址模式关闭、7位寻址
    I2caRegs.I2CMDR.bit.TRX = 1;//发送模式打开
    I2caRegs.I2CMDR.bit.MST = 1;//主控模式打开
    I2caRegs.I2CMDR.bit.STP= 1;//在内部数据计数器达到0时生成一个停止条件
    I2caRegs.I2CMDR.bit.STT = 1;//生成一个启动条件
    I2caRegs.I2CMDR.bit.FREE = 0;//让 I2C 保持运行
    I2caRegs.I2CMDR.bit.NACKMOD = 0;//正常 ACK 模式。

    I2caRegs.I2CEMDR.bit.BCM = 0;//

    I2caRegs.I2CIER.ALL = 0;//使用 FF 中断

    for (i = 0;i < FIFO_SIZE;i++)

    I2cRegs.I2CDXR = I2cMsgOut.SendBuffer[I2cMsgOut.NumBytesSent++];

    I2caRegs.I2CFFTX.bit.TXFFRST = 0;//复位 TX FIFO
    I2caRegs.I2CFFTX.bit.TXFFIL = TX_FF_INT_LEVEL;//当缓冲区有一个字节要发送时触发中断
    I2caRegs.I2CFFTX.bit.TXFFIENA=1;//启用发送 FIFO 中断
    I2caRegs.I2CFFTX.bit.TXFFRST = 1;//启用 TF TIFO 操作
    I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;//按照 spufz9d 表21的建议清除发送 FIFO 中断
    I2caRegs.I2CFFTX.bit.I2CFFEN = 1;//启用 FF 模式

    // I2CFFTX = 0x60A1

    返回 I2C_Success;


    _interrupt void i2c_int1a_isr (void)// I2C-A

    uint16 i、intSource;
    IntSource = I2caRegs.I2CISRC.ALL;

    if (IntSource =I2C_TX_ISRC)

    if (I2cMsgOut.MsgCommand =I2C_MSGSTAT_SEND_WITHSTOP)

    //检查中断源
    //if (((IntSource =I2C_TX_ISRC)||
    //(I2caRegs.I2CFFTX.bit.TXFFINT =1)
    if (I2caRegs.I2CFFTX.bit.TXFFINT =1)

    I2caRegs.I2CFFTX.bit.TXFFINTCLR = 1;//清除中断
    I2caRegs.I2CFFTX.bit.TXFFIENA=0;//禁用中断
    if (I2cMsgOut.NumBytesSent <= I2cMsgOut.NumBytesToSend){
    // TX 缓冲区应为空,重新加载
    for (i = 0;i < FIFO_SIZE;i++)

    I2cRegs.I2CDXR = I2cMsgOut.SendBuffer[I2cMsgOut.NumBytesSent++];

    I2caRegs.I2CFFTX.bit.TXFFIENA=1;//重新启用中断

    其他

    EepromWP_ClrVal ();
    I2cMsgOut.MsgCommand = I2C_MSGSTAT_INACTIVE;




    //启用未来的 I2C (PIE 组8)中断
    PieCtrlRegs.PIEACX.ALL = PIEACK_group8;


    void EepromWP_ClrVal (void)//不受写保护

    GpioDataRegs.GPACLEAR.bit.GPIO17 = 1;//加载输出锁存// EEPROM 不具有写保护


    void EepromWP_SetVal (void)//受写保护;

    GpioDataRegs.GPASET.BIT.GPIO17 = 1;//加载输出锁存= 1;// EEPROM 不具有写保护


    空 InitI2cGpio()

    EALLOW;

    /*为所选引脚启用内部上拉*/
    //用户可以启用或禁用上拉。
    //这将启用指定引脚的上拉电阻。
    GpioCtrlRegs.GPBPUD.bit.GPIO32 = 0;//启用 GPIO32的上拉电阻(SDAA)
    GpioCtrlRegs.GPBPUD.bit.GPIO33 = 0;//启用 GPIO33的上拉电阻器(SCLA)


    /*将所选引脚的限定条件设置为仅异步*/
    //这将为所选引脚选择异步(无限定条件)。


    GpioCtrlRegs.GPBQSEL1.bit.GPIO32 = 3;//异步输入 GPIO32 (SDAA)
    GpioCtrlRegs.GPBQSEL1.bit.GPIO33 = 3;//异步输入 GPIO33 (SCLA)

    /*使用 GPIO 寄存器配置 I2C 引脚*/
    GpioCtrlRegs.GPBMUX1.bit.GPIO32=1;//将 GPIO32配置为 SDAA 操作
    GpioCtrlRegs.GPBMUX1.bit.GPIO33 = 1;//为 SCLA 操作配置 GPIO33

    //在 GPIO8 - GPIO11上启用 GPIO 输出、将其设置为高电平
    GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;//启用 GPIO17上的上拉
    GpioDataRegs.GPASET.bit.GPIO17 = 1;//加载输出锁存器
    GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 0;// GPIO17 = GPIO17
    GpioCtrlRegs.GPADIR.bit.GPIO17 = 1;// GPIO17 =输出

    EDIS;


    空 I2CA_Init (空)

    //初始化 I2C
    I2caRegs.I2CSAR = 0x0050;//从器件地址- EEPROM 控制代码

    I2caRegs.I2CPSC.all = 6;//预分频器-模块时钟需要7-12MHz
    I2caRegs.I2CCLKL = 500;//10;//注意:必须为非零
    I2caRegs.I2CCLKH = 500;//5;//注意:必须为非零
    I2caRegs.I2CIER.ALL = 0x24;//启用 SCD 和 ARDY 中断

    I2caRegs.I2CMDR.ALL = 0x0020;//使 I2C 退出复位
    //挂起时停止 I2C
    I2caRegs.I2CFFTX.ALL = 0x6000;//启用 FIFO 模式和 TXFIFO

    I2caRegs.I2CFFRX.ALL = 0;//复位 RXFFINT、

    返回;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是否使用示波器检查了 SCL 和 SDA 线路、以确保从器件不是 NACKing 或保持 SCL 为低电平? 在您未能获得第二个中断后、I2CSTR、I2CMDR 和 I2CFFTX 寄存器中的值是多少?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我发现连接问题。 当前我发送了四个字节、但从未收到中断! 发送完第四个字节后、SDA 为高电平、SCL 为低电平。 I2CSTR 为0x1010、I2CMDR 为0x4E20、I2CFFTX 为0x60A1。

    uint16 EEpromWriteDataBlock( void )

    uint16 i;
    IF (I2caRegs.I2CMDR.bit.STP==1)

    返回 I2C_STP_NOT _READY_ERROR;

    I2caRegs.I2CSAR = I2cMsgOut.MsgSlaveAddress;

    //检查总线是否占线
    IF (I2cRegs.I2CSTR.bit.BB = 1)

    返回 I2C_BUS_BUS_BUSY_ERROR;

    I2caRegs.I2CCNT = packet_size;
    for (i = 0;i < FIFO_SIZE;i++)
    {//包含2个地址字节和前2个数据字节。
    I2cRegs.I2CDXR = I2cMsgOut.SendBuffer[I2cMsgOut.NumBytesSent++];

    I2cMsgOut.MsgCommand = I2C_MSGSTAT_SEND_WITHSTOP;
    EepromEnableWriting();
    I2caRegs.I2CFFTX.ALL = 0x6021;
    I2caRegs.I2CIER.ALL = 0x20;// dtr 0x20;//使用 FF 中断
    I2caRegs.I2CMDR.ALL = 0x6E20;
    返回 I2C_Success;


    我有一个 Beagle I2C 分析器、我将在下一个查看它。 有什么问题吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您是否在 PIE 中正确设置了中断。 请注意、I2C FIFO 中断与正常/状态中断位于不同的通道上。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    灌篮、灌篮 键盘对前额的印象。 完全错过了 PIE 的变化 我在看 ISR、错过了 PIE。 今天我将介绍 PIE。

    再次感谢