打印
[应用相关]

利用stm32f4单片机的mpu6050六轴加速度传感器

[复制链接]
楼主: 自动化陈稳
手机看帖
扫描二维码
随时随地手机跟帖
21
自动化陈稳|  楼主 | 2022-4-30 12:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
然后再看 MPU_Get_Temperature、 MPU_Get_Gyroscope 和 MPU_Get_Accelerometer 等三个
函数,源码如下:

使用特权

评论回复
22
自动化陈稳|  楼主 | 2022-4-30 12:28 | 只看该作者
//得到温度值
//返回值:温度值(扩大了 100 倍)
short MPU_Get_Temperature(void)
{
u8 buf[2];
short raw; float temp;
MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf);
raw=((u16)buf[0]<<8)|buf[1];
temp=36.53+((double)raw)/340;
return temp*100;;
}
//得到陀螺仪值(原始值)
//gx,gy,gz:陀螺仪 x,y,z 轴的原始读数(带符号)
//返回值:0,成功
// 其他,错误代码
u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
{
u8 buf[6],res;
res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf);
if(res==0)
{
*gx=((u16)buf[0]<<8)|buf[1];
*gy=((u16)buf[2]<<8)|buf[3];
*gz=((u16)buf[4]<<8)|buf[5];
}
return res;;
}
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪 x,y,z 轴的原始读数(带符号)
//返回值:0,成功
// 其他,错误代码
u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
{
u8 buf[6],res;
res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf);
if(res==0)
{
*ax=((u16)buf[0]<<8)|buf[1];
*ay=((u16)buf[2]<<8)|buf[3];
*az=((u16)buf[4]<<8)|buf[5];
}
return res;;
}

使用特权

评论回复
23
自动化陈稳|  楼主 | 2022-4-30 12:29 | 只看该作者
其中 MPU_Get_Temperature 用于获取 MPU6050 自带温度传感器的温度值,然后MPU_Get_Gyroscope 和 MPU_Get_Accelerometer 分别用于读取陀螺仪和加速度传感器的原始数据。

使用特权

评论回复
24
自动化陈稳|  楼主 | 2022-4-30 12:29 | 只看该作者
最后看 MPU_Write_Len 和 MPU_Read_Len 这两个函数,代码如下
//IIC 连续写
//addr:器件地址 reg:寄存器地址
//len:写入长度 buf:数据区
//返回值:0,正常 其他,错误代码
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
u8 i;
IIC_Start();
IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令
if(IIC_Wait_Ack()){IIC_Stop();return 1;}//等待应答
IIC_Send_Byte(reg); //写寄存器地址
IIC_Wait_Ack(); //等待应答
for(i=0;i<len;i++)
{
IIC_Send_Byte(buf[i]); //发送数据
if(IIC_Wait_Ack()) {IIC_Stop();return 1;}//等待 ACK
}
IIC_Stop();
return 0;
}
//IIC 连续读
//addr:器件地址 reg:要读取的寄存器地址
//len:要读取的长度 buf:读取到的数据存储区
//返回值:0,正常 其他,错误代码
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
IIC_Start();
IIC_Send_Byte((addr<<1)|0); //发送器件地址+写命令
if(IIC_Wait_Ack()){ IIC_Stop();return 1; } //等待应答
IIC_Send_Byte(reg); //写寄存器地址
IIC_Wait_Ack(); //等待应答
IIC_Start();
IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令
IIC_Wait_Ack(); //等待应答
while(len)
{
if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送 nACK
else *buf=IIC_Read_Byte(1); //读数据,发送 ACK
len--; buf++;
}
IC_Stop(); //产生一个停止条件
return 0;
}

使用特权

评论回复
25
自动化陈稳|  楼主 | 2022-4-30 12:30 | 只看该作者
MPU_Write_Len 用于指定器件和地址,连续写数据,可用于实现 DMP 部分的: i2c_write函数。而 MPU_Read_Len 用于指定器件和地址,连续读数据,可用于实现 DMP 部分的: i2c_read函数。 DMP 移植部分的 4 个函数,这里就实现了 2 个,剩下的 delay_ms 就直接采用我们 delay.c里面的 delay_ms 实现, get_ms 则直接提供一个空函数即可。

使用特权

评论回复
26
自动化陈稳|  楼主 | 2022-4-30 12:31 | 只看该作者
关于 mpu6050.c 就介绍到这。

最后看看 main.c 代码如下:
//串口 1 发送 1 个字符
//c:要发送的字符
void usart1_send_char(u8 c)
{
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
USART_SendData(USART1,c);
}
//传送数据给匿名四轴上位机软件(V2.6 版本)
//fun:功能字. 0XA0~0XAF
//data:数据缓存区,最多 28 字节!!
//len:data 区有效数据个数
void usart1_niming_report(u8 fun,u8*data,u8 len)
{
u8 send_buf[32],i;
if(len>28)return; //最多 28 字节数据
send_buf[len+3]=0;//校验数置零
send_buf[0]=0X88;//帧头
send_buf[1]=fun; //功能字
send_buf[2]=len; //数据长度
for(i=0;i<len;i++)send_buf[3+i]=data[i]; //复制数据
for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i]; //计算校验和
for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]); //发送数据到串口 1
}
//发送加速度传感器数据和陀螺仪数据
//aacx,aacy,aacz:x,y,z 三个方向上面的加速度值
//gyrox,gyroy,gyroz:x,y,z 三个方向上面的陀螺仪值
void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
{
u8 tbuf[12];
tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF;
tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF;
tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF;
tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF;
tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF;
tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF;
usart1_niming_report(0XA1,tbuf,12);//自定义帧,0XA1
}
//通过串口 1 上报结算后的姿态数据给电脑
//aacx,aacy,aacz:x,y,z 三个方向上面的加速度值
//gyrox,gyroy,gyroz:x,y,z 三个方向上面的陀螺仪值
//roll:横滚角.单位 0.01 度。 -18000 -> 18000 对应 -180.00 -> 180.00 度
//pitch:俯仰角.单位 0.01 度。 -9000 - 9000 对应 -90.00 -> 90.00 度
//yaw:航向角.单位为 0.1 度 0 -> 3600 对应 0 -> 360.0 度
void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,
short gyroz,short roll,short pitch,short yaw)
{
u8 tbuf[28];
u8 i;
for(i=0;i<28;i++)tbuf[i]=0;//清 0
tbuf[0]=(aacx>>8)&0XFF; tbuf[1]=aacx&0XFF;
tbuf[2]=(aacy>>8)&0XFF; tbuf[3]=aacy&0XFF;
tbuf[4]=(aacz>>8)&0XFF; tbuf[5]=aacz&0XFF;
tbuf[6]=(gyrox>>8)&0XFF; tbuf[7]=gyrox&0XFF;
tbuf[8]=(gyroy>>8)&0XFF; tbuf[9]=gyroy&0XFF;
tbuf[10]=(gyroz>>8)&0XFF; tbuf[11]=gyroz&0XFF;
tbuf[18]=(roll>>8)&0XFF; tbuf[19]=roll&0XFF;
tbuf[20]=(pitch>>8)&0XFF; tbuf[21]=pitch&0XFF;
tbuf[22]=(yaw>>8)&0XFF; tbuf[23]=yaw&0XFF;
usart1_niming_report(0XAF,tbuf,28);//飞控显示帧,0XAF
}
int main(void)
{
u8 t=0,report=1; //默认开启上报
u8 key;
float pitch,roll,yaw; //欧拉角
short aacx,aacy,aacz; //加速度传感器原始数据
short gyrox,gyroy,gyroz;//陀螺仪原始数据
short temp; //温度
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组 2
delay_init(168); //初始化延时函数
uart_init(500000); //初始化串口波特率为 500000
LED_Init(); //初始化 LED
KEY_Init(); //初始化按键
LCD_Init(); //LCD 初始化
MPU_Init(); //初始化 MPU6050
POINT_COLOR=RED;//设置字体为红色
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2014/5/9");
while(mpu_dmp_init())
{ LCD_ShowString(30,130,200,16,16,"MPU6050 Error"); delay_ms(200);
LCD_Fill(30,130,239,130+16,WHITE); delay_ms(200);
}
LCD_ShowString(30,130,200,16,16,"MPU6050 OK");
LCD_ShowString(30,150,200,16,16,"KEY0:UPLOAD ON/OFF");
POINT_COLOR=BLUE;//设置字体为蓝色
LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");
LCD_ShowString(30,200,200,16,16," Temp: . C");
LCD_ShowString(30,220,200,16,16,"Pitch: . C");
LCD_ShowString(30,240,200,16,16," Roll: . C");
LCD_ShowString(30,260,200,16,16," Yaw : . C");
while(1)
{
key=KEY_Scan(0);
if(key==KEY0_PRES)
{
report=!report;
if(report)LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");
else LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");
}
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
{
temp=MPU_Get_Temperature(); //得到温度值
MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据
MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据
if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);
//用自定义帧发送加速度和陀螺仪原始数据
if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),
(int)(pitch*100),(int)(yaw*10));
if((t%10)==0)
{
if(temp<0)
{
LCD_ShowChar(30+48,200,'-',16,0); //显示负号
temp=-temp; //转为正数
}else LCD_ShowChar(30+48,200,' ',16,0); //去掉负号
LCD_ShowNum(30+48+8,200,temp/100,3,16); //显示整数部分
LCD_ShowNum(30+48+40,200,temp%10,1,16); //显示小数部分
temp=pitch*10;
if(temp<0)
{
LCD_ShowChar(30+48,220,'-',16,0); //显示负号
temp=-temp; //转为正数
}else LCD_ShowChar(30+48,220,' ',16,0); //去掉负号
LCD_ShowNum(30+48+8,220,temp/10,3,16); //显示整数部分
LCD_ShowNum(30+48+40,220,temp%10,1,16); //显示小数部分
temp=roll*10;
if(temp<0)
{
LCD_ShowChar(30+48,240,'-',16,0); //显示负号
temp=-temp; //转为正数
}else LCD_ShowChar(30+48,240,' ',16,0); //去掉负号
LCD_ShowNum(30+48+8,240,temp/10,3,16); //显示整数部分
LCD_ShowNum(30+48+40,240,temp%10,1,16); //显示小数部分
temp=yaw*10;
if(temp<0)
{
LCD_ShowChar(30+48,260,'-',16,0); //显示负号
temp=-temp; //转为正数
}else LCD_ShowChar(30+48,260,' ',16,0); //去掉负号
LCD_ShowNum(30+48+8,260,temp/10,3,16); //显示整数部分
LCD_ShowNum(30+48+40,260,temp%10,1,16); //显示小数部分
t=0; LED0=!LED0;//LED 闪烁
}
}
t++;
}
}

使用特权

评论回复
27
自动化陈稳|  楼主 | 2022-4-30 12:32 | 只看该作者
此部分代码除了 main 函数,还有几个函数,用于上报数据给上位机软件,利用上位机软件显示传感器波形,以及 3D 姿态显示,有助于更好的调试 MPU6050。上位机软件推荐使用: ANO_Tech匿名四轴上位机_V2.6.exe。 usart1_niming_report 函数用于将数据打包、计算校验和,然后上报给匿名四轴上位机软件。mpu6050_send_data 函数用于上报加速度和陀螺仪的原始数据,可用于波形显示传感器数据,通过 A1 自定义帧发送。而 usart1_report_imu 函数,则用于上报飞控显示帧,可以实时 3D 显示
MPU6050 的姿态,传感器数据等。

使用特权

评论回复
28
自动化陈稳|  楼主 | 2022-4-30 12:33 | 只看该作者
这里, main 函数是比较简单的,大家看代码即可,不过需要注意的是,为了高速上传数据,
这里将串口 1 的波特率设置为 500Kbps 了,测试的时候要注意下。

使用特权

评论回复
29
自动化陈稳|  楼主 | 2022-4-30 12:34 | 只看该作者
最后,将 MPU_Write_Byte、 MPU_Read_Byte 和 MPU_Get_Temperature 等三个函数加入 USMART 控制,这样,我们就可以通过串口调试助手,改写和读取 MPU6050 的寄存器数据了,并可以读取温度传感器的值,方便大家调试(注意在 USMART 调试的时候,最好通过按KEY0,先关闭数据上传功能,否则会受到很多乱码,妨碍调试)。
至此,我们的软件设计部分就结束了。

使用特权

评论回复
30
自动化陈稳|  楼主 | 2022-4-30 12:34 | 只看该作者
下载验证:

在代码编译成功之后,我们通过下载代码到 ALIENTEK 探索者 STM32F4 开发板上,可以
看到 LCD 显示如图 :

使用特权

评论回复
31
自动化陈稳|  楼主 | 2022-4-30 12:35 | 只看该作者
屏幕显示了 MPU6050 的温度、俯仰角(pitch)、横滚角(roll)和航向角(yaw)的数值。
然后,可以晃动开发板,看看各角度的变化。

使用特权

评论回复
32
自动化陈稳|  楼主 | 2022-4-30 12:36 | 只看该作者
另外,通过按 KEY0 可以开启或关闭数据上报,开启状态下,我们可以打开: ANO_Tech
匿名四轴上位机_V2.6.exe(该软件双击后,会弹出一个蓝色的小界面,直接关闭即可。

使用特权

评论回复
33
自动化陈稳|  楼主 | 2022-4-30 12:37 | 只看该作者
然后才
会进入主界面),这个软件,接收 STM32F4 上传的数据,从而图形化显示传感器数据以及飞行
姿态,如图 :
传感器数据波形显示:

使用特权

评论回复
34
自动化陈稳|  楼主 | 2022-4-30 12:38 | 只看该作者
飞控状态显示:

使用特权

评论回复
35
自动化陈稳|  楼主 | 2022-4-30 12:38 | 只看该作者
也可以通过串口调试助手,读取数据,保存数据,对数据进行后续处理。

使用特权

评论回复
36
天空大海| | 2022-8-11 17:38 | 只看该作者
厉害了,学习学习

使用特权

评论回复
37
51xlf| | 2022-10-1 12:30 | 只看该作者
可以使用dmp实现数据的读取吗?                                 

使用特权

评论回复
38
Uriah| | 2022-10-1 14:30 | 只看该作者

多次检查也会给单片机带来负荷,对功耗不利

使用特权

评论回复
39
Bblythe| | 2022-10-1 17:29 | 只看该作者

如果在编程时加密锁定位被使能/锁定,就无法用普通编程器直接读取单片机内的程序

使用特权

评论回复
40
qbwww| | 2022-10-2 07:01 | 只看该作者
免除了组合陀螺仪与加速器时间轴之差的问题,减少了大量的封装空间

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则