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.

opt3001碰到一个问题,就是在中断里面给opt3001的寄存器写值,发现I2C_transfer写值写不进去。这是因为I2C和opt3001的中断嵌套吗,这个问题应该怎么解决呢,下面是opt3001的中断代码,光照判断进中断首先是没问题的,在中断外,读写寄存器值也是没问题的。

Other Parts Discussed in Thread: OPT3001, SYSBIOS

void OPT3001CallbackFxn(PIN_Handle handle, PIN_Id pinId) {
  switch (pinId) {
    case OPT3001_INT:
          PIN_setConfig(OPT3001_INT_PinHandle, PIN_BM_IRQ, OPT3001_INT | PIN_IRQ_DIS);
          PIN_clrPendInterrupt(handle,pinId);
         if(g_DoorStatus == DOOR_OPEN){
             g_DoorStatus == DOOR_CLOSE;
            Set_OPT3001_High_Limit( cfg_para_opt3001.lignt_limit_ths );
          }else{
            g_DoorStatus == DOOR_OPEN;
           Set_OPT3001_Low_Limit( cfg_para_opt3001.lignt_limit_ths );
          }
        break;
    }
}

  • 能进中断具体指的是运行到哪一步,监测写的值是否发生变化
  • 下面是我的代码,我是将开发板置于箱子内部,通过光照阈值和当前光照值来判断箱子的开关状态,例如我阈值设置的是0x20,当前采集的光照值大于0x20,则判断箱子打开,设置光照下限,当关闭箱子的时候,将会触发下限进中断函数,因此我需要在中断里面再设置其上限,刹车再次打开箱子的时候能够再次进入中断来获取箱子的打开状态,现在的问题是中断里面的设置上限(通过I2C)的时候,就卡住了,程序就跑飞了,我具体跟踪了下,I2C_transfer(handle,&i2cTrans)在写上一部分的时候返回老是false。我I2C用的是block通讯模式。


    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>

    / * XDCtools头文件* /
    #include <xdc / std.h>
    #include <xdc / runtime / System.h>

    / * BIOS头文件* /
    #include <ti / sysbios /BIOS.h>
    #include <ti / sysbios /knl/Clock.h>
    #include <ti / sysbios /knl/Task.h>

    / * TI-RTOS头文件* /
    #include <ti /
    drivers / I2C.h> //修改
    #include <ti / drivers / i2c / I2CCC26XX.h>

    #include“ Board.h”
    #include“ HAL_ OPT3001 .h”

    静态PIN_Handle OPT3001 _LED_PinHandle;
    静态PIN_Handle OPT3001 _INT_PinHandle;
    静态PIN_State OPT3001 _LED_PinState;
    静态PIN_State OPT3001 _INT_PinState;
    静态Task_Struct task0Struct;
    静态Char task0Stack [TASKSTACKSIZE];

    / *定义I2C ============================================ ============================== * //
    静态uint8_t txBuffer [3]; //发送器缓冲区
    静态uint8_t rxBuffer [3] ; //接收缓冲区

    静态uint8_t RXBuf [3]; //发送缓冲区
    静态uint8_t TXBuf [3]; //接收缓冲区

    静态I2C_Handle句柄;
    静态I2C_Params参数;
    静态I2C_Transaction i2cTrans;

    无符号字符g_DoorStatus = DOOR_OPEN;
    typedef struct
    {
    uint8_t lignt_limit_ths; //光照强度阈值
    } CONGFIG_PARAMETER;

    CONGFIG_PARAMETER cfg_para_ opt3001 ;

    静态PIN_Config OPT3001 _INT_PinTable [] = {
    OPT3001 _INT | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    PIN_TERMINATE
    };

    void I2C_configParam_ OPT3001(){
    / *创建要使用的I2C ***************** /
    I2C_Params_init(&params);
    params.bitRate = I2C_100kHz;

    handle = I2C_open(Board_I2C,&params);
    if(句柄== NULL){
    System_abort(“初始化I2C时出错\ n”);
    }
    else {
    System_printf(“ I2C Initialized!\ n”);
    }
    / *完成I2C的使用创建********** /
    Task_sleep(1000000 / Clock_tickPeriod);
    }

    //函数封装(给寄存器读写值)
    布尔HalSensorRWReg_ OPT3001(uint8_t地址,uint8_t * pWriteBuf,uint8_t WriteBytes,uint8_t * pReadBuf,uint8_t的ReadBytes,uint8_t slaveAddress)
    {
    uint8_t TMP [32]; //接收器缓冲器
    的memcpy(TMP, txBuffer,WriteBytes);
    txBuffer [0] = addr; //地址是设备ID
    memcpy(txBuffer + 1,tmp,WriteBytes);
    i2cTrans.writeCount = 1 + WriteBytes;
    i2cTrans.writeBuf = txBuffer;
    i2cTrans.readCount = ReadBytes;
    i2cTrans.readBuf = rxBuffer;
    i2cTrans.slaveAddress = slaveAddress;
    while(!I2C_transfer(handle,&i2cTrans)){

    }
    返回0;
    }

    //重置总线
    void Reset_ OPT3001 _Register()
    {
    HalSensorRWReg_ OPT3001(0x06,txBuffer,0,rxBuffer,0,0x00);
    }

    //获取当前光照结果寄存器值

    无效Get_ OPT3001 _Result()
    {
    HalSensorRWReg_ OPT3001(0x00,txBuffer,0,rxBuffer,2,0x44);
    memcpy(TXBuf,rxBuffer,2);
    }

    //获取光照状态寄存器值

    无效Get_ OPT3001 _Status()
    {
    HalSensorRWReg_ OPT3001(0x01,txBuffer,0,rxBuffer,2,0x44);
    memcpy(RXBuf,rxBuffer,2);
    }

    //设置光照下限

    无效Set_ OPT3001 _Low_Limit(uint8_t限制)

    {

    Reset_ OPT3001 _Register();

    txBuffer [0] = 0x54; txBuffer [1] = 0x10;
    HalSensorRWReg_ OPT3001(0x01,txBuffer,2,rxBuffer,0,0x44);

    txBuffer [0] = 0x50; txBuffer [1] =限制;
    HalSensorRWReg_ OPT3001(0x02,txBuffer,2,rxBuffer,0,0x44);
    }

    //设置光照上限

    无效Set_ OPT3001 _High_Limit(无符号字符数限制)
    {
    txBuffer [0] = 0x54; txBuffer [1] = 0x10;
    HalSensorRWReg_ OPT3001(0x01,txBuffer,2,rxBuffer,0,0x44);

    txBuffer [0] = 0x50; txBuffer [1] =限制;
    HalSensorRWReg_ OPT3001(0x03,txBuffer,2,rxBuffer,0,0x44);

    }

    //初始化箱门状态,如果当前光照值大于阈值,则判断箱门开,设置光照下限(当光照度低于当前阈值时,会进中断)

    //如果当前光照值小于于阈值,则判断箱门关,设置光照上限(当光照度高于当前阈值时,会进中断)

    void Init_ OPT3001 _IN(){
    Get_ OPT3001 _Status();
    Get_ OPT3001 _Result();
    uint16_t b =(TXBuf [0] << 8 | TXBuf [1])&0xFFF;

    uint16_t c = TXBuf [1];
    if((((TXBuf [0] << 8 | TXBuf [1])&0xFFF)> = cfg_para_ opt3001 .lignt_limit_ths)
    {
    g_DoorStatus = DOOR_OPEN;
    Set_ OPT3001 _Low_Limit(cfg_para_ opt3001 .lignt_limit_ths);
    }
    else if(TXBuf [1] <cfg_para_ opt3001 .lignt_limit_ths)
    {
    g_DoorStatus = DOOR_CLOSE;
    组_OPT3001 _High_Limit(cfg_para_ opt3001 .lignt_limit_ths);
    }
    }

    // OPT3001初始化,给0x01寄存器配值(5101)
    void SET_ OPT3001 _Register()
    {
    //清空总线
    Reset_ OPT3001 _Register();

    txBuffer [0] = 0x54; txBuffer [1] = 0x10;
    HalSensorRWReg_ OPT3001(0x01,txBuffer,2,rxBuffer,0,0x44);

    HalSensorRWReg_ OPT3001(0x01,txBuffer,0,rxBuffer,2,0x44);
    }

    / ***************************************************** ********************* // **
    * @brief根据箱门状态设置上下限
    *
    * @param箱门报警后,箱门状态
    *
    * @return无
    *************************************************** ************************** /
    void CFG_ OPT3001 _IN(unsigned char state)
    {
    if(state == DOOR_OPEN)
    {
    Set_ OPT3001 _Low_Limit(cfg_para_ opt3001 .lignt_limit_ths);
    }
    else if(state == DOOR_CLOSE)
    {
    Set_ OPT3001 _High_Limit(cfg_para_ opt3001 .lignt_limit_ths);
    }
    }

    //主任务函数

    静态uint8_t HalSensorRWRegOPT3001(UArg arg0,UArg arg1)
    {
    I2C_configParam_ OPT3001();

    / * OPT3001初始化* /
    SET_ OPT3001 _Register();
    Task_sleep(2000000 / Clock_tickPeriod);

    / *初始化箱门状态* /
    Init_ OPT3001 _IN();


    / *使能光照报警* /
    PIN_setConfig(OPT3001 _INT_PinHandle,PIN_BM_IRQ,OPT3001 _INT | PIN_IRQ_NEGEDGE);
    返回0;
    }

    / *
    * ======== OPT3001CallbackFxn(中断函数)========
    * /
    void OPT3001CallbackFxn(PIN_Handle handle,PIN_Id pinId){
    switch(pinId){
    case OPT3001 _INT:
    PIN_setConfig(OPT3001 _INT_PinHandle, PIN_BM_IRQ,OPT3001 _INT | PIN_IRQ_DIS);
    PIN_clrPendInterrupt(handle,pinId);
    if(g_DoorStatus == DOOR_OPEN){
    g_DoorStatus == DOOR_CLOSE;
    设置OPT3001高限(cfg_para_ opt3001 .lignt_limit_ths);
    }否则{
    g_DoorStatus == DOOR_OPEN;
    组_OPT3001 _Low_Limit(cfg_para_ opt3001 .lignt_limit_ths);
    }
    ;
    }
    }

    / *
    * ========主要======================================= ================================================== ======
    * /
    INT opt3001main(无效)
    {
    / *初始化设备配置参数* /
    cfg_para_ opt3001 .lignt_limit_ths = 0×20; //光照强度阈值
    Task_Params taskParams;

    / *调用板初始化函数* /
    Board_initGeneral();
    Board_initI2C();
    OPT3001 _INT_PinHandle = PIN_open(&OPT3001 _INT_PinState,OPT3001 _INT_PinTable);
    *为按钮引脚设置回调* /
    如果(PIN_registerIntCb(OPT3001 _INT_PinHandle,&OPT3001CallbackFxn)!= 0){
    System_abort(“错误注册按钮回调函数”);
    }

    / *构造g_sensor任务线程* /
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack =&task0Stack;
    Task_construct(&task0Struct,(Task_FuncPtr)HalSensorRWRegOPT3001,&taskParams,NULL);

    / *启动BIOS * /
    BIOS_start();

    返回(0);
    }
  • 就是红箭头指的这块,程序就会跑飞。

  • 返回false可能是没有收到信号,一直在等待
    看下SDK中C:/ti/simplelink_cc2640r2_sdk_4_30_00_08/docs/tidrivers/doxygen/html/_i2_c_8h.html
    IIC的用法说明
  • I2C读写是没有问题的,在中断外读写都ok的,就是在中断里面读写I2C就阻塞了。
  • 在中断中使用阻塞容易发生问题,得不到返回信号,建议不要在中断中使用阻塞
    也可以看下e2e.ti.com/.../3124685
  • 中断里面不要使用任何driver程序

  • 我现在是这样解决的,我建了两个任务,将读取I2C操作放到另外一个任务里面,然后用信号量去控制,这是好的解决方法吗,还有其他的解决方法吗?
  • 读取I2C操作放到另外一个任务里面我認為好的解决方法了