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.

[参考译文] tms320f2.8075万:I2C接口至BQ40z60 -在ISR中使用断点

Guru**** 2587365 points
Other Parts Discussed in Thread: BQ40Z60

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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/658682/tms320f28075-i2c-interface-to-bq40z60---works-with-breakpoint-in-isr

部件号:TMS320F2.8075万
主题中讨论的其他部件:BQ40Z60

我使用28.0775万的I2C连接TI BQ40z60芯片(SMB)。  我使用的是TI-RTOS,其中的中断(使用HWI_构造 初始化)是为FIFO完全以及nack,ARDY和SCD的常规中断生成的。  如果我在常规中断的开始处放置一个断点,并在每次中断被触发时按“继续”,一切都很正常。  如果我不这样做,我会得到各种nacks,并在合理的时间内停止不发生的事情。  我感到困惑的是,遇到断点会导致接口正常工作。 以下是一些相关代码剪切:

作废I2CB_Init(void)

   I2cbRegs.I2CMDR.All &=~0x0020;    //将I2C置于复位状态

   I2cbRegs.I2CSAL.ALL = 0x006a;    //从属地址

  // PLL时钟/CPU时钟为120 MHz
  I2cbRegs.I2CPsc.all = 9;         //预分频器-需要7-12 MHz的模块clk。  9 => 120/(9+1)= 12 MHz
  // SMBus在10k - 100kHz之间工作。  时钟除以200 (I2CCLKL + I2CCLKLH + 10)可提供60 kHz的频率
  // 10是基于I2CPSC的调整系数
  I2cbRegs.I2CCLKL = 150;//200           //注意:必须为非零
  I2cbRegs.I2CCLKH = 150; //200         //注意:必须为非零
  I2cbRegs.I2CIER = 0x26;      //启用SCD & ARDY & nack__interrupts

  I2cbRegs.I2CFFTX.ALL = 0;
  I2cbRegs.I2CFFTX.ALL = 0x6000;//使用FIFO
  I2cbRegs.I2CFFRX.ALL = 0;
  I2cbRegs.I2CFFRX.ALL = 0x202A;//重置+启用Rx中断+中断级别


  I2cbRegs.I2CMDR.ALL = 0x0020;    //从重置中取出I2C
                                    //暂停时停止I2C
  返回;
}

void i2cBIsr (UArg参数)

   UINT16 IntSource = I2cbRegs.I2CISRC.ALL;

   //中断源=检测到停止条件
   IF (IntSource == I2C_SCD_ISRC)
   {
       bqLog[LogEntry +]= 15 |(dataIndex << 4)+(I2cbRegs.I2CFFRX.Bit.RXFFST << 8);
       LogEntry %= log_length;
       //如果FIFO中仍有数据,请获取
       如果(I2cbRegs.I2CFFRX.bit.RXFFST != 0)
       {
           bqLog[LogEntry +]= 8 |(dataIndex << 4)+(I2cbRegs.I2CFFRX.Bit.RXFFST << 8);
           LogEntry %= log_length;
           i2cB_FIFO ISR (0);
       }

       I2cbRegs.I2CSTR.Bit.SCD = 1;//清除SCD

       如果(BQ_MsgStatus == ADDR_MSG_Sent)&&(dataQueries[dataIndex].type44Msg)
       {
           I2cbRegs.I2CCNT = 1;
           I2cbRegs.I2CDXR/all = 0x44;
           I2cbRegs.I2CMDR.All = 0x2e20;// 0x6e20;// 0x2620;//发送数据
           Bq_MsgStatus = type_44_sent;
           bqLog[LogEntry +]=6|(dataIndex << 4);
           LogEntry %= log_length;
       }
       否则,如果(BQ_MsgStatus == type_44_sended)
       {
           I2cbRegs.I2CCNT = dataQueries[dataIndex].respLen;   //设置预期的字节数
           I2cbRegs.I2CMDR.All = 0x2C20;        //作为主接收器发送重启
           Bq_MsgStatus =读取数据;
           bqLog[LogEntry +]=7|(dataIndex << 4);
           LogEntry %= log_length;
       }
       否则,如果(reading_data == BQ_MsgStatus)
       {
           Bq_MsgStatus = COMM_IDLE;
           bqLog[LogEntry +]=9|(dataIndex << 4);
           LogEntry %= log_length;
       }
   }

   //
   //中断源=寄存器访问就绪
   //此__interrupt用于确定EEPROM地址设置的时间
   //部分读取数据通信已完成。 因为没有停止位
   //命令,此标志告诉我们消息已发送,而不是
   // SCD标志。 如果收到nack,请清除nack位并命令a
   //停止。 否则,请转到通信的读取数据部分。
   //
   否则IF (IntSource == I2C_ARDY_ISRC)
   {
       如果(BQ_MsgStatus == ADDR_MSG_Sent)&&(!dataQueries[dataIndex].type44Msg)
       {
           //对于非类型44s,我们发送重启,而不是先停止,然后再发送新的启动
           I2cbRegs.I2CCNT = dataQueries[dataIndex].respLen;   //设置预期的字节数
           I2cbRegs.I2CMDR.All = 0x2C20;        //作为主接收器发送重启
           Bq_MsgStatus =读取数据;
           bqLog[LogEntry +]=10|(dataIndex << 4);
           LogEntry %= log_length;
       }
       否则
       {
           I2cbRegs.I2CSTR.bit.ARDY = 1;
           bqLog[LogEntry +]= 13|(dataIndex << 4);
           LogEntry %= log_length;
       }
   }
   否则,如果(IntSource == I2C_Nack_ISRC)
   {
       I2cbRegs.I2CSTR.bit.nack = 1;
       Bq_MsgStatus = COMM_IDLE;
       bqLog[LogEntry +]= 11|(dataIndex << 4);
       LogEntry %= log_length;
   }
   否则
   {
      //
      //由于__interrupt源无效而产生一些错误
      //
      ASM ("  ESTOP0");
   }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    注:ARDY中断部分之前的注释是我从EEPROM示例中窃取的,不准确
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Rob,

    您是否试图说在未遇到断点时从未收到FIFO中断?

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

    接口有点复杂。  类型0x44消息需要多个I2C步骤才能接收数据。  我经常不能获得足够的FIFO中断。  但是,如果我不在主I2C ISR中设置断点,那么我就不会获得FIFO中断,这是正确的。  但它不应该。  没有收到数据。

    我真正想说的是,除非我在主I2C ISR (i2cBIRR)中设置断点,否则我不会得到我应该得到的停止位,也不会接收数据。  

    对于类型0x44消息,应该是我发送(十六进制):

    44 02 AL AH [停止位](AL =地址低,AH =地址高)

    44 [停止位]

    然后将 I2CCNT设置为预期的接收长度并发送重新启动。

    在i2cBIR的顶部有一个断点,这很好。  重新启动后,数据进入,FIFO ISR被点击,显示一条高于FIFO阈值的消息。  否则,在数据进入后会有一个停止位,我在i2cBIR中检查是否有任何可能滞留在FIFO中的数据。  但是,如果i2cBIR顶部没有断点,我在第一条消息后得到一个nack,否则在第二条消息后我永远不会得到停止位中断。  我不想设置I2CCNT然后再将数据输入。

    我希望这一点更清楚。

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

    Rob,

    根据您的消息,您似乎没有收到来自BQ40z60的停止位。 您是否在SDAA针脚上探头?

    从代码中,I2C模块被配置为从属设备,I2C等待从BQ40z60接收停止位引起的I2C中断。 对吗?

    此致,
    Manoj

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

    我不是从属设备。 在init函数中,我从重置中出来。 但我使用初始主写入启动传输(MDR寄存器为0x2E20)。 然后作为主服务器读取(MDR = 0x2C20)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Rob,

    但是,您正在i2cBISR (ISR例程)中配置MDR寄存器= 0x2E20和MDR寄存器= 0x2C20。 但是,它首先将如何进入ISR程序。

    此致,
    Manoj
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    每隔一秒左右就会调用此功能以启动整个过程。 这是一个计时器运行,操作应在ISR中完成。 dataQueries是我循环使用的消息数组。

    UINT16 BQ_ReadData (无效)

    //
    //等待STP位从以前的任何主通信中清除。
    //模块清除此位的时间延迟到SCD位之后
    //设置。 如果在启动新消息之前未检查此位,则
    // I2C可能会混淆。
    //
    IF (I2cbRegs.I2CMDR.bit.stp == 1)

    返回I2C_STP_NOT_READY_ERROR;
    }

    I2cbRegs.I2CSAL.ALL = 0x0B;

    IF (BQ_MsgStatus == COMM_IDLE)

    //
    //检查总线是否繁忙
    //
    IF (I2cbRegs.I2CSTR.Bit.BB == 1)

    返回I2C_BUS_BUSY_ERROR;
    }

    IF (dataQueries[dataIndex].type44Msg)

    I2cbRegs.I2CCNT = 4;
    I2cbRegs.I2CDXR/all = 0x44;// cmd 44
    I2cbRegs.I2CDXR/all = 2;//后面2个字节

    I2cbRegs.I2CDXR/all = dataQueries[dataIndex].cmdNum;// Ad & 0xFF;
    I2cbRegs.I2CDXX.ALL = 0;// Ad >> 8;
    I2cbRegs.I2CMDR.All = 0x2E20;//发送数据以设置EEPROM地址
    }
    否则

    I2cbRegs.I2CCNT = 1;
    I2cbRegs.I2CDXR/all = dataQueries[dataIndex].cmdNum;// Ad & 0xFF;
    I2cbRegs.I2CMDR.All = 0x2620;//发送数据至设置EEPROM地址
    }

    }

    返回I2C_SUCCESS;

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

    我没有得到您想要传达的信息。

    此致,
    Manoj