赞
踩
本次使用的模块是MPU6050模块。这个模块的价格相对便宜,做一般的电子作品完全没有问题。
模块详情介绍,我的理解可能不太好,这里附上专业人解释的功能。该模块的主要特点是3轴的陀螺仪。此外,该模块还可以接入一个磁力计,即可以输出9轴的信号了。
不考虑中断的情况下,我们只需要使用4个引脚就可以对该模块进行控制。VDD GND SCL SDA
INT是中断引脚,XCL和XDA是该模块作为I2C主机的时候所使用的引脚。一般情况下,模块需要作为I2C的从机,即不需要使用该引脚。
为了更好的了解该模块,那当然是找对应的资料。下载地址如下。
https://pan.baidu.com/s/13i-tKcd5sRXHljJCJOOfXg?pwd=NICE#list/path=%2F
咱们下载好之后,可以看到如图所示的文件列表。
首先打开测试程序文件夹,里面的程序是C51单片机和arduino单片机,之后移植代码会用到。
接着介绍第二个文件,文件是一个压缩包文件,我们来解压下,可以得到下图所示的文件。
对于GY-52测试程序
部分,我们关注下stm32即可,学有余力的同学,当然也可以学习C51单片机。
只需要关注main.c
文件即可,这个文件很大,原因是他把所有的编写都写在了里面。
我们只需要关注下面打勾的文件即可。打勾的第一个文件是产品标准,打勾的第二个文件是寄存器介绍。
圈出的第一个是尺寸图,第二个则是原理图。
首先呢,我们先看看不同型号之间的引脚区别。可以看出除了7、8、23、24引脚不一致(MPU6000可以支持SPI通讯),其他都是相同的。
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。
首先我们先研读第一个手册。
可以看出MPU6050只支持I2C通讯。
特点有很多,这里圈了下比较重要的特点。注意自测试和DMP很重要的。
这个可以看出MPU6050芯片的VDD最好给3.3V,VLOGIC最好给1.8V或者3.3V。
I2C接法。
SPI接法。
I2C的写寄存器定义。
I2C的读寄存器定义。
其中BIT3-BIT7暂时不需要关注(FSYNC暂时不需要使用的),这里看下BIT0-BIT2即可。
下图看出0和7的时候,陀螺仪的输出频率为8KHZ,当取1-6的时候,陀螺仪的输出频率为1KHZ。
该寄存器用于触发陀螺仪自检并配置陀螺仪的满量程范围。
BIT5、BIT6、BIT7分别控制陀螺仪的自测试控制位。
自检回应=自检开启-自检关闭
通过自检回应可以判断芯片功能是否正常。
BIT3、BIT4主要陀螺仪的控制满量程范围。
参考资料
BIT5、BIT6、BIT7是加速度计的自测试控制位。
BIT3、BIT4主要控制加速度计的满量程范围。
BIT0、BIT1、BIT2控制高通滤波器的模式。(咱们没用到)
这个寄存器的值是固定的,所以该寄存器是只读寄存器。
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。