小兴教你做平衡小车-stm32程序开发(MPU6050显示角度)-1
文章目录
1 前言
本次使用的模块是MPU6050模块。这个模块的价格相对便宜,做一般的电子作品完全没有问题。
模块详情介绍,我的理解可能不太好,这里附上专业人解释的功能。该模块的主要特点是3轴的陀螺仪。此外,该模块还可以接入一个磁力计,即可以输出9轴的信号了。
不考虑中断的情况下,我们只需要使用4个引脚就可以对该模块进行控制。VDD GND SCL SDA
INT是中断引脚,XCL和XDA是该模块作为I2C主机的时候所使用的引脚。一般情况下,模块需要作为I2C的从机,即不需要使用该引脚。
2 资料下载
为了更好的了解该模块,那当然是找对应的资料。下载地址如下。
https://pan.baidu.com/s/13i-tKcd5sRXHljJCJOOfXg?pwd=NICE#list/path=%2F
咱们下载好之后,可以看到如图所示的文件列表。
2.1 寻找可移植的程序
首先打开测试程序文件夹,里面的程序是C51单片机和arduino单片机,之后移植代码会用到。
接着介绍第二个文件,文件是一个压缩包文件,我们来解压下,可以得到下图所示的文件。
对于GY-52测试程序
部分,我们关注下stm32即可,学有余力的同学,当然也可以学习C51单片机。
只需要关注main.c
文件即可,这个文件很大,原因是他把所有的编写都写在了里面。
2.2 重要文档
我们只需要关注下面打勾的文件即可。打勾的第一个文件是产品标准,打勾的第二个文件是寄存器介绍。
2.3 原理图文件
圈出的第一个是尺寸图,第二个则是原理图。
3 原理图分析
3.1 各系列引脚对比
首先呢,我们先看看不同型号之间的引脚区别。可以看出除了7、8、23、24引脚不一致(MPU6000可以支持SPI通讯),其他都是相同的。
3.2 MPU6050原理图分析
MPU6050原理图。左边是稳压电路,可输入的电压是3.3V-5V,经过LDO降压后得到3.3V稳定输出电压。
这时候就有个疑问了,为什么不直接接入3.3V呢。这里因为加入稳压电路,主要作用是使供电范围变宽,并不局限于3.3V供电,可以满足大部分电子爱好者的需求。
下图中MPU6050芯片,SDA和SCL引脚分别接入4.7K电阻上拉到3.3V。I2C总线做上拉处理也是常规操作。
CLKIN接入GND。
VLOGIC接入3.3V(接入一个10NF的滤波电容到GND)。
REGOUT接入一个0.1UF的滤波电容到GND。
FSYNC接入GND。
CPOUT接入一个2.2NF的滤波电容到GND。
4 手册分析
首先我们先研读第一个手册。
4.1 特点介绍
可以看出MPU6050只支持I2C通讯。
特点有很多,这里圈了下比较重要的特点。注意自测试和DMP很重要的。
这个可以看出MPU6050芯片的VDD最好给3.3V,VLOGIC最好给1.8V或者3.3V。
4.2 芯片电路内部功能图
4.3 芯片I2C与SPI引脚使用
I2C接法。
SPI接法。
4.3 I2C的写寄存器与读寄存器
I2C的写寄存器定义。
I2C的读寄存器定义。
4.4 芯片旋转图
5 寄存器手册分析
5.1 辅助的I2C供电选择寄存器
5.2 采样分频寄存器
5.3 配置寄存器
其中BIT3-BIT7暂时不需要关注(FSYNC暂时不需要使用的),这里看下BIT0-BIT2即可。
下图看出0和7的时候,陀螺仪的输出频率为8KHZ,当取1-6的时候,陀螺仪的输出频率为1KHZ。
5.4 陀螺仪配置寄存器
该寄存器用于触发陀螺仪自检并配置陀螺仪的满量程范围。
BIT5、BIT6、BIT7分别控制陀螺仪的自测试控制位。
自检回应=自检开启-自检关闭
通过自检回应可以判断芯片功能是否正常。
BIT3、BIT4主要陀螺仪的控制满量程范围。
参考资料
5.5 加速度配置寄存器
BIT5、BIT6、BIT7是加速度计的自测试控制位。
BIT3、BIT4主要控制加速度计的满量程范围。
BIT0、BIT1、BIT2控制高通滤波器的模式。(咱们没用到)
5.5 一些阈值和持续时间寄存器(这个可以不关注)
5.6 FIFO使能寄存器(这个可以不关注)
5.7 I2C主机控制寄存器(这个可以不关注)
5.8 I2C从机0-4控制寄存器
5.9 I2C主机状态寄存器(这个可以不关注)
5.10 INT脚/旁路使能配置寄存器(这个可以不关注)
5.11 中断使能寄存器(这个可以不关注)
5.12 中断状态寄存器(这个可以不关注)
5.13 加速度测量寄存器(非常重要)
5.14 温度测量寄存器(非常重要)
5.15 陀螺仪测量寄存器(非常重要)
5.16 外部传感器数据寄存器(这个可以不关注)
5.17 运动检测状态寄存器(这个可以不关注)
5.17 I2C从机0-3数据输出寄存器
5.18 I2C主机延时控制寄存器
5.19 信号通道复位寄存器
5.20 运动检测控制寄存器
5.21 用户控制寄存器
5.22 电源管理寄存器1
5.23 电源管理寄存器2
5.24 FIFO计数寄存器
5.25 FIFO读写寄存器
5.25 Who Am I寄存器
这个寄存器的值是固定的,所以该寄存器是只读寄存器。
6 得到加速度和陀螺仪、温度的初始值
main.c
文件。
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "tim.h"
#include "pwm.h"
#include "adc.h"
#include "oled.h"
#include "bmp.h"
#include "mpu6050.h"
#include "stdio.h"
int16_t AX= 0,AY=0,AZ=0;
int16_t GX= 0,GY=0,GZ=0;
int16_t ID= 0;
int16_t TEMP= 0;
int main(void)
{
//-------------------------------------------------------------------------//
RCC->APB2ENR |= (uint32_t)0x00000008;//打开GPIOB时钟
I2C_GPIO_Config();
//-------------------------------------------------------------------------//
//RCC->APB2ENR |= (uint32_t)0x00000008;//打开GPIOB时钟
//GPIOB->CRH &= (uint32_t)0xFF0FFFFF;//使用前清零
//GPIOB->CRH |= (uint32_t)0x00300000;//配置PB13为推挽输出,最大速度50MHz
//-------------------------------------------------------------------------//
RCC->APB2ENR |= (uint32_t)0x00000010;//打开GPIOC时钟
GPIOC->CRH &= (uint32_t)0xFF0FFFFF;//使用前清零
GPIOC->CRH |= (uint32_t)0x00300000;//配置PC13为推挽输出,最大速度50MHz
//-------------------------------------------------------------------------//
//RCC->APB2ENR |= (uint32_t)0x00000004;//打开GPIOA时钟
//PA4-5
//GPIOA->CRL &= (uint32_t)0xFF00FFFF;//使用前清零
//GPIOA->CRL |= (uint32_t)0x00330000;//配置PA4-5为推挽输出,最大速度50MHz
//GPIOA->BSRR = (uint32_t)0x00000010;//PA4引脚输出高电平
//GPIOA->BRR = (uint32_t)0x00000020;//PA5引脚输出低电平
//GPIOA->BSRR = (uint32_t)0x00000020;//PA5引脚输出高电平
//GPIOA->BRR = (uint32_t)0x00000010;//PA4引脚输出低电平
//PWM_Init(899,0); //(7199+1)*(0+1)/72000000hz = 0.0001s 换成频率为10khz
//TIM_SetCompare1(TIM3,450);//设置PWM占空比
//-------------------------------------------------------------------------//
Delay_Init();//延时初始化
//-------------------------------------------------------------------------//
Usart_Init(115200);//串口初始化
printf("hello world!\r\n");
//-------------------------------------------------------------------------//
OLED_Init_new(); //初始化OLED
OLED_Clear_new();
//-------------------------------------------------------------------------//
InitMPU6050();
while(1)
{
AX = MPU6050_GetData(ACCEL_XOUT_H);
AY = MPU6050_GetData(ACCEL_YOUT_H);
AZ = MPU6050_GetData(ACCEL_ZOUT_H);
GX = MPU6050_GetData(GYRO_XOUT_H);
GY = MPU6050_GetData(GYRO_YOUT_H);
GZ = MPU6050_GetData(GYRO_ZOUT_H);
ID = MPU6050_ReadID(WHO_AM_I);
TEMP = MPU6050_GetData(TEMP_OUT_H);
OLED_ShowSignedNum_new(1, 1, AX, 5);
OLED_ShowSignedNum_new(2, 1, AY, 5);
OLED_ShowSignedNum_new(3, 1, AZ, 5);
OLED_ShowSignedNum_new(1, 9,GX, 5);
OLED_ShowSignedNum_new(2, 9,GY, 5);
OLED_ShowSignedNum_new(3, 9,GZ, 5);
OLED_ShowSignedNum_new(4, 1,ID, 5);
OLED_ShowSignedNum_new(4, 9,TEMP, 5);
printf("AX=%d\r\n",AX);
printf("AY=%d\r\n",AY);
printf("AZ=%d\r\n",AZ);
printf("GX=%d\r\n",GX);
printf("GY=%d\r\n",GY);
printf("GZ=%d\r\n",GZ);
printf("ID=%d\r\n",ID);
printf("TEMP=%d\r\n",TEMP);
//GPIOB->BSRR = GPIO_Pin_6;
//GPIOB->BSRR = GPIO_Pin_7;
//GPIOB->BSRR = (uint32_t)0x00002000;//PB13引脚输出高电平
//GPIOC->BSRR = (uint32_t)0x00002000;//PC13引脚输出高电平
//Delay_ms(1800); //延时1800ms
//GPIOB->BRR = GPIO_Pin_6;
//GPIOB->BRR = GPIO_Pin_7;
//GPIOB->BRR = (uint16_t)0x2000; //PB13引脚输出低电平
//GPIOC->BRR = (uint16_t)0x2000; //PC13引脚输出低电平
//Delay_ms(1800); //延时1800ms
}
}
oled.c
文件。
#include "stm32f10x.h"
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"
//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
//new code 参考江科大oled代码部分(目前使用版本)
//---------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------//
/*引脚配置*/
#define OLED_W_SCL(x) GPIO_WriteBit(GPIOA, GPIO_Pin_6, (BitAction)(x))
#define OLED_W_SDA(x) GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)(x))
/*引脚初始化*/
void OLED_I2C_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOA, &GPIO_InitStructure);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void OLED_I2C_Start(void)
{
OLED_W_SDA(1);
OLED_W_SCL(1);
OLED_W_SDA(0);
OLED_W_SCL(0);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void OLED_I2C_Stop(void)
{
OLED_W_SDA(0);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_SDA(Byte & (0x80 >> i));
OLED_W_SCL(1);
OLED_W_SCL(0);
}
OLED_W_SCL(1); //额外的一个时钟,不处理应答信号
OLED_W_SCL(0);
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCommand(uint8_t Command)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x00); //写命令
OLED_I2C_SendByte(Command);
OLED_I2C_Stop();
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x40); //写数据
OLED_I2C_SendByte(Data);
OLED_I2C_Stop();
}
/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点,向下方向的坐标,范围:0~7
* @param X 以左上角为原点,向右方向的坐标,范围:0~127
* @retval 无
*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
OLED_WriteCommand(0xB0 | Y); //设置Y位置
OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}
/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
void OLED_Clear_new(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
/**
* @brief OLED显示一个字符
* @param Line 行位置,范围:1~4
* @param Column 列位置,范围:1~16
* @param Char 要显示的一个字符,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowChar_new(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}
/**
* @brief OLED显示字符串
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowString_new(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar_new(Line, Column + i, String[i]);
}
}
/**
* @brief OLED次方函数
* @retval 返回值等于X的Y次方
*/
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}
/**
* @brief OLED显示数字(十进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~4294967295
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar_new(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十进制,带符号数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-2147483648~2147483647
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowSignedNum_new(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
OLED_ShowChar_new(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar_new(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
OLED_ShowChar_new(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十六进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFFFFFF
* @param Length 要显示数字的长度,范围:1~8
* @retval 无
*/
void OLED_ShowHexNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i, SingleNumber;
for (i = 0; i < Length; i++)
{
SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
OLED_ShowChar_new(Line, Column + i, SingleNumber + '0');
}
else
{
OLED_ShowChar_new(Line, Column + i, SingleNumber - 10 + 'A');
}
}
}
/**
* @brief OLED显示数字(二进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void OLED_ShowBinNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar_new(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
}
}
/**
* @brief OLED初始化
* @param 无
* @retval 无
*/
void OLED_Init_new(void)
{
uint32_t i, j;
for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}
OLED_I2C_Init(); //端口初始化
OLED_WriteCommand(0xAE); //关闭显示
OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCommand(0x80);
OLED_WriteCommand(0xA8); //设置多路复用率
OLED_WriteCommand(0x3F);
OLED_WriteCommand(0xD3); //设置显示偏移
OLED_WriteCommand(0x00);
OLED_WriteCommand(0x40); //设置显示开始行
OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
OLED_WriteCommand(0x12);
OLED_WriteCommand(0x81); //设置对比度控制
OLED_WriteCommand(0xCF);
OLED_WriteCommand(0xD9); //设置预充电周期
OLED_WriteCommand(0xF1);
OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
OLED_WriteCommand(0x30);
OLED_WriteCommand(0xA4); //设置整个显示打开/关闭
OLED_WriteCommand(0xA6); //设置正常/倒转显示
OLED_WriteCommand(0x8D); //设置充电泵
OLED_WriteCommand(0x14);
OLED_WriteCommand(0xAF); //开启显示
OLED_Clear_new(); //OLED清屏
}
//---------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------//
//参考
//OLED_ShowChar_new(1, 1, 'A'); //1行1列显示字符A
//OLED_ShowString_new(1, 3, "HelloWorld!"); //1行3列显示字符串HelloWorld!
//OLED_ShowNum_new(2, 1, 12345, 5); //2行1列显示十进制数字12345,长度为5
//OLED_ShowSignedNum_new(2, 7, -66, 2); //2行7列显示有符号十进制数字-66,长度为2
//OLED_ShowHexNum_new(3, 1, 0xAA55, 4); //3行1列显示十六进制数字0xA5A5,长度为4
//OLED_ShowBinNum_new(4, 1, 0xAA55, 16); //4行1列显示二进制数字0xA5A5,长度为16
//C语言无法直接写出二进制数字,故需要用十六进制表示
oled.h
文件。
#ifndef __OLED_H
#define __OLED_H
#include "stm32f10x.h"
//new code 参考江科大oled代码部分
//---------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------//
void OLED_Init_new(void);
void OLED_Clear_new(void);
void OLED_ShowChar_new(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString_new(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum_new(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum_new(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
//---------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------//
#endif
oledfont.h
文件。
#ifndef __OLEDFONT_H
#define __OLEDFONT_H
#include "stm32f10x.h"
/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][16]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,
0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,
0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,
0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,
0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,
0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,
0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,
0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,
0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,
0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,
0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,
0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,
0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,
0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,
0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,
0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,
0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,
0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,
0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,
0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,
0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,
0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,
0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,
0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,
0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,
0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,
0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,
0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,
0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,
0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,
0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,
0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,
0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,
0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,
0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,
0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,
0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,
0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,
0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,
0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,
0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,
0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,
0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,
0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,
0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,
0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,
0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,
0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,
0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,
0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,
0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,
0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,
0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,
0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,
0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,
0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,
0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,
0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,
0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,
0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,
0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,
0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};
#endif
mpu6050.c
文件。
#include "stm32f10x.h"
#include "math.h"
#include "stdbool.h"
#include "delay.h"
#include "stdio.h"
#include "mpu6050.h"
//PB6 SCL
//PB7 SDA
#define SCL_H GPIOB->BSRR = GPIO_Pin_6
#define SCL_L GPIOB->BRR = GPIO_Pin_6
#define SDA_H GPIOB->BSRR = GPIO_Pin_7
#define SDA_L GPIOB->BRR = GPIO_Pin_7
#define SCL_read GPIOB->IDR & GPIO_Pin_6
#define SDA_read GPIOB->IDR & GPIO_Pin_7
void I2C_delay(void)
{
u8 i=5; //这里可以优化速度,经测试最低到5还能写入
while(i)
{
i--;
}
}
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void I2C_Start(void) //I2C开始波形
{
SDA_H;
SCL_H;
I2C_delay();
I2C_delay();
SDA_L;
I2C_delay();
SCL_L;
I2C_delay();
}
void I2C_Stop(void) //I2C结束波形
{
SDA_L;
SCL_L;
I2C_delay();
SCL_H;
I2C_delay();
SDA_H;
I2C_delay();
}
//void I2C_Ack(void) //主机(单片机)发送ACK波形
//{
// SCL_L;
// SDA_L;
// I2C_delay();
//
// SDA_L;
// I2C_delay();
//
// SCL_H;
// I2C_delay();
// I2C_delay();
//
// SCL_L;
// I2C_delay();
//
// SCL_L;
// SDA_L;
// I2C_delay();
//}
//void I2C_NoAck(void) //主机(单片机)发送NACK波形
//{
// SCL_L;
// SDA_L;
// I2C_delay();
//
// SDA_H;
// I2C_delay();
//
// SCL_H;
// I2C_delay();
// I2C_delay();
//
// SCL_L;
// I2C_delay();
//
// SCL_L;
// SDA_L;
// I2C_delay();
//}
void I2C_WaitAck(void)
{
SCL_L;
SDA_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if((SDA_read) == 1)
{
I2C_delay();
SCL_L;
I2C_delay();
SCL_L;
SDA_L;
I2C_delay();
}
else
{
I2C_delay();
SCL_L;
I2C_delay();
SCL_L;
SDA_L;
I2C_delay();
}
}
void I2C_SendByte(uint8_t SendByte)
{
uint8_t i=8;
while(i--)
{
SCL_L;
SDA_L;
I2C_delay();
if(SendByte&0x80)
SDA_H;
else
SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
I2C_delay();
SCL_L;
I2C_delay();
SCL_L;
SDA_L;
I2C_delay();
SendByte <<= 1;
}
}
unsigned char I2C_ReadByte(void)
{
uint8_t i=8;
uint8_t ReceiveByte=0;
while(i--)
{
ReceiveByte<<=1;
SCL_L;
SDA_L;
I2C_delay();
SDA_H;
I2C_delay();
SCL_H;
I2C_delay();
if(SDA_read)
{
ReceiveByte|=0x01;
}
I2C_delay();
SCL_L;
I2C_delay();
SCL_L;
SDA_L;
I2C_delay();
}
return ReceiveByte;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_WaitAck();
I2C_SendByte(REG_Address); //内部寄存器地址
I2C_WaitAck();
I2C_SendByte(REG_data); //内部寄存器数据
I2C_WaitAck();
I2C_Stop(); //发送停止信号
Delay_ms(2);
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
uint8_t Single_ReadI2C(uint8_t REG_Address)
{
uint8_t REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_WaitAck();
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2C_WaitAck();
I2C_Stop(); //停止信号
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号
I2C_WaitAck();
REG_data=I2C_ReadByte(); //读出寄存器数据
I2C_WaitAck(); //接收应答信号
I2C_Stop(); //停止信号
Delay_ms(2);
return REG_data;
}
//**************************************
//初始化MPU6050
//**************************************
void InitMPU6050(void)
{
Single_WriteI2C(PWR_MGMT_1, 0x00); //0x6B 解除睡眠并且选择内部8M时钟
Single_WriteI2C(PWR_MGMT_2, 0x00); //0x6C
Single_WriteI2C(SMPLRT_DIV, 0x07); //0x19
Single_WriteI2C(CONFIG, 0x06); //0x1A
Single_WriteI2C(GYRO_CONFIG, 0x18); //0x1B
Single_WriteI2C(ACCEL_CONFIG, 0x18);//0x1C
}
//**************************************
//合成数据
//**************************************
int16_t MPU6050_GetData(uint8_t REG_Address)
{
uint8_t H,L;
H=Single_ReadI2C(REG_Address);
L=Single_ReadI2C(REG_Address+1);
return (H<<8)+L; //合成数据
}
//**************************************
//合成数据
//**************************************
uint8_t MPU6050_ReadID(uint8_t REG_Address)
{
return Single_ReadI2C(REG_Address);
}
mpu6050.h
文件。
#ifndef ___MPU6050_H
#define ___MPU6050_H
#include "stm32f10x.h"
#define uchar unsigned char
#define uint unsigned char
//****************************************
// 定义MPU6050内部地址
//****************************************
#define SMPLRT_DIV 0x19 //陀螺仪采样率,典型值:0x07(125Hz)
#define CONFIG 0x1A //低通滤波频率,典型值:0x06(5Hz)
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
#define ACCEL_CONFIG 0x1C //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C
#define ACCEL_YOUT_H 0x3D
#define ACCEL_YOUT_L 0x3E
#define ACCEL_ZOUT_H 0x3F
#define ACCEL_ZOUT_L 0x40
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47
#define GYRO_ZOUT_L 0x48
#define PWR_MGMT_1 0x6B //电源管理,典型值:0x00(正常启用)
#define PWR_MGMT_2 0x6C
#define WHO_AM_I 0x75 //IIC地址寄存器(默认数值0x68,只读)
#define SlaveAddress 0xD0 //IIC写入时的地址字节数据,+1为读取
void I2C_GPIO_Config(void);
void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data);
uint8_t Single_ReadI2C(uint8_t REG_Address);
void InitMPU6050(void);
int16_t MPU6050_GetData(uint8_t REG_Address);
uint8_t MPU6050_ReadID(uint8_t REG_Address);
#endif
作者:爱发明的小兴