DRV2604L的I2C无法通讯

Other Parts Discussed in Thread: DRV2604L, MSP430G2553, DRV2604

您好,使用MSP430G2553驱动DRV2604L,I2C无法通讯,I2C初始化及寄存器配置如下:

/*************************************************
函数名称:DRV2604L_Init(void)
功 能:DRV2604L初始化
参 数:无
返回值 :无
**************************************************/
void Init_DRV2604L(void)
{
P2OUT |= 0x20;
I2C_Init();
DRV2604L_Write_ModeSel();
DRV2604L_Write_LRASel();
DRV2604L_Write_LRAOpenLoop();
DRV2604L_Write_LRAPeriod();
P2OUT &= ~0x20; //5V Unenable

}

/*************************************************
函数名称:I2C_Init(void)
功 能:I2C初始化
参 数:无
返回值 :无
**************************************************/
void I2C_Init(void)
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗定时器
P1SEL |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA
P1SEL2 |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA

UCB0CTL1 |= UCSWRST; //复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; //主模式+IIC模式+同步模式
UCB0CTL1 |= UCSSEL_2 + UCSWRST; //SMCLK+复位
UCB0BR0 = 10; //时钟分频设置(UCBxBR0 + UCBxBR1 × 256)
UCB0BR1 = 0; //1MHZ/10=100KHZ
UCB0I2CSA = 0x5A; //7位地址
UCB0CTL1 &= ~UCSWRST; //清复位标志
delay_us(1);
}

/*************************************************
函数名称:DRV2604L_Write_ModeSel(void)
功 能:PWM模式选择
参 数:无
返回值 :无
**************************************************/
void DRV2604L_Write_ModeSel(void)
{
I2C_Init();
while(UCB0CTL1 & UCTXSTP); //If ICC Stop
UCB0CTL1 |= UCTR;
UCB0CTL1 |= UCTXSTT; //IIC Start + Write


while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
UCB0TXBUF = 0xB4; //ADDRESS+WRITE
while((UCB0CTL1 & UCTXSTT) == UCTXSTT); //检测ACK信号,如果有ACK信号,则UCTXSTT自动清零
delay_us(1);

UCB0TXBUF = 0x01; //Mode register Address
while(!(IFG2 & UCB0TXIFG));  //一直卡在这一句
delay_us(1);

UCB0TXBUF = 0x03; //PWM Mode
while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
delay_us(1);

UCB0CTL1 |= UCTXSTP + UCTXNACK; //IIC Stop + NACK
while((UCB0CTL1 & UCTXSTP) == 1);
}

while(!(IFG2 & UCB0TXIFG));将这一句屏蔽后,用示波器观察SCL及SDA输出波形是正确的,基本可以确定从机无响应,请问是DRV2604的从机地址问题还是,通讯格式有问题?

  • 您好,下面是I2C初始化和2604L寄存器配置部分程序,无法通讯,请大神回复,谢谢
    !!

    /*************************************************
    函数名称:DRV2604L_Init(void)
    功 能:DRV2604L初始化
    参 数:无
    返回值 :无
    **************************************************/
    void Init_DRV2604L(void)
    {
    P2OUT |= 0x20;  //5V
    delay_us(300);
    P3OUT |= 0x04;  //2604L EN
    delay_us(10);
    DRV2604L_Write_Reset();
    delay_us(300);
    DRV2604L_Write_ModeSel();
    delay_us(10);
    DRV2604L_Write_LRASel();
    delay_us(10);
    DRV2604L_Write_LRAOpenLoop();
    delay_us(10);
    DRV2604L_Write_LRAPeriod();
    delay_us(10);
    P3OUT &= ~0x04;
    P2OUT &= ~0x20; //5V Unenable

    }


    /*************************************************
    函数名称:I2C_Init(void)
    功 能:I2C初始化
    参 数:无
    返回值 :无
    **************************************************/
    void I2C_Init(void)
    {
    WDTCTL = WDTPW + WDTHOLD; //关闭看门狗定时器
    P1SEL |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA
    P1SEL2 |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA

    UCB0CTL1 |= UCSWRST; //复位
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; //主模式+IIC模式+同步模式
    UCB0CTL1 |= UCSSEL_2 + UCSWRST; //SMCLK+复位
    UCB0BR0 = 10; //时钟分频设置(UCBxBR0 + UCBxBR1 × 256)
    UCB0BR1 = 0; //1MHZ/10=100KHZ
    UCB0I2CSA = 0xA5; //7位地址
    UCB0CTL1 &= ~UCSWRST; //清复位标志
    delay_us(1);
    }

    /*************************************************
    函数名称:DRV2604L_Write_Reset(void)
    功 能:Reset
    参 数:无
    返回值 :无
    **************************************************/
    void DRV2604L_Write_Reset(void)
    {
    I2C_Init();
    while(UCB0CTL1 & UCTXSTP); //If ICC Stop
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT; //IIC Start + Write


    // while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
    // UCB0TXBUF = 0xB4; //ADDRESS+WRITE
    // while((UCB0CTL1 & UCTXSTT) == UCTXSTT); //检测ACK信号,如果有ACK信号,则UCTXSTT自动清零
    // delay_us(1);

    UCB0TXBUF = 0x01; //Mode register Address
    while(!(IFG2 & UCB0TXIFG));  //一直卡在这一句,无法和DRV2604通讯
    delay_us(1);

    UCB0TXBUF = 0x80; //Reset
    while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
    delay_us(1);

    UCB0CTL1 |= UCTXSTP + UCTXNACK; //IIC Stop + NACK
    while((UCB0CTL1 & UCTXSTP) == 1);

    /*************************************************
    函数名称:DRV2604L_Write_ModeSel(void)
    功 能:PWM模式选择
    参 数:无
    返回值 :无
    **************************************************/
    void DRV2604L_Write_ModeSel(void)
    {
    I2C_Init();
    while(UCB0CTL1 & UCTXSTP); //If ICC Stop
    UCB0CTL1 |= UCTR;
    UCB0CTL1 |= UCTXSTT; //IIC Start + Write


    // while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
    // UCB0TXBUF = 0xB4; //ADDRESS+WRITE
    // while((UCB0CTL1 & UCTXSTT) == UCTXSTT); //检测ACK信号,如果有ACK信号,则UCTXSTT自动清零
    // delay_us(1);

    UCB0TXBUF = 0x01; //Mode register Address
    while(!(IFG2 & UCB0TXIFG));
    delay_us(1);

    UCB0TXBUF = 0x03; //PWM Mode
    while(!(IFG2 & UCB0TXIFG)); //判断UCB0TXBUF是否为空
    delay_us(1);

    UCB0CTL1 |= UCTXSTP + UCTXNACK; //IIC Stop + NACK
    while((UCB0CTL1 & UCTXSTP) == 1);
    }

  • 您是否知道设备是否通过确认标志响应设备地址?
    否则,您可以尝试向左或向右移动1位吗? 我的意思是说,I2C地址为0x2D或0xB4。
  • 试过了,不行,现在确认是从机没有ack返回。

    void i2c_writeByte(char slave_addr, char reg_addr, char data)

    {

     while((UCB0STAT & BUSY)!=0);             //make sure bus is free

     UCB0I2CSA = slave_addr;                   // Slave Address is 0x5A for accelerometer

     while(UCB0CTL1 & UCTXSTP);               //If ICC Stop

     UCB0CTL1 |=UCTR;                          //set write bit

     UCB0CTL1 |= UCTXSTT;                      // send start and slave address+Write

     if (UCB0STAT & UCNACKIFG)               //address not acknowledged

     {

       UCB0CTL1 |= UCTXSTP;                  // I2C stop condition   这打个断点,程序运行到这里

       UCB0STAT &= ~UCNACKIFG;               //clear nack flag

     }

     UCB0TXBUF=reg_addr;                      //load register address to transmitt buffer

     while(UCB0CTL1 & UCTXSTT);              // Wait for the start sequence to complete

     UCB0TXBUF=data;

     UCB0CTL1 |= UCTXSTP + UCTXNACK;        //IIC Stop + NACK

     while((UCB0CTL1 & UCTXSTP) == 1);

    }

    上图为执行一次void i2c_writeByte(char slave_addr, char reg_addr, char data)函数的I2C波形

    /*************************************************
    函数名称:DRV2604L_Init(void)
    功 能:DRV2604L初始化
    参 数:无
    返回值 :无
    **************************************************/
    void Init_DRV2604L(void)
    {
    P2OUT |= 0x20;
    delay_ms(2);
    P3OUT |= 0x04;
    delay_ms(2);
    I2C_Init();
    i2c_writeByte(0x5A,0x01,0x00); //reset
    // DRV2604L_Write_Reset();
    i2c_writeByte(0x5A,0x01,0x03); //PWM Mode
    // DRV2604L_Write_ModeSel();
    i2c_writeByte(0x5A,0x1A,0xB6); //LAR Mode
    // DRV2604L_Write_LRASel();
    i2c_writeByte(0x5A,0x1D,0x81); //LAR Open Mode
    // DRV2604L_Write_LRAOpenLoop();
    i2c_writeByte(0x5A,0x20,0x54); //LAR Mode
    // DRV2604L_Write_LRAPeriod();
    delay_us(10);
    P3OUT &= ~0x04;
    P2OUT &= ~0x20; //5V Unenable

    }

    /*************************************************
    函数名称:I2C_Init(void)
    功 能:I2C初始化
    参 数:无
    返回值 :无
    **************************************************/
    void I2C_Init(void)
    {
    WDTCTL = WDTPW + WDTHOLD; //关闭看门狗定时器
    P1SEL |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA
    P1SEL2 |= (BIT6 + BIT7); // P1.6 = SCL, P1.7=SDA

    UCB0CTL1 |= UCSWRST; //复位
    UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; //主模式+IIC模式+同步模式
    UCB0CTL1 |= UCSSEL_2 + UCSWRST; //SMCLK+复位
    UCB0BR0 = 12; //时钟分频设置(UCBxBR0 + UCBxBR1 × 256)
    UCB0BR1 = 0; //1MHZ/10=100KHZ
    // UCB0I2CSA = 0x5A; //7位地址
    UCB0CTL1 &= ~UCSWRST; //清复位标志
    delay_us(1);
    }

  • 硬件I2C发送了写地址0xB4,但是从机没有响应
  • 请您能否仅测试一个I2C命令,只是为了检查确认位是否由设备返回?

    设备需要发送该位,以确保进行I2C通信。 另外,是否在I2C命令期间启用了设备?我的意思是,EN引脚是否为“高”电平?

  • /*************************************************
    函数名称:DRV2604L_Init(void)
    功 能:DRV2604L初始化
    参 数:无
    返回值 :无
    **************************************************/
    void Init_DRV2604L(void)
    {
    P2OUT |= 0x20;//2604L供电2ms后开的EN
    delay_ms(2);
    P3OUT |= 0x04;  //开EN,延时2ms后才去操作的I2C写命令
    delay_ms(2);
    I2C_Init();
    // i2c_writeByte(0x5A,0x01,0x80); //设备reset
    delay_ms(2);
    i2c_writeByte(0x5A,0x01,0x00); //reset
    // delay_ms(2);
    // DRV2604L_Write_Reset();
    i2c_writeByte(0x5A,0x01,0x03); //PWM Mode
    // DRV2604L_Write_ModeSel();
    i2c_writeByte(0x5A,0x1A,0xB6); //LAR Mode
    // DRV2604L_Write_LRASel();
    i2c_writeByte(0x5A,0x1D,0x81); //LAR Open Mode
    // DRV2604L_Write_LRAOpenLoop();
    i2c_writeByte(0x5A,0x20,0x54); //LAR Period
    // DRV2604L_Write_LRAPeriod();
    delay_ms(2);
    P3OUT &= ~0x04;
    P2OUT &= ~0x20; //5V Unenable

    }

  • 如果方便的话是否能提供DRV2604的初始化例程,如果可以,非常感谢!!
  • 初始化例程可以在数据表的9.4节中找到:

    https://www.ti.com/lit/ds/symlink/drv2604l.pdf#page=58

    但是,建议您检查设备是否响应I2C地址,您必须在发送I2C地址后确保有一个ACK位。

    然后,将地址0x1A /位7 ='1'配置为LRA模式,将设备置于寄存器0x01 /位6 ='0'的活动模式,选择地址0x01 /位2-0的自动校准模式 =“ 111”并选择寄存器0x0c的GO位。

    此过程必须显示LRA负载的活动。 如果问题仍然存在,建议您检查电路连接以及执行器和IC是否损坏。

  • 您好,annie Liu:

    希望您看完我的邮件后,希望TI技术支持工程师能给联系我电话支持,非常感谢,因为这件事儿比较急,我的电话是010-51570080-876,期待您的来电

    我是要配置成开环PWM模式,至于数据表中的寄存器配置,我都是按照数据表推荐配置的,初始化都是按照数据表推荐的初始化顺序。现在的情况是,I2C通讯成功了,但是我配置成开环PWM模式,2604L无法正常驱动LRA马达,详见下图:

    1.I2C通讯

    通讯波形展开:

    配置完寄存器后2604L的out+(蓝色):

    out+只输出一下就停止输出了,连接马达的情况下,也是马达只是振动一下然后就停止了

    PWM输入(IN/TRIG脚):170Hz*128

    下面是我配置的寄存器参数:

    /*************************************************
    函数名称:DRV2604L_Init(void)
    功 能:DRV2604L初始化
    参 数:无
    返回值 :无
    **************************************************/
    void Init_DRV2604L(void)
    {
    P2OUT |= 0x20; //PWR ON
    delay_ms(2);
    P3OUT |= 0x04;// 2604L EN
    delay_ms(2);
    I2C_Init();
    i2c_writeByte(0x5A,0x01,0x00); //reset
    // delay_ms(2);
    // DRV2604L_Write_Reset();
    i2c_writeByte(0x5A,0x01,0x03); //PWM Mode
    // DRV2604L_Write_ModeSel();
    i2c_writeByte(0x5A,0x1A,0xB6); //LAR Mode
    // DRV2604L_Write_LRASel();
    i2c_writeByte(0x5A,0x1D,0x81); //LAR Open Mode
    // DRV2604L_Write_LRAOpenLoop();
    i2c_writeByte(0x5A,0x20,0x3C); //LAR Period
    // DRV2604L_Write_LRAPeriod();
    i2c_writeByte(0x5A,0x17,0x38); //LAR Voltage
    delay_ms(2);
    // P3OUT &= ~0x04;
    // P2OUT &= ~0x20; //5V Unenable

    }

    主程序我屏蔽了所有的功能,只是配置完2604L初始化后没有后续动作:

    /*************************************************
    函数名称:main(void)
    功 能:主程序
    参 数:无
    返回值 :无
    **************************************************/
    void main(void)
    {
    float fSmpledBatteryVoltage =0;
    unsigned int nOneMINCounter = 0; //TIMERA1接收中断计数


    WDTCTL = WDTPW + WDTHOLD; //Stop WacthDog
    Init_GPIO(); //GPIO Init
    Init_IO_Interrupt(); //IO Interrupt Init
    Init_CLK(); //SET CLOCK
    Init_DRV2604L(); //SET PWM Mode
    Init_Timer0_A(LED_PWM_Period); //TA0 Init
    Init_Timer1_A(Motor_PWM_Period); //TA1 Init
    _EINT();

    // i2c_writeByte(0x5A,0x0C,0x01); //GO bit
    while(1);

  • 很抱歉,支持的工程师在美国的。您可以直接在这个帖子中跟工程师沟通:http://e2e.ti.com/support/motor-drivers/f/38/p/899011/3327227