您好,使用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的从机地址问题还是,通讯格式有问题?
user5981564:
您好,下面是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);}
Annie Liu:
您是否知道设备是否通过确认标志响应设备地址?
否则,您可以尝试向左或向右移动1位吗? 我的意思是说,I2C地址为0x2D或0xB4。
user5981564:
回复 Annie Liu:
试过了,不行,现在确认是从机没有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);}
user5981564:
回复 user5981564:
硬件I2C发送了写地址0xB4,但是从机没有响应
Annie Liu:
回复 user5981564:
请您能否仅测试一个I2C命令,只是为了检查确认位是否由设备返回?
设备需要发送该位,以确保进行I2C通信。 另外,是否在I2C命令期间启用了设备?我的意思是,EN引脚是否为“高”电平?
user5981564:
回复 Annie Liu:
/*************************************************函数名称: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 }
user5981564:
回复 user5981564:
如果方便的话是否能提供DRV2604的初始化例程,如果可以,非常感谢!!
Annie Liu:
回复 user5981564:
初始化例程可以在数据表的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是否损坏。
user5981564:
回复 Annie Liu:
您好,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);
Annie Liu:
回复 user5981564:
很抱歉,支持的工程师在美国的。您可以直接在这个帖子中跟工程师沟通:http://e2e.ti.com/support/motor-drivers/f/38/p/899011/3327227