电子说
(2)创建mpu6050.c文件,输入以下代码。
/*********************************************************************************************************
MUP6050 驱 动 程 序
*********************************************************************************************************/
#include "mpu6050.h"
#include "delay.h"
/***************************************************
Name :MPU_IIC_Init
Function :初始化IIC
Paramater :None
Return :None
***************************************************/
void MPU_IIC_Init()
{
RCC->APB2ENR |= 1<<3 ; //先使能PB时钟
GPIOB->CRH &= 0xFFFF00FF ; //PB10/11 推挽输出
GPIOB->CRH |= 0x00003300 ;
GPIOB->ODR |= 3<<10 ; //PB10,11 输出高
}
/***************************************************
Name :MPU_IIC_Wait_Ack
Function :开始时序
Paramater :None
Return :None
***************************************************/
void MPU_IIC_Start()
{
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00003000 ;
MPU_IIC_SDA = 1 ;
MPU_IIC_SCL = 1 ;
delay_us( 2 ) ;
MPU_IIC_SDA = 0 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 0 ;
}
/***************************************************
Name :MPU_IIC_Wait_Ack
Function :停止时序
Paramater :None
Return :None
***************************************************/
void MPU_IIC_Stop()
{
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00003000 ;
MPU_IIC_SCL = 0 ;
MPU_IIC_SDA = 0 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 1 ;
MPU_IIC_SDA = 1 ;
delay_us( 2 ) ;
}
/***************************************************
Name :MPU_IIC_Wait_Ack
Function :应答时序
Paramater :None
Return :
0:成功
1:失败
***************************************************/
u8 MPU_IIC_Wait_Ack()
{
u8 ucErrTime=0 ;
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00008000 ;
MPU_IIC_SDA = 1 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 1 ;
delay_us( 2 ) ;
while( MPU_READ_SDA )
{
ucErrTime ++ ;
if( ucErrTime>250 )
{
MPU_IIC_Stop() ;
return 1 ;
}
}
MPU_IIC_SCL = 0 ; //时钟输出0
return 0 ;
}
/***************************************************
Name :MPU_IIC_Send_Byte
Function :IIC发送1个字节
Paramater :
Ack:应答控制
0:不应答
1:应答
Return :None
***************************************************/
void MPU_IIC_Send_Byte( u8 Byte )
{
u8 i ;
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00003000 ;
MPU_IIC_SCL = 0 ; //拉低时钟开始数据传输
for( i=0; i<8; i++ )
{
if( ( Byte&0x80 )==0x80 )
MPU_IIC_SDA = 1 ;
else
MPU_IIC_SDA = 0 ;
Byte <<= 1 ;
MPU_IIC_SCL = 1 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 0 ;
delay_us( 2 ) ;
}
}
/***************************************************
Name :MPU_IIC_Read_Byte
Function :IIC读取1个字节
Paramater :
Ack:应答控制
0:不应答
1:应答
Return :读取的字节
***************************************************/
u8 MPU_IIC_Read_Byte( u8 Ack )
{
u8 i, Byte=0;
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00008000 ;
for( i=0; i<8; i++ )
{
MPU_IIC_SCL = 0 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 1 ;
Byte <<= 1 ;
if( MPU_READ_SDA )
Byte ++ ;
delay_us( 2 ) ;
}
MPU_IIC_SCL = 0 ;
GPIOB->CRH &= 0xFFFF0FFF ;
GPIOB->CRH |= 0x00003000 ;
MPU_IIC_SDA = 1-Ack ;
delay_us( 2 ) ;
MPU_IIC_SCL = 1 ;
delay_us( 2 ) ;
MPU_IIC_SCL = 0 ;
return Byte ;
}
/***************************************************
Name :MPU_Write_Byte
Function :IIC写一个字节
Paramater :
reg:寄存器地址
data:数据
Return :
0:正常
其他:错误代码
***************************************************/
u8 MPU_Write_Byte( u8 reg, u8 data )
{
MPU_IIC_Start() ;
MPU_IIC_Send_Byte( MPU_ADDR<<1 ) ; //发送器件地址+写命令
//等待应答
if( MPU_IIC_Wait_Ack() )
{
MPU_IIC_Stop() ;
return 1 ;
}
MPU_IIC_Send_Byte( reg ) ; //写寄存器地址
MPU_IIC_Wait_Ack() ; //等待应答
MPU_IIC_Send_Byte( data ) ; //发送数据
//等待ACK
if( MPU_IIC_Wait_Ack() )
{
MPU_IIC_Stop() ;
return 1 ;
}
MPU_IIC_Stop() ;
return 0 ;
}
/***************************************************
Name :MPU_Read_Byte
Function :IIC读一个字节
Paramater :
reg:寄存器地址
Return :读到的数据
***************************************************/
u8 MPU_Read_Byte( u8 reg )
{
u8 res ;
MPU_IIC_Start() ;
MPU_IIC_Send_Byte( MPU_ADDR<<1 ) ; //发送器件地址+写命令
MPU_IIC_Wait_Ack() ; //等待应答
MPU_IIC_Send_Byte( reg ) ; //写寄存器地址
MPU_IIC_Wait_Ack() ; //等待应答
MPU_IIC_Start() ;
MPU_IIC_Send_Byte( ( MPU_ADDR<<1 )|1 ) ; //发送器件地址+读命令
MPU_IIC_Wait_Ack() ; //等待应答
res = MPU_IIC_Read_Byte( 0 ) ; //读取数据,发送nACK
MPU_IIC_Stop() ; //产生一个停止条件
return res ;
}
/***************************************************
Name :MPU_Read_Byte
Function :设置MPU6050的采样率(假定Fs=1KHz)
Paramater :
rate:4~1000(Hz)
Return :
0:成功
其他:失败
***************************************************/
u8 MPU_Set_Rate( u16 rate )
{
u8 data ;
if( rate>1000 )
rate=1000 ;
if( rate<4 )
rate = 4 ;
data = 1000/rate-1 ;
data = MPU_Write_Byte( MPU_SAMPLE_RATE_REG, data ) ; //设置数字低通滤波器
//自动设置LPF为采样率的一半
if( ( rate/2 )>=188 )
data = 1 ;
else if( ( rate/2 )>=98 )
data = 2 ;
else if( ( rate/2 )>=42 )
data = 3 ;
else if( ( rate/2 )>=20 )
data = 4;
else if( ( rate/2 )>=10 )
data = 5 ;
else
data = 6 ;
return MPU_Write_Byte( MPU_CFG_REG, data ) ; //设置数字低通滤波器
}
/***************************************************
Name :MPU_Init
Function :初始化MPU6050
Paramater :None
Return :
0:成功
其他:错误代码
***************************************************/
u8 MPU_Init()
{
u8 res ;
RCC->APB2ENR |= 1<<2 ; //使能PORTA时钟
GPIOA->CRH &= 0x0FFFFFFF ; //PA15设置成推挽输出
GPIOA->CRH |= 0x30000000 ;
JTAG_Set( 1 ) ; //禁止JTAG,从而PA15可以做普通IO使用,否则PA15不能做普通IO
MPU_AD0_CTRL = 0 ; //控制MPU6050的AD0脚为低电平,从机地址为:0X68
//初始化IIC总线
RCC->APB2ENR |= 1<<3 ; //先使能PB时钟
GPIOB->CRH &= 0xFFFF00FF ; //PB10/11 推挽输出
GPIOB->CRH |= 0x00003300 ;
GPIOB->ODR |= 3<<10 ; //PB10,11 输出高
MPU_Write_Byte( MPU_PWR_MGMT1_REG, 0x80 ) ; //复位MPU6050
delay_ms( 100 ) ;
MPU_Write_Byte( MPU_PWR_MGMT1_REG, 0x00 ) ; //唤醒MPU6050
MPU_Write_Byte( MPU_GYRO_CFG_REG, 3<<3 ) ; //陀螺仪传感器,±2000dps
MPU_Write_Byte( MPU_ACCEL_CFG_REG, 0<<3 ) ; //加速度传感器,±2g
MPU_Set_Rate( 50 ) ; //设置采样率50Hz
MPU_Write_Byte( MPU_INT_EN_REG, 0x00 ) ; //关闭所有中断
MPU_Write_Byte( MPU_USER_CTRL_REG, 0x00 ) ; //I2C主模式关闭
MPU_Write_Byte( MPU_FIFO_EN_REG, 0x00 ) ; //关闭FIFO
MPU_Write_Byte( MPU_INTBP_CFG_REG, 0x80 ) ; //INT引脚低电平有效
res = MPU_Read_Byte( MPU_DEVICE_ID_REG ) ;
//器件ID正确
if( res==MPU_ADDR )
{
MPU_Write_Byte( MPU_PWR_MGMT1_REG, 0x01 ) ; //设置CLKSEL,PLL X轴为参考
MPU_Write_Byte( MPU_PWR_MGMT2_REG, 0x00 ) ; //加速度与陀螺仪都工作
MPU_Set_Rate( 50 ) ; //设置采样率为50Hz
}
else
return 1 ;
return 0 ;
}
/***************************************************
Name :MPU_Write_Len
Function :IIC连续写
Paramater :
addr:器件地址
reg:寄存器地址
len:写入长度
buf:数据区
Return :
0:成功
其他:错误代码
***************************************************/
u8 MPU_Write_Len( u8 addr, u8 reg, u8 len, u8 *buf )
{
u8 i ;
MPU_IIC_Start() ;
MPU_IIC_Send_Byte( addr<<1 ) ; //发送器件地址+写命令
if( MPU_IIC_Wait_Ack() ) //等待应答
{
MPU_IIC_Stop() ;
return 1 ;
}
MPU_IIC_Send_Byte( reg ) ; //写寄存器地址
MPU_IIC_Wait_Ack() ; //等待应答
for( i=0; i
(3)创建1.c文件,输入以下代码。
#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "mpu6050.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
int main()
{
u8 t, Str[ 20 ] ;
float pitch, roll, yaw ; //欧拉角
short aacx, aacy, aacz ; //加速度传感器原始数据
short gyrox, gyroy, gyroz ; //陀螺仪原始数据
float temp ; //温度
STM32_Clock_Init( 9 ) ; //系统时钟设置
SysTick_Init( 72 ) ; //延时初始化
USART1_Init( 72, 500000 ) ; //串口初始化为500000
LCD_Init() ; //初始化LCD
MPU_Init() ; //初始化MPU6050
while( mpu_dmp_init() ) ;
POINT_COLOR = RED ; //设置字体为蓝色
while(1)
{
if( mpu_dmp_get_data( &pitch, &roll, &yaw )==0 )
{
temp = ( float )MPU_Get_Temperature()/100 ; //得到温度值
MPU_Get_Accelerometer( &aacx, &aacy, &aacz ) ; //得到加速度传感器数据
MPU_Get_Gyroscope( &gyrox, &gyroy, &gyroz ) ; //得到陀螺仪数据
//转换温度
sprintf( ( char* )Str, "Temp: %.2f C", temp ) ;
for( t=0; t<20; t++ )
{
if( Str[ t ]=='.' )
{
t += 4 ;
while( t<20 )
{
t ++ ;
Str[ t ] = ' ' ;
}
}
}
LCD_ShowString( 10, 0, Str ) ;
//自转角
sprintf( ( char* )Str, "Pitch: %.1f C", pitch ) ;
for( t=0; t<20; t++ )
{
if( Str[ t ]=='.' )
{
t += 3 ;
while( t<20 )
{
t ++ ;
Str[ t ] = ' ' ;
}
}
}
LCD_ShowString( 10, 30, Str ) ;
//章动角
sprintf( ( char* )Str, "Roll: %.1f C", roll ) ;
for( t=0; t<20; t++ )
{
if( Str[ t ]=='.' )
{
t += 3 ;
while( t<20 )
{
t ++ ;
Str[ t ] = ' ' ;
}
}
}
LCD_ShowString( 10, 60, Str ) ;
//旋转角
sprintf( ( char* )Str, "Yaw: %.1f C", yaw ) ;
for( t=0; t<20; t++ )
{
if( Str[ t ]=='.' )
{
t += 3 ;
while( t<20 )
{
t ++ ;
Str[ t ] = ' ' ;
}
}
}
LCD_ShowString( 10, 90, Str ) ;
}
}
}
注:例程使用了网上已经移植成功的DMP源码,直接调用即可。
全部0条评论
快来发表一下你的评论吧 !