mpu6050的AD0引脚可以通过给高地电平来控制它的地址(0X68或0X69),mpu6050只支持2个级联,如果要连接更多就需要开起格外的I2C组了。如果我想同时采集10个mpu6050的数据怎么办,可以俩个分一组,用5组i2c线连接就行了。
我定义了2个全局变量I2CChose和AD0,用这2个变量来控制选择和谁通讯,这里主要考虑了对现有代码的利用,为了尽量少修改原来的单I2C驱动程序,选择使用修改宏定义的方式来修改地址和用哪根总线,代码如下
#define GPIO_PORT_IIC (I2CChose==1?(GPIOA):(I2CChose==2?(GPIOE):(I2CChose==3?(GPIOD):(I2CChose==4?(GPIOD):(I2CChose==5?(GPIOD):(I2CChose==6?(GPIOA):(I2CChose==7?(GPIOE):(GPIOC)))))))) /* GPIO端口 */
#define RCC_IIC_ENABLE __HAL_RCC_GPIOE_CLK_ENABLE() /* GPIO端口时钟 */
#define IIC_SCL_PIN (I2CChose==1?(GPIO_PIN_3):(I2CChose==2?(GPIO_PIN_3):(I2CChose==3?(GPIO_PIN_6):(I2CChose==4?(GPIO_PIN_4):(I2CChose==5?(GPIO_PIN_2):(I2CChose==6?(GPIO_PIN_5):(I2CChose==7?(GPIO_PIN_5):(GPIO_PIN_0)))))))) /* 连接到SCL时钟线的GPIO */
#define IIC_SDA_PIN (I2CChose==1?(GPIO_PIN_2):(I2CChose==2?(GPIO_PIN_2):(I2CChose==3?(GPIO_PIN_7):(I2CChose==4?(GPIO_PIN_5):(I2CChose==5?(GPIO_PIN_3):(I2CChose==6?(GPIO_PIN_4):(I2CChose==7?(GPIO_PIN_4):(GPIO_PIN_5)))))))) /* 连接到SDA数据线的GPIO */
#define IIC_SCL_1() HAL_GPIO_WritePin(GPIO_PORT_IIC, IIC_SCL_PIN, GPIO_PIN_SET) /* SCL = 1 */
#define IIC_SCL_0() HAL_GPIO_WritePin(GPIO_PORT_IIC, IIC_SCL_PIN, GPIO_PIN_RESET) /* SCL = 0 */
#define IIC_SDA_1() HAL_GPIO_WritePin(GPIO_PORT_IIC, IIC_SDA_PIN, GPIO_PIN_SET) /* SDA = 1 */
#define IIC_SDA_0() HAL_GPIO_WritePin(GPIO_PORT_IIC, IIC_SDA_PIN, GPIO_PIN_RESET) /* SDA = 0 */
#define IIC_SDA_READ() HAL_GPIO_ReadPin(GPIO_PORT_IIC, IIC_SDA_PIN) /* 读SDA口线状态 */
对原来的驱动程序不需要进行过多的修改就可以通过I2CChose来更改使用那一条模拟总线。
对应AD0也是如此
//如果AD0脚(9脚)接地,IIC地址为0X68(不包含最低位).
//如果接V3.3,则IIC地址为0X69(不包含最低位).
#define MPU_ADDR (AD0==0?0X68:0X69) //原0X68
顺便说一下,具体修改可能要根据你自己手里的mpu6050驱动进行修改,有些驱动里可能设置了const常量,导致你不能动态更改,要找出进行去掉,还有DMP库里的地址也要进行修改,官方的DMP库没有用宏定义的方式进行地址定义,用的是结构体,可以用下面的代码设置
if(AD0==1){
st.hw->addr = 0X69;
}else{
st.hw->addr = 0X68;
}
st.hw->addr 就是DMP库的存储器件地址的结构体成员
如上我们实现了I2CChose和AD0控制选择哪个mpu6050了,在主函数中写
//f1
I2CChose=1;
AD0=0;
while(MPU_Init()){}
while(mpu_dmp_init()){
len=sprintf(strtest,"mpu_dmp_init........f11\r\n"); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)strtest,len);
}
I2CChose=1;
AD0=1;
while(MPU_Init()){}
while(mpu_dmp_init()){
len=sprintf(strtest,"mpu_dmp_init.........f12\r\n"); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)strtest,len);
}
//f2
I2CChose=2;
AD0=0;
while(MPU_Init()){}
while(mpu_dmp_init()){
len=sprintf(strtest,"mpu_dmp_init........f21\r\n"); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)strtest,len);
}
I2CChose=2;
AD0=1;
while(MPU_Init()){}
while(mpu_dmp_init()){
len=sprintf(strtest,"mpu_dmp_init.........f22\r\n"); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)strtest,len);
}
进行异步初始化,然后在主函数的while()里面写
//mpu6050测试
I2CChose=1;
AD0=0;
//HAL_Delay(35);
while(mpu_dmp_get_data(&f11p, &f11r, &f11y)); //必须要用while等待,才能正常读取
I2CChose=1;
AD0=1;
//HAL_Delay(35);
while(mpu_dmp_get_data(&f12p, &f12r, &f12y)); //必须要用while等待,才能正常读取
I2CChose=2;
AD0=0;
//HAL_Delay(35);
while(mpu_dmp_get_data(&f21p, &f21r, &f21y)); //必须要用while等待,才能正常读取
I2CChose=2;
AD0=1;
//HAL_Delay(35);
while(mpu_dmp_get_data(&f22p, &f22r, &f22y)); //必须要用while等待,才能正常读取
进行数据的读取,之后再用H743的虚拟串口功能进行打印输出
//打包所有数据
len=sprintf(str,"f11p:%.1lf f11r:%.1lf f11y:%.1lf\r\nf12p:%.1lf f12r:%.1lf f12y:%.1lf\r\n"
"f21p:%.1lf f21r:%.1lf f21y:%.1lf\r\nf22p:%.1lf f22r:%.1lf f22y:%.1lf\r\n",
f11p,f11r,f11y,f12p,f12r,f12y,f21p,f21r,f21y,f22p,f22r,f22y); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)str,len);
HAL_Delay(30);
len=sprintf(str,"\r\n\r\n**********\r\n\r\n"); //虚拟串口打印数据
CDC_Transmit_FS((uint8_t*)str,len);
可以看见串口助手成功接收到了数据,而且H743本身的性能强劲,10秒接收并输出1万次,可以实现高精度的动态采集。
以上是我自己的学习笔录,需要源码的朋友可以私信联系我。