目录
一、硬件设计
1、模块说明
2、电气原理图
二、程序设计
1、工程创建
2、程序设计
(1)main程序
(2)IIC初始化
(3)串口1配置
(4)MPU6050初始化
(5)MPU6050角度状态获取
三、测试
四、工程下载连接
STM32芯片型号:STM32C8T6
陀螺仪:MPU6050,使用I²C和CPU通讯,通讯引脚PB8、PB9
串口1对外通讯:引脚PA9、PA10
串口3接蓝牙通讯:引脚PB10、PB11
硬件设备
创建程序工程对应型号的单片机,在工程中添加下列文件夹
在工程根目录下添加下来文件夹,文件夹中添加相应的配置文件。
模板工程创建可以参加教程:STM32笔记1-库函数模板工程创建_Big_潘大师的博客-CSDN博客_site:csdn.net
这里提供一个创建好的模板STM32F103C8(LED灯闪烁运行指示)
https://download.csdn.net/download/panjinliang066333/86753318
User:用户程序,运行Main程序
App:各个功能块程序
Public:公用的程序
Startup:放置启动文件
StdPeriph_Driver:存储系统库文件
MPU DMP:陀螺仪库文件
#include "system.h"
#include "SysTick.h"
#include "SysDelay.h"
#include "led.h"
#include "i2c.h"
#include "mpu6050.h"
#include "usart.h"
int main()
{
u8 count=0;
u16 i=0;
SystemInit(); //系统初始化
SysDelay_Init(72); //自定义延时函数初始化
LED_Init();
USART1_Config(); //串口1初始化
USART3_Config(); //串口3初始化-接蓝牙
i2cInit(); //IIC初始化
SysDelay_ms(10); //10毫秒延时
MPU6050_Init(); //MPU6050 DMP陀螺仪初始化
while(1)
{
//LED闪烁
if(i%500==0)
{
led1=!led1;
}
//2秒执行一次
if(i%2000==0)
{
count++;
printf("count:%d \r\n",count);
printf("Pitch: %.2f ,Roll: %.2f,Yaw: %.2f \r\n",Pitch,Roll,Yaw); //Pitch,Roll,Yaw数据串口传递
}
/*获取MPU6050角度状态*/
//在串口数据发送之后执行
MPU6050_Pose(); //Pitch翻滚,Roll俯仰,Yaw偏航
SysDelay_ms(1); //1毫秒延时
i++;
}
}
void i2cInit(void)
{
GPIO_InitTypeDef gpio;
//ÒѸü¸Ä
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
gpio.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
gpio.GPIO_Speed = GPIO_Speed_2MHz;
gpio.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &gpio);
}
void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
/* config USART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
/* USART1 GPIO config */
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* USART1 mode config */
USART_InitStructure.USART_BaudRate = 115200;
//USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void MPU6050_Init(void)
{
int result=0;
//IIC_Init();
result=mpu_init();
if(!result)
{
PrintChar("mpu initialization complete......\n "); //mpu initialization complete
if(!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) //mpu_set_sensor
PrintChar("mpu_set_sensor complete ......\n");
else
PrintChar("mpu_set_sensor come across error ......\n");
if(!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) //mpu_configure_fifo
PrintChar("mpu_configure_fifo complete ......\n");
else
PrintChar("mpu_configure_fifo come across error ......\n");
if(!mpu_set_sample_rate(DEFAULT_MPU_HZ)) //mpu_set_sample_rate
PrintChar("mpu_set_sample_rate complete ......\n");
else
PrintChar("mpu_set_sample_rate error ......\n");
if(!dmp_load_motion_driver_firmware()) //dmp_load_motion_driver_firmvare
PrintChar("dmp_load_motion_driver_firmware complete ......\n");
else
PrintChar("dmp_load_motion_driver_firmware come across error ......\n");
if(!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation))) //dmp_set_orientation
PrintChar("dmp_set_orientation complete ......\n");
else
PrintChar("dmp_set_orientation come across error ......\n");
if(!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
DMP_FEATURE_GYRO_CAL)) //dmp_enable_feature
PrintChar("dmp_enable_feature complete ......\n");
else
PrintChar("dmp_enable_feature come across error ......\n");
if(!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) //dmp_set_fifo_rate
PrintChar("dmp_set_fifo_rate complete ......\n");
else
PrintChar("dmp_set_fifo_rate come across error ......\n");
run_self_test(); //自检
if(!mpu_set_dmp_state(1))
PrintChar("mpu_set_dmp_state complete ......\n");
else
PrintChar("mpu_set_dmp_state come across error ......\n");
}
}
void MPU6050_Pose(void)
{
dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more);
/* Gyro and accel data are written to the FIFO by the DMP in chip frame and hardware units.
* This behavior is convenient because it keeps the gyro and accel outputs of dmp_read_fifo and mpu_read_fifo consistent.
**/
/*if (sensors & INV_XYZ_GYRO )
send_packet(PACKET_TYPE_GYRO, gyro);
if (sensors & INV_XYZ_ACCEL)
send_packet(PACKET_TYPE_ACCEL, accel); */
/* Unlike gyro and accel, quaternions are written to the FIFO in the body frame, q30.
* The orientation is set by the scalar passed to dmp_set_orientation during initialization.
**/
if(sensors & INV_WXYZ_QUAT )
{
q0 = quat[0] / q30;
q1 = quat[1] / q30;
q2 = quat[2] / q30;
q3 = quat[3] / q30;
//Pitch翻滚,Roll俯仰,Yaw偏航
Pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
Roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)*57.3; // roll
Yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
}
}
打开串口调试助手,可以接收到单片机发送过来的数据,转动单片机板子可以发现YAW(偏航)数据发生变化。
https://download.csdn.net/download/panjinliang066333/86753201