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.

[参考译文] LAUNCHXL-F28379D:修改 i2c-ex2-EEPROM 示例以实现简单的单传感器 i2c 通信

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/947543/launchxl-f28379d-modify-the-i2c-ex2-eeprom-example-for-simple-single-sensor-i2c-communication

器件型号:LAUNCHXL-F28379D

大家好、

我不熟悉这一点、如果可以的话、请您解释一下、而不是多说少。 )

我需要设置与传感器的连接、以便通过 I2C 进行距离测量。 我已经编写了用于初始化和范围测量的函数、只是一组简单的寄存器读取和写入执行。 现在、我 要修改此示例以符合我的目的:

/文件:  I2C_ex2_EEPROM.c

//
//包含的文件
//
#include "driverlib.h"
#include "device.h"

//
//定义
//
#define SLAVE_ADDRESS              0x50 //我的新地址为0x29
#define EEPROM_HIGH_ADDR           0x00 //为了进行初始化、我有大约30个高地址和低地址
#define EEPROM_LOW_ADDR            0x30 //要写入保存在结构中使用的数组中的值
在                  本例中为#define NUM_Bytes 8 // Just 1
#define MAX_BUFFER_SIZE            14     //目前最大值为14,原因是
                                           // 2个地址字节和16字节
                                           // FIFO

//
// I2CMsg 结构的 I2C 消息状态
//
#define MSG_STATUS_INACTIVE        0x0000 //消息未使用,请勿发送
#define MSG_STATUS_SEND_WITHSTOP   0x0010 //发送带有停止位的消息
#define MSG_STATUS_WRITE_BUSY      0x0011 //已发送消息,等待 STOP
#define MSG_STATUS_SEND_NOSTOP     0x0020 //发送无停止位的消息
#define MSG_STATUS_SEND_NOSTOP_BUSY 0x0021 //已发送消息,等待 ARDY
#define MSG_STATUS_RESTART         0x0022 //准备成为主接收器
#define MSG_STATUS_READ_BUSY       0x0023 //在读取数据之前等待 STOP

//
//读取和写入函数的错误消息
//
#define ERROR_BUS_BUS_BUSY             0x1000
#define ERROR_STOP_NOT_READY       0x5555
#define SUCCESS                    0x0000

//
// Typedefs
//
结构 I2CMsg

   uint16_t msgStatus;                 //字指示 msg 处于何种状态。
                                        //参见上面的 MSG_STATUS_*定义。
   uint16_t slaveAddr;                 //绑定到消息的从器件地址。
   uint16_t numBytes;                  //消息中有效字节的数量。
   uint16_t memoryHighAddr;            //相关数据的 EEPROM 地址
                                        //带有消息(高字节)。
   uint16_t memoryLowAddr;             //相关数据的 EEPROM 地址
                                        //带有消息(低字节)。
   uint16_t msgBuffer[MAX_Buffer_SIZE];//阵列保存消息数据。
};

//
//全局
//
struct I2CMsg i2cMsgOut ={MSG_STATUS_SEND_WITHSTOP、
                          Slave_address、
                          num_Bytes、
                          EEPROM_HIGH_ADDR、/更高 版本、我将为每次通信定义新结构
                          EEPROM_LOW_ADDR、
                          0x01、               //消息字节
                          0x23、
                          0x45、
                          0x67、
                          0x89、
                          0xAB、
                          0xCD、
                          0xEF};
struct I2CMsg i2cMsgIn ={MSG_STATUS_SEND_NOSTOP、
                          Slave_address、
                          num_Bytes、
                          EEPROM_HIGH_ADDR、//later 我将为每次通信定义新结构
                          EEPROM_LOW_ADDR};

struct I2CMsg *currentMsgPtr;                  //用于中断

uint16_t passCount = 0;//我不需要
uint16_t failcount = 0;

//
//函数原型
//
void initI2C (void);
uint16_t ReadData (struct I2CMsg *msg);
uint16_t writeData (struct I2CMsg *msg);

void fail (void);//我不需要
void pass (void);

_interrupt void i2cAISR (void);

//
//主函
//
void main (void)

   uint16_t 错误;
   uint16_t i;

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

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

   //
   //初始化 GPIO 32和33,分别用作 SDA 和 SCL A
   //
   GPIO_setPinConfig (GPIO_32_SDAA);
   GPIO_setPadConfig (32、GPIO_PIN_TYPE_PULLUP);
   GPIO_setQualificationMode (32、GPIO_QUAL_ASYNCx);

   GPIO_setPinConfig (GPIO_33_SCLA);
   GPIO_setPadConfig (33、GPIO_PIN_TYPE_PULLUP);
   GPIO_setQualificationMode (33、GPIO_QUAL_异 步);

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

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

   //
   //此示例中使用的中断被重新映射到 ISR 函数
   //在此文件中找到。
   //
   interrupt_register (INT_I2CA、&i2cAISR);//我认为这里的中断被设置到 i2cAISR 函数上以进行中断处理

   //
   //设置 I2C 使用,将其初始化为 FIFO 模式
   //
   initi2C();

   //
   //清除传入消息缓冲区
   //
   对于(I = 0;I < MAX_BUFFER_SIZE;I++)
   {
       i2cMsgIn.msgBuffer[i]= 0x0000;
   }

   //
   //将中断中使用的消息指针设置为指向传出消息
   //
   currentMsgPtr =&i2cMsgOut;

   //
   //启用此示例所需的中断
   //
   INTERRUPT_ENABLE (INT_I2CA);

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

   //
   //无限循环
   //
   while (1)
   {
       //
       //****将数据写入 EEPROM 部分****
       //
       //检查外发消息是否应发送。 在这里
       //示例它被初始化以使用停止位发送。
       //
       if (i2cMsgOut.msgStatus = MSG_STATUS_SEND_WITHSTOP)
       {
           //
           //将数据发送到 EEPROM
           //
           错误= writeData (&i2cMsgOut);

           //
           //如果通信已正确启动,请将 msg 状态设置为忙
           //并更新中断服务例程的当前 MsgPtr。
           //否则,不执行任何操作,然后重试下一个循环。 发送一条消息
           //启动后、I2C 中断将处理其余中断。 请参阅
           //函数 i2cAISR()。
           //
           if (错误==成功)
           {
               currentMsgPtr =&i2cMsgOut;
               i2cMsgOut.msgStatus = MSG_STATUS_WRITE_BUSY;
           }
       }

       //
       //****从 EEPROM 部分读数据****
       //
       //检查外发消息状态。 如果状态为、则绕过读取段
       //未处于非活动状态。
       //
       if (i2cMsgOut.msgStatus = MSG_STATUS_INACTIVE)
       {
           //
           //检查传入消息状态
           //
           if (i2cMsgIn.msgStatus = MSG_STATUS_SEND_NOSTOP)
           {
               //
               //发送 EEPROM 地址设置
               //
               while (ReadData (&i2cMsgIn)!=成功)
               {
                   //
                   //可以设置一个尝试计数器来打破无穷大
                   // while 循环。 EEPROM 会在它发出否定应答时发回一个否定应答
                   //执行写操作。 即使是写入
                   //此时已完成,EEPROM 仍可以
                   //繁忙的数据编程。 因此、多个
                   //必须尝试。
                   //
               }

               //
               //更新当前消息指针和消息状态
               //
               currentMsgPtr =&i2cMsgIn;
               i2cMsgIn.msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY;
          }

           //
           //一旦消息经过设置内部地址的过程
           //在 EEPROM 中、发送重新启动以从读取数据字节
           // EEPROM。 完成公报并停留一会。 msgStatus 为
           //在中断服务例程中更新。
           //
           否则、if (i2cMsgIn.msgStatus = MSG_STATUS_RESTART)
           {
               //
               //读取数据部分
               //
               while (ReadData (&i2cMsgIn)!=成功)
               {
                   //
                   //可以设置一个尝试计数器来打破无穷大
                   // while 循环。
                   //
               }

               //
               //更新当前消息指针和消息状态
               //
               currentMsgPtr =&i2cMsgIn;
               i2cMsgIn.msgStatus = MSG_STATUS_READ_BUSY;
           }
       }
   }


//
// initI2C -用于在 FIFO 模式中配置 I2C A 的函数。
//
无效
initi2C()

   //
   //必须在配置 I2C 之前将其复位
   //
   I2C_DisableModule (I2CA_BASE);

   //
   // I2C 配置。 使用占空比为33%的400kHz I2CCLK。
   //
   I2C_initMaster (I2CA_BASE、DEVICE_SYSCLK_FREQ、400000、I2C_DUTYCYCLE _33);
   I2C_setBitCount (I2CA_BASE、I2C_BITCOUNT_8);
   I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);
   I2C_setEmulationMode (I2CA_BASE、I2C_emulation_free_run);

   //
   //启用停止条件和寄存器访问就绪中断
   //
   I2C_enableInterrupt (I2CA_BASE、I2C_INT_STOP_Condition |
                       I2C_INT_REG_ACCESS_RDY);

   //
   // FIFO 配置
   //
   I2C_enableFIFO (I2CA_BASE);
   I2C_clearInterruptStatus (I2CA_BASE、I2C_INT_RXFF | I2C_INT_TXFF);

   //
   //配置完成。 启用模块。
   //
   I2C_enableModule (I2CA_BASE);


//
// writeData -发送要写入 EEPROM 的数据的函数
//
uint16_t
writeData (struct I2CMsg *msg)

   uint16_t i;

   //
   //等待 STP 位从任何先前的主设备清零
   //通信。 模块将该位清零的时间延迟到之后
   // SCD 位被置位。 如果在启动新的之前没有检查该位
   //消息、I2C 可能会被混淆。
   //
   if (I2C_getStopConditionStatus (I2CA_BASE))
   {
       返回(ERROR_STOP_NOT _READY);
   }

   //
   //设置从地址
   //
   I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);

   //
   //检查总线是否占线
   //
   IF (I2C_isBusy (I2CA_BASE))
   {
       return (error_bus_busy);
   }

   //
   //设置要发送 msgBuffer 和地址的字节数
   //
   I2C_setDataCount (I2CA_BASE、(msg->numBytes + 2));

   //
   //设置要发送的数据
   //
   i2C_putData (I2CA_BASE、msg->memoryHighAddr);
   i2C_putData (I2CA_BASE、msg->memoryLowAddr);

   对于(i = 0;i < msg->numBytes;i++)//仅为我的目的使用1个字节
   {
       I2C_putData (I2CA_BASE、msg->msgBuffer[i]);
   }

   //
   //将 START 作为主发送器发送
   //
   I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
   I2C_sendStartCondition (I2CA_BASE);
   I2C_sendStopCondition (I2CA_BASE);

   返回(成功);


//
// ReadData -准备从 EEPROM 读取的数据的函数
//
uint16_t
ReadData (struct I2CMsg *msg)

   //
   //等待 STP 位从任何先前的主设备清零
   //通信。 模块将该位清零的时间延迟到之后
   // SCD 位被置位。 如果在启动新的之前没有检查该位
   //消息、I2C 可能会被混淆。
   //
   if (I2C_getStopConditionStatus (I2CA_BASE))
   {
       返回(ERROR_STOP_NOT _READY);
   }

   //
   //设置从地址
   //
   I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);

   //
   //如果我们处于地址设置阶段,则发送地址时不使用
   //停止条件。
   //
   if (msg->msgStatus =MSG_STATUS_SEND_NOSTOP)
   {
       //
       //检查总线是否占线
       //
       IF (I2C_isBusy (I2CA_BASE))
       {
           return (error_bus_busy);
       }

       //
       //将数据发送到设置 EEPROM 地址
       //
       I2C_setDataCount (I2CA_BASE、2);
       i2C_putData (I2CA_BASE、msg->memoryHighAddr);
       i2C_putData (I2CA_BASE、msg->memoryLowAddr);
       I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
       I2C_sendStartCondition (I2CA_BASE);
   }
   否则(msg->msgStatus =MSG_STATUS_RESTART)
   {
       //
       //地址设置阶段已完成。 现在设置预期的字节数
       //并将重新启动作为主接收器发送。
       //
       I2C_setDataCount (I2CA_BASE、(msg->numBytes));
       I2C_setConfig (I2CA_BASE、I2C_MASTER_Receive_MODE);
       I2C_sendStartCondition (I2CA_BASE);
       I2C_sendStopCondition (I2CA_BASE);
   }

   返回(成功);


//
// i2cAISR - I2C A ISR (非 FIFO)
//
_interrupt void
i2cAISR (空)

   I2C_InterruptSource intSource;
   uint16_t i;

   //
   //读取中断源
   //
   intSource = I2C_getInterruptSource (I2CA_BASE);

   //
   //中断源=检测到停止条件
   //
   if (intSource = I2C_INTSRC_STOP_Condition)
   {
       //
       //如果已完成的消息正在写入数据,则将 msg 重置为非活动状态
       //
       if (currentMsgPtr ->msgStatus =MSG_STATUS_WRITE_BUSY)
       {
           currentMsgPtr ->msgStatus = MSG_STATUS_INACTIVE;
       }
       其他
       {
           //
           //如果在的地址设置部分收到 NACK 消息
           // EEPROM 读取、下面的代码进一步包含在寄存器中
           //访问就绪中断源代码将生成停止
           //条件。 在接收到停止条件后(此处)、设置
           //要重试的消息状态。 用户可能希望限制该数字
           //在生成错误之前重试次数。
           //
           if (currentMsgPtr ->msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY)
           {
               currentMsgPtr ->msgStatus = MSG_STATUS_SEND_NOSTOP;
           }
           //
           //如果已完成消息正在读取 EEPROM 数据,则将消息重置为
           //处于非活动状态并从 FIFO 读取数据。
           //
           否则 if (currentMsgPtr ->msgStatus =MSG_STATUS_READ_BUSY)
           {
               currentMsgPtr ->msgStatus = MSG_STATUS_INACTIVE;
               for (i=0;i < NUM_bytes;i++)
               {
                   currentMsgPtr ->msgBuffer[i]= I2C_getData (I2CA_BASE);
               }

               //
               //检查接收到的数据//我不需要
               //
               for (i=0;i < NUM_bytes;i++)
               {
                   if (i2cMsgIn.msgBuffer[i]=i2cMsgOut.msgBuffer[i])
                   {
                       PassCount++;
                   }
                   其他
                   {
                       failcount++;
                   }
               }

               if (passCount =NUM_Bytes)
               {
                   pass();
               }
               其他
               {
                   fail();
               }
           }
       }
   }
   //
   //中断源=寄存器访问就绪
   //
   //此中断用于确定何时设置 EEPROM 地址
   //读取数据通信的部分已完成。 因为没有停止位
   //为命令,此标志告诉我们何时发送了消息
   //而不是 SCD 标志。
   //
   否则、如果(intSource = I2C_INTSRC_REG_ACCESS_RDY)
   {
       //
       //如果接收到 NACK,清除 NACK 位并命令停止。
       //否则,继续到通信的读取数据部分。
       //
       if ((I2C_getStatus (I2CA_BASE)& I2C_STS_NO_ACK)!= 0)
       {
           I2C_sendStopCondition (I2CA_BASE);
           I2C_clearStatus (I2CA_BASE、I2C_STS_NO_ACK);
       }
       否则 if (currentMsgPtr -> msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY)
       {
           currentMsgPtr ->msgStatus = MSG_STATUS_RESTART;
       }
   }
   其他
   {
       //
       //从无效的中断源生成一些错误
       //
       asm ("  ESTOP0");
   }

   //
   //发出 ACK 以启用将来的组8中断
   //
   INTERRUPT_clearACKGROUP (INTERRUPT_ACK_group8);


//
//传递-如果写入的数据与读取的数据匹配,则调用的函数//无目的
//
无效
通过(无效)

   asm ("  ESTOP0");
   for (;;);


//
//失败-如果写入的数据与读取的数据不匹配,则调用的函数
//
失效失败(无效)

   asm ("  ESTOP0");
   for (;;);


//
//圆角结束/稍后我将为每次通信定义新结构
//

我将所有内容标记为红色、我已经修改了这些内容。 现在我的问题是、如果我使用自己的主循环、说我会将其部分用于简单的读取和写入目的、我可以这么做吗? 已经声明了所有中断和状态? 我希望尽可能少地进行修改。 或者我是否需要修改中断功能? 我不太明白、何时发生 i2c 中断、因此无法完全理解代码。

以后使用时、我想在传感器的 GPIO 中断被置位时写入一个函数。 因此、我想在其中一个引脚上设置一个中断、如果新的测量准备就绪并且没有读取寄存器、则该中断会将引脚拉高。 有什么提示吗?

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

    您好、Alexander、

    您正在处理的 I2C EEPROM 示例代码被写入以与 CAT24WC256 EEPROM 存储器件或需要相同协议的类似 I2C EEPROM 一起使用。 默认情况下、该示例将数据写入指定的 EEPROM 存储器地址(高/低地址字节)、然后读回写入的数据。 SW 主要由中断驱动、并包含一个状态机、因此很难跟随。

    [引用 user="Alexander Laub">稍后使用时、我希望在设置传感器的 GPIO 中断时编写一个函数。 因此、我想在其中一个引脚上设置一个中断、如果新的测量准备就绪并且没有读取寄存器、则该中断会将引脚拉高。 有什么提示吗?[/引述]

    如果您的最终目标是上述内容、我认为使用 I2C DriverLib 函数(在 i2c.h 内)编写新软件比尝试利用示例的状态机更简单。 用于此中断的引脚将是 C2000器件的输入还是输出? 从传感器器件配置和读取测量值的顺序是什么?

    最棒的

    Kevin

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    //
    //包含的文件
    //
    #include "driverlib.h"
    #include "device.h"
    #include "stdio.h"
    
    //
    定义
    //
    #define SLAVE_ADDRESS 0x29
    //#define EEPROM_HIGH_ADDR 0x00
    //#define EEPROM_LOW_ADDR 0x30
    #define NUM_Bytes 1
    #define MAX_BUFFER_SIZE 14. //目前最大值为14,原因是
    // 2个地址字节和16字节
    // FIFO
    //
    //距离连续模式所需的函数
    //
    #define SYSRANGE_INTERMEASUREMENT_PERIOD 0x01B
    #define SYSTEM_MODE_GPIO1 0x011
    #define system_interrupt_config_GPIO 0x014
    #define SYSRANGE_START 0x018
    #define RESULT_RANGE_RAW 0x064
    #define system_interrupt_clear 0x015
    
    typedef uint16_t VL6180xDev_t;
    VL6180xDev_t dev = slave_address;
    uint16_t n = 0;
    
    //
    I2CMsg Struct//
    
    #define MSG_STATUS_INACTIVE 的 I2C 消息状态 0x0000 //未使用消息,请勿发送
    #define MSG_STATUS_SEND_WITHSTOP 0x0010 //发送停止位
    #define MSG_STATUS_WRITE_BUSY 的消息 0x0011 //发送消息,等待 STOP
    #define MSG_STATUS_SEND_NOSTOP 0x0020 //发送无停止位
    的消息#define MSG_STATUS_SEND_NOSTOP_BUSY 0x0021 //发送的消息,等待 ARDY
    #define MSG_STATUS_RESTART 0x0022 //准备成为主接收
    器#define MSG_STATUS_READ_BUSY 0x0023 //在读取数据之前等待停止
    
    //
    //读取和写入函数的错误消息
    //
    #define ERROR_BUS_BUS_BUSY 0x1000
    #define ERROR_STOP_NOT_READY 0x5555
    #define SUCCESS 0x0000
    
    
    //
    // Typedefs
    //
    struct I2CMsg
    {
    uint16_t msgStatus; //字说明 msg 处于什么状态。
    //参见上面的 MSG_STATUS_*定义。
    uint16_t slaveAddr; //绑定到消息的从器件地址。
    uint16_t numBytes; //消息中有效字节的数量。
    uint16_t memoryHighAddr[30]; //相关数据的 EEPROM 地址
    //带有消息(高字节)。
    uint16_t memoryLowAddr[30]; //相关数据的 EEPROM 地址
    //带有消息(低字节)。
    uint16_t msgBuffer[30]; //阵列保存消息数据。
    };
    
    //
    // Globals
    //
    /* struct I2CMsg i2cMsgOut ={MSG_STATUS_SEND_WITHSTOP,
    Slave_address、
    num_Bytes、
    ArrayMemoryHighAddr[n]、
    ArrayMemoryLowAddr[n]、
    ArrayAddrValue[n]};
    
    struct I2CMsg i2cMsgIn ={MSG_STATUS_SEND_NOSTOP、
    Slave_address、
    num_Bytes、
    ArrayMemoryHighAddr[n]、
    ArrayMemoryLowAddr[n]};
    */
    struct I2CMsg * currentMsgPtr; //在中断中使用
    
    //
    函数原型
    //
    void initI2C (void);
    void initVL6180X (void);
    uint16_t ReadData (struct I2CMsg *msg);
    uint16_t writeData (struct I2CMsg *msg);
    int Rang6180x_Init (struct I2CMsg *msg);uintvr6180x_int_int_intvr6_int_intvr6_int_intvr6_intvr18x_int_int_intvr6_intvr6_intvr6_intvr6_int_intvr6_int_intvr6_int_intvr6_int
    
    uint16_t GPIOIntOn、uint16_t ActiveHigh);
    int VL6180x_RangeConfigInterrupt (VL6180xDev_t dev、uint16_t LevelLow、uint16_t LevelHigh、 uint16_t OutOfWindow、uint16_t NewSample);
    int VL6180x_RangeStartContinuousMode (VL6180xDev_t dev、uint16_t ContMode、uint16_t StartMode);
    int VL6180x_RangeGetMeasurement (VL6180xDev_t dev、Int32_t * pRange_mm);
    int VL6180x_ClearAllInterrupt (VL6180xDev_t dev、uint16_t ClearRange、uint16_t ClearALS、 uint16_t ClearError);
    
    __interrupt void i2cAISR (void);
    
    //
    // Main
    //
    void main (void)
    {
    //uint16_t i;
    
    //
    //初始化设备时钟和外设
    //
    device_init();
    
    //
    //禁用引脚锁定并启用内部上拉。
    //
    DEVICE_initGPIO();
    
    //
    //初始化 GPIO 32和33,分别用作 SDA 和 SCL A
    //
    GPIO_setPinConfig (GPIO_104_SDAA);
    GPIO_setPadConfig (104、GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (104、GPIO_QUAL_异 步);
    
    GPIO_setPinConfig (GPIO_105_SCLA);
    GPIO_setPadConfig (105、GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode (105、GPIO_QUAL_ASYNC_A);
    
    //
    //初始化 PIE 并清除 PIE 寄存器。 禁用 CPU 中断。
    //
    interrupt_initModule();
    
    //
    //使用指向 shell 中断的指针初始化 PIE 矢量表
    //服务例程(ISR)。
    //
    interrupt_initVectorTable();
    
    //
    //此示例中使用的中断被重新映射到 ISR 函数
    //在此文件中找到。
    //
    interrupt_register (INT_I2CA、&i2cAISR);
    
    //
    //设置 I2C 使用,将其初始化为 FIFO 模式
    //
    initi2C();
    
    //
    //清除传入消息缓冲区
    //
    /*表示(i = 0;i < MAX_BUFFER_SIZE;i++)
    {
    i2cMsgIn.msgBuffer[i]= 0x0000;
    }
    *
    //
    //将中断中使用的消息指针设置为指向传出消息
    //
    //currentMsgPtr =&i2cMsgOut;
    
    //
    //启用此示例所需的中断
    //
    INTERRUPT_ENABLE (INT_I2CA);
    
    //
    //启用全局中断(INTM)和实时中断(DBGM)
    //
    EINT;
    ERTM;
    
    
    INT STATUS = VL6180x_Init (dev);
    DEVICE_DELAY_US (1000);
    状态= VL6180x_RangeSetInterMeasuriod (dev、1000);
    DEVICE_DELAY_US (1000);
    状态= VL6180x_SetupGPIO1 (dev、1、1);
    DEVICE_DELAY_US (1000);
    状态= VL6180x_RangeConfigInterrupt (dev、0、0、0、1);
    DEVICE_DELAY_US (1000);
    状态= VL6180x_RangeStartContinuousMode (dev、1、1);
    DEVICE_DELAY_US (1000);
    int32_t 范围= 0;
    while (true){
    状态= VL6180x_RangeGetMeasurement (dev、&range);
    DEVICE_DELAY_US (1000000);
    //fprintf ("%c\n"、&range);
    状态= VL6180x_ClearAllInterrupt (dev、1、0、1);
    }
    }
    //
    // initI2C -用于在 FIFO 模式中配置 I2C A 的函数。
    //
    void
    initI2C()
    {
    //
    //必须在配置 I2C 之前将其复位
    //
    I2C_DisableModule (I2CA_BASE);
    
    //
    // I2C 配置。 使用占空比为33%的400kHz I2CCLK。
    //
    I2C_initMaster (I2CA_BASE、DEVICE_SYSCLK_FREQ、400000、I2C_DUTYCYCLE _33);
    I2C_setBitCount (I2CA_BASE、I2C_BITCOUNT_8);
    I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);
    I2C_setEmulationMode (I2CA_BASE、I2C_emulation_free_run);
    
    //
    //启用停止条件和寄存器访问就绪中断
    //
    I2C_enableInterrupt (I2CA_BASE、I2C_INT_STOP_Condition |
    I2C_INT_REG_ACCESS_RDY);
    
    //
    // FIFO 配置
    //
    I2C_enableFIFO (I2CA_BASE);
    I2C_clearInterruptStatus (I2CA_BASE、I2C_INT_RXFF | I2C_INT_TXFF);
    
    //
    //配置完成。 启用模块。
    //
    I2C_enableModule (I2CA_BASE);
    }
    
    //
    writeData Mask
    //
    uint16_t
    I2CwriteData (struct I2CMsg *msg){
    uint16_t 错误;
    if (msg->msgStatus =MSG_STATUS_SEND_WITHSTOP){
    错误= writeData (msg);
    
    if (error = success){
    currentMsgPtr = msg;
    MSG->msgStatus = MSG_STATUS_WRITE_BUSY;
    
    返回0;
    }
    }
    否则{
    返回1;
    }
    返回0;
    }
    
    //
    // writeData -发送要写入 EEPROM 的数据的函数
    //
    uint16_t
    writeData (struct I2CMsg *msg)
    {
    //uint16_t i;
    
    //
    //等待 STP 位从任何先前的主设备清零
    //通信。 模块将该位清零的时间延迟到之后
    // SCD 位被置位。 如果在启动新的之前没有检查该位
    //消息、I2C 可能会被混淆。
    //
    if (I2C_getStopConditionStatus (I2CA_BASE))
    {
    return (error_stop_not _ready);
    }
    
    //
    //设置从地址
    //
    I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);
    
    //
    //检查总线是否占线
    //
    IF (I2C_isBusy (I2CA_BASE))
    {
    return (error_bus_busy);
    }
    
    //
    //设置要发送 msgBuffer 和地址的字节数
    //
    I2C_setDataCount (I2CA_BASE、(msg->numBytes + 2));
    
    //
    //设置要发送的数据
    //
    i2C_putData (I2CA_BASE、msg->memoryHighAddr[n]);
    i2C_putData (I2CA_BASE、msg->memoryLowAddr[n]);
    
    //for (i = 0;i < msg->numBytes;i++)
    //{
    I2C_putData (I2CA_BASE、msg->msgBuffer[n]);
    //}
    
    //
    //将 START 作为主发送器发送
    //
    I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition (I2CA_BASE);
    I2C_sendStopCondition (I2CA_BASE);
    
    return (Success);
    }
    
    //
    // ReadData Mask
    //
    uint16_t
    I2CreadData (struct I2CMsg *msg)
    {
    while (true){
    if (msg->msgStatus =MSG_STATUS_SEND_NOSTOP){
    while (ReadData (msg)!=成功){
    
    }
    currentMsgPtr = msg;
    MSG->msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY;
    }
    
    
    否则 if (msg->msgStatus =MSG_STATUS_RESTART){
    while (ReadData (msg)!=成功){
    
    }
    currentMsgPtr = msg;
    MSG->msgStatus = MSG_STATUS_READ_BUSY;
    中断;
    }
    }
    返回0;
    }
    
    //
    // ReadData -准备从 EEPROM 读取的数据的函数
    //
    uint16_t
    ReadData (struct I2CMsg *msg)
    {
    //
    //等待 STP 位从任何先前的主设备清零
    //通信。 模块将该位清零的时间延迟到之后
    // SCD 位被置位。 如果在启动新的之前没有检查该位
    //消息、I2C 可能会被混淆。
    //
    if (I2C_getStopConditionStatus (I2CA_BASE))
    {
    return (error_stop_not _ready);
    }
    
    //
    //设置从地址
    //
    I2C_setSlaveAddress (I2CA_BASE、SLAVE_ADDRESS);
    
    //
    //如果我们处于地址设置阶段,则发送地址时不使用
    //停止条件。
    //
    if (msg->msgStatus =MSG_STATUS_SEND_NOSTOP)
    {
    //
    //检查总线是否占线
    //
    IF (I2C_isBusy (I2CA_BASE))
    {
    return (error_bus_busy);
    }
    
    //
    //将数据发送到设置 EEPROM 地址
    //
    I2C_setDataCount (I2CA_BASE、2);
    I2C_putData (I2CA_BASE、msg->memoryHighAddr[0]);
    I2C_putData (I2CA_BASE、msg->memoryLowAddr[0]);
    I2C_setConfig (I2CA_BASE、I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition (I2CA_BASE);
    }
    否则(msg->msgStatus =MSG_STATUS_RESTART)
    {
    //
    //地址设置阶段已完成。 现在设置预期的字节数
    //并将重新启动作为主接收器发送。
    //
    I2C_setDataCount (I2CA_BASE、(msg->numBytes));
    I2C_setConfig (I2CA_BASE、I2C_MASTER_Receive_MODE);
    I2C_sendStartCondition (I2CA_BASE);
    I2C_sendStopCondition (I2CA_BASE);
    }
    
    return (Success);
    }
    
    //
    // i2cAISR - I2C A ISR (非 FIFO)
    //
    _interrupt void
    i2cAISR (void)
    {
    I2C_InterruptSource intSource;
    uint16_t i;
    
    //
    //读取中断源
    //
    intSource = I2C_getInterruptSource (I2CA_BASE);
    
    //
    //中断源=检测到停止条件
    //
    if (intSource = I2C_INTSRC_STOP_Condition)
    {
    //
    //如果已完成的消息正在写入数据,则将 msg 重置为非活动状态
    //
    if (currentMsgPtr ->msgStatus =MSG_STATUS_WRITE_BUSY)
    {
    currentMsgPtr ->msgStatus = MSG_STATUS_INACTIVE;
    }
    其他
    {
    //
    //如果在的地址设置部分收到 NACK 消息
    // EEPROM 读取、下面的代码进一步包含在寄存器中
    //访问就绪中断源代码将生成停止
    //条件。 在接收到停止条件后(此处)、设置
    //要重试的消息状态。 用户可能希望限制该数字
    //在生成错误之前重试次数。
    //
    if (currentMsgPtr ->msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY)
    {
    currentMsgPtr ->msgStatus = MSG_STATUS_SEND_NOSTOP;
    }
    //
    //如果已完成消息正在读取 EEPROM 数据,则将消息重置为
    //处于非活动状态并从 FIFO 读取数据。
    //
    否则 if (currentMsgPtr ->msgStatus =MSG_STATUS_READ_BUSY)
    {
    currentMsgPtr ->msgStatus = MSG_STATUS_INACTIVE;
    for (i=0;i < NUM_bytes;i++)
    {
    currentMsgPtr ->msgBuffer[i]= I2C_getData (I2CA_BASE);
    }
    
    }
    
    }
    //
    //中断源=寄存器访问就绪
    //
    //此中断用于确定何时设置 EEPROM 地址
    //读取数据通信的部分已完成。 因为没有停止位
    //为命令,此标志告诉我们何时发送了消息
    //而不是 SCD 标志。
    //
    否则、如果(intSource = I2C_INTSRC_REG_ACCESS_RDY)
    {
    //
    //如果接收到 NACK,清除 NACK 位并命令停止。
    //否则,继续到通信的读取数据部分。
    //
    if ((I2C_getStatus (I2CA_BASE)& I2C_STS_NO_ACK)!= 0)
    {
    I2C_sendStopCondition (I2CA_BASE);
    I2C_clearStatus (I2CA_BASE、I2C_STS_NO_ACK);
    }
    否则 if (currentMsgPtr -> msgStatus = MSG_STATUS_SEND_NOSTOP_BUSY)
    {
    currentMsgPtr ->msgStatus = MSG_STATUS_RESTART;
    }
    }
    其他
    {
    //
    //从无效的中断源生成一些错误
    //
    asm (" ESTOP0");
    }
    
    //
    //发出 ACK 以启用将来的组8中断
    //
    interrupt_clearACKGroup (interrupt_ack_group8);
    }
    
    //
    VL6180X 寄存器初始化
    //
    int VL6180x_Init (VL6180xDev_t dev){
    
    uint16_t ArrayMemoryHighAddr[30]={0x02、0x02、0x00、0x00、0x00、 0x00、0x00、0x00、0x00、0x00、 0x00、0x00、0x00、0x00、0x00、 0x00、0x00、0x00、0x00、0x00、 0x01、0x01、0x01、0x00、0x01、 0x01、0x01、0x01、0x01、0x00};
    uint16_t ArrayMemoryLowAddr[30] ={0x07、0x08、0x96、0x97、0xE3、 0xE4、0xE5、0xE6、0xE7、0xf5、 0xD9、0xDB、0xDC、0xDD、0x9F、 0xA3、0xB7、0xBB、0xB2、0xCA、 0x98、0xB0、0xAD、0xFF、0x00、 0x99、0xA6、0xAC、0xA7、0x30};
    uint16_t ArrayAddrValue[30] ={0x01、0x01、0x00、0xFD、0x00、 0x04、0x02、0x01、0x03、0x02、 0x05、0xCE、0x03、0xf8、0x00、 0x3C、0x00、0x3C、0x09、0x09、 0x01、0x17、0x00、0x05、0x05、 0x05、0x1B、0x3E、0x1F、0x00};
    uint16_t n = 0;
    INT STATUS = 0;
    
    struct I2CMsg I2CMsgInit ={MSG_STATUS_SEND_WITHSTOP、
    Slave_address、
    num_Bytes};
    对于(n = 0;n < 30;n++){ 
           I2CMsgInit.memoryHighAddr[n]= ArrayMemoryHighAddr[n];
           I2CMsgInit.memoryLowAddr[n]= ArrayMemoryLowAddr[n];
           I2CMsgInit.msgBuffer[n]= ArrayAddrValue[n];
       } 对于(n = 0;n < 30;n++){ I2CMsgInit.msgStatus = MSG_STATUS_SEND_WITHSTOP; 状态= I2CwriteData (&I2CMsgInit); DEVICE_DELAY_US (1000); } if (status){ fprintf (stderr、"初始化写入失败\n"); } 返回状态; } // // VL6180X 内部测量周期时间设置 // int VL6180x_RangeSetInterMeasPeriod (VL6180xDev_t dev、uint32_t InterMeasure Time_msec) { uint16_t settime = 0; INT STATUS = 0; if (InterMeasure Time_msec <= 2550 && InterMeasure Time_msec >=10){ settime =(uint16_t)(InterMeasure Time_msec / 10); struct I2CMsg I2CMsgOut ={MSG_STATUS_SEND_WITHSTOP、 Slave_address、 num_Bytes、 {0x00}、 {SYSRANGE_INTERMEASUREMENT_PERIOD}、 settime}; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、SYSRANGE_INTERMEASUREMENT、settime); if (status){ fprintf (stderr、"SYSRANGE_INTERMEASUREMENT_PERIOD 写入失败"); } }否则{ fprintf (stderr、"InterMeasTime_msec 超出范围"); 状态= 1; } 返回状态; } // // VL6180X GPIO1中断设置 // int VL6180x_SetupGPIO1 (VL6180xDev_t dev、uint16_t GPIOIntOn、uint16_t ActiveHigh) { uint16_t 值= 0; INT STATUS = 0; if ((GPIOIntOn <= 0x01)&&(ActiveHigh <= 0x01)){ 值= ActiveHigh << 5; 值|= GPIOIntOn << 4; struct I2CMsg I2CMsgOut ={MSG_STATUS_SEND_WITHSTOP、 Slave_address、 num_Bytes、 {0x00}、 {SYSTEM_MODE_GPIO1}、 值}; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、system_mode_GPIO1、value); if (status){ fprintf (stderr、"system_mode_gpio1写入失败"); } }否则{ fprintf (stderr、"GPIOIntOn 或 ActiveHigh 超出范围"); 状态= 1; } 返回状态; } // // VL6180X 范围中断配置 // int VL6180x_RangeConfigInterrupt (VL6180xDev_t dev、uint16_t LevelLow、uint16_t LevelHigh、uint16_t OutOfWindow、uint16_t NewSample) { uint16_t 值= 0; INT STATUS = 0; if ((LevelLow <= 0x01)&&(LevelHigh <= 0x01)&&(OutOfWindow <= 0x01)&&(NewSample <= 0x01)){ 值=低电平; 值|= LevelHigh << 1; if (OutOfWindow = 0x01){ 值|= 0x03; } 值|= NewSample <<2; struct I2CMsg I2CMsgOut ={MSG_STATUS_SEND_WITHSTOP、 Slave_address、 num_Bytes、 {0x00}、 {SYSTEM_INTERRUPT_CONFIG_GPIO}、 值}; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、system_interrupt_config_GPIO、value); if (status){ fprintf (stderr、"system_interrupt_config_GPIO 写入失败"); } }否则{ fprintf (stderr、"ConfigGpioInt Out of range"); 状态= 1; } 返回状态; } // // VL6180X 范围连续模式集 // int VL6180x_RangeStartContinuousMode (VL6180xDev_t dev、uint16_t ContMode、uint16_t StartMode) { uint16_t 值= 0; INT STATUS = 0; /* FIXME 我们不会通过@A VL6180x_RangeWaitDeviceReady 检查设备是否就绪 *因此、如果调用返回到真正的 FAST、我们不会进行检查 *如果之前的模式"置位"被吸收=>位0必须为0才能工作 * if ((ContMode <= 0x01)&&(StartMode <= 0x01)){ 值= ContMode << 1; struct I2CMsg I2CMsgOut ={MSG_STATUS_SEND_WITHSTOP、 Slave_address、 num_Bytes、 {0x00}、 {SYSRANGE_START}、 值}; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、SYSRANGE_START、Value); DEVICE_DELAY_US (100); 值|= StartMode; I2CMsgOut.msgBuffer[0]=值; I2CMsgOut.msgStatus = MSG_STATUS_SEND_WITHSTOP; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、SYSRANGE_START、Value); if (status){ fprintf (stderr、"SYSRANGE_START 写失败"); } }否则{ fprintf (stderr、"模式或启动模式超出范围"); 状态= 1; } 返回状态; } // // VL6180X 范围获取测量 // int VL6180x_RangeGetMeasurement (VL6180xDev_t dev、int32_t *pRange_mm) { INT STATUS = 0; Int16_t RawRange = 0; struct I2CMsg I2CMsgIn ={MSG_STATUS_SEND_NOSTOP、 Slave_address、 num_Bytes、 {0x00}、 {RESULT_RANGE_RAW}、 RawRange}; 状态= I2CreadData (&I2CMsgIn); //status = I2CRead (dev、Result_range_raw、&RawRange); if (status){ fprintf (stderr、"result_range_raw 读取失败"); } 否则{ *pRange_mm =(int32_t) I2CMsgIn.msgBuffer[0]; } 返回状态; } // // VL6180X 清除中断配置 // int VL6180x_ClearAllInterrupt (VL6180xDev_t dev、uint16_t ClearRange、uint16_t ClearALS、uint16_t ClearError) { uint16_t 值= 0; INT STATUS = 0; if ((ClearRange <= 1)&&(ClearALS <= 1)&&(ClearError <= 1)){ 值= ClearError << 2; 值|= ClearALS <<1; Value |= ClearRange; struct I2CMsg I2CMsgOut ={MSG_STATUS_SEND_WITHSTOP、 Slave_address、 num_Bytes、 {0x00}、 {system_interrupt_clear}、 值}; 状态= I2CwriteData (&I2CMsgOut); //status = I2CWrite (dev、system_interrupt_clear、value); if (status){ fprintf (stderr、"system_interrupt_clear write failed"); } }否则{ fprintf (stderr、"ClearRange 或 ClearALS 或 ClearError 超出范围"); 状态= 1; } 返回状态; }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我知道您的意思、但我使用的传感器似乎使用相同的协议、每个地址具有2个字节、依此类推。 传感器是 VL6180x、这是飞行时间距离传感器。 在下面、我插入了我的当前代码、该代码正在运行、但未读出当前距离、这是我当前的目标。 
    我将尝试解释我的更改。 传感器在通电时处于待机状态。 然后、它需要一个寄存器写入序列进行初始化。
    VL6180x_Init 为初始化写入30个寄存器。
    VL6180x_RangeSetInterMeasPeriod 写入1个寄存器来设置距离测量之间的周期。
    VL6180x_SetupGPIO1会设置中断引脚、稍后、当新测量准备就绪但当前未使用时、该引脚将为高电平
    VL6180x_RangeConfigInterrrupt 写入1个寄存器以设置、为什么应在此处设置 GPIO1上的中断、此时新测量准备就绪、但当前未使用、稍后会如此
    VL6180x_RangeStartContinuousMode 写入1个寄存器来设置连续测距模式
    VL6180x_RangeMeasurement 应该读取一个寄存器、并将其设置为我要读取的变量、主函数中的变量范围(void)
    VL6180x_ClearAllInterrupt 写入1个寄存器来清除中断

    我仍然使用了 msg 结构、所以我不必修改太多代码、就像您想的那样。
    VL6180xDev_t 类型只是单个传感器使用中从地址的整数。
    我将引脚104和105用于数据 apin 和时钟引脚。
    I2Cwrite/ReadData 只是掩码函数、用于在不修改原始 write/ReadData 的情况下使用 VL6180x 函数、并使用状态变量、以便中断可以正常运行。

    所以一切都正常工作、代码正在运行并且没有错误、唯一的问题是 VL6180x_RangeMeasurement 不能为我提供范围测量。 有人知道原因吗? 我在每个步骤中都使用了 brakpoints、到目前为止、它没有在我的.msgbuffer[0]中放置一个值。

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

    我知道您的意思、但我使用的传感器似乎使用相同的协议、每个地址具有2个字节、依此类推。 传感器是 VL6180x、这是飞行时间距离传感器。 下面我插入了我的当前代码、该代码正在运行、但未读出当前距离、这是我的目标。我将尝试解释我的更改。 传感器在通电时处于待机状态。

    然后、它需要一个寄存器写入序列进行初始化。

    VL6180x_Init 为初始化写入30个寄存器。

    VL6180x_RangeSetInterMeasPeriod 写入1个寄存器来设置距离测量之间的周期。

    VL6180x_SetupGPIO1会设置中断引脚、稍后、当新测量准备就绪但当前未使用时、该引脚将为高电平

    VL6180x_RangeConfigInterrrupt 写入1个寄存器以设置、为什么应在此处设置 GPIO1上的中断、此时新测量准备就绪、但当前未使用、稍后会如此

    VL6180x_RangeStartContinuousMode 写入1个寄存器来设置连续测距模式

    VL6180x_RangeMeasurement 应该读取一个寄存器、并将其设置为我要读取的变量、主函数中的变量范围(void)

    VL6180x_ClearAllInterrupt 写入1个寄存器来清除中断

    我仍然使用了 msg 结构、所以我不必修改太多代码、就像您想的那样。

    VL6180xDev_t 类型只是单个传感器使用中从地址的整数。

    我将引脚104和105用于数据 apin 和时钟引脚。

    I2Cwrite/ReadData 只是掩码函数、用于在不修改原始 write/ReadData 的情况下使用 VL6180x 函数、并使用状态变量、以便中断可以正常运行。

    所以一切都正常工作、代码正在运行并且没有错误、唯一的问题是 VL6180x_RangeMeasurement 不能为我提供范围测量。

    有人知道原因吗?

    我在执行每个步骤后都有断点、它到目前为止并没有在.msgbuffer[0]中放置一个值。

     



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

    您好、Alexander、

    使用 I2C 逻辑分析仪通常可以更轻松地调试类似的内容。 您是否有机会使用您可以使用的设备?

    您能否发布您遇到问题的代码段? 否则很难进行审查。

    最棒的

    Kevin