赞
踩
目录
要想获取Mpu6050陀螺仪和加速度那就需要了解一下Mpu6050。Mpu6050使用的是I2C通讯
先了解一下
SCL高电平期间,SDA从高电平切换到低电平
SCL高电平期间,SDA从低电平切换到高电平
下来让我们用代码实现一下I2C通讯:
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- void MyI2C_W_SCL(uint8_t Bitvalue)//SCL电平,可以给这个函数0或1
- { //设置引脚引脚后续可以改
- GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)Bitvalue);//bitactiion就是一个枚举类型的变量,给1或0就可以拉低或拉高电平
- Delay_us(10);//延时10um
- }
- void MyI2C_W_SDA(uint8_t Bitvalue)//SAD电平,可以给这个函数0或1
- { //设置引脚引脚后续可以改
- GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)Bitvalue);//bitactiion就是一个枚举类型的变量,表示这个位是高电平还是低电平
- Delay_us(10);//延时10um
- }
- //因为stm32读和写不是一个寄存器
- uint8_t MyI2C_R_SDA(void)//读SDA
- {
- uint8_t Bitvalue;
- Bitvalue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);/*函数 GPIO_ReadInputDataBit 读的是 GPIOx_IDR
- 读的是当 IO 口设置为输入状态时候的 IO 口电平状态值。*/
- Delay_us(10);//延时
- return Bitvalue;//返回值
- }
-
-
-
- void MyI2C_inite(void)//初始化引脚
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//因为mpu6050接的是PB10和11脚
-
- GPIO_InitTypeDef GPIO_InitStructure;//结构体
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;//设为开漏输出 可输入输出
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;//设置引脚
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设置频率
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_11);
-
- }
-
- void MyI2C_start(void)
- {
- MyI2C_W_SDA(1);//先给这两条线的电平先释放
- MyI2C_W_SCL(1);
-
- MyI2C_W_SDA(0);//先拉底SDA再拉低SCL
- MyI2C_W_SCL(0);
- }
- void MyI2C_stop(void)
- {
-
- MyI2C_W_SDA(0);//先拉低SDA确保他处于低电平
- MyI2C_W_SCL(1);//然后拉高SCL再拉高SDA终止通讯
- MyI2C_W_SDA(1);
-
-
- }
-
-
- void MyI2C_SendByte(uint8_t Byte)//发送字节参数是八位的字节
- {
- uint8_t i;//定义变量
- for(i=0;i<8;i++)//进入循环
- {
- MyI2C_W_SDA(Byte & (0x80 >> i));//取最高位向右移,与取最高位依次取出字节
- MyI2C_W_SCL(1);//释放SCL拉低SCL给它一个脉冲继续取下一个数据
- MyI2C_W_SCL(0);
- }
-
- }
- uint8_t MyI2C_ReceiveByte(void)//接收字节
- {
- uint8_t i,Byte= 0x00;
- MyI2C_W_SDA(1);//先释放SDA
- for(i=0;i<8;i++)
- {
- MyI2C_W_SCL(1);//SCL高电平是读SCL低电平是写
- if (MyI2C_R_SDA() == 1){Byte|=(0x80>>i);}
- MyI2C_W_SCL(0);
- }
- return Byte;
-
- }
-
- void MyI2C_SendAck(uint8_t AckBit)//发送应答
- {
-
- MyI2C_W_SDA(AckBit);//取最高位
- MyI2C_W_SCL(1);
- MyI2C_W_SCL(0);//进入下一个时序单位
-
-
- }
- uint8_t MyI2C_ReceiveAck(void)
- {
- uint8_t AckBit;
- MyI2C_W_SDA(1);
- MyI2C_W_SCL(1);
- AckBit = MyI2C_R_SDA();//接收SDA的信号
- MyI2C_W_SCL(0);//进入下一个时序单位
-
- return AckBit;
-
- }

- #ifndef __MYI2C_H
- #define __MYI2C_H
-
- void MyI2C_inite(void);
- void MyI2C_start(void);
- void MyI2C_stop(void);
- void MyI2C_SendByte(uint8_t Byte);
- uint8_t MyI2C_ReceiveByte(void);
- void MyI2C_SendAck(uint8_t AckBit);
- uint8_t MyI2C_ReceiveAck(void);
- void Mpu6050_GetData(int16_t*AccX,int16_t*AccY,int16_t*AccZ,int16_t*GyroX,int16_t*GyroY,int16_t*GyroZ);
- #endif
写好了i2c的通讯就可以来写mpu6050的代码
- #include "stm32f10x.h"
- #include "Mpu6050Reg.h"
- #include "myi2c.h"
- #include "Delay.h"
-
- #define MPU6050_ADDRESS 0XD0
-
- void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)//写入地址和写入数据
- {
- MyI2C_start();//打开I2C通讯
- MyI2C_SendByte(MPU6050_ADDRESS);//从机地址+读写位,0是写,1读
- MyI2C_ReceiveAck();//返回一个应答位,接收
- MyI2C_SendByte(RegAddress);//发送指定寄存器
- MyI2C_ReceiveAck();//返回一个应答位,接收
- MyI2C_SendByte(Data);//给寄存器写入数据
- MyI2C_ReceiveAck();//返回一个应答位,接收
- MyI2C_stop();//停止通讯
- }
-
- uint8_t MPU6050_ReadReg(uint8_t RegAddress)//读寄存器地址
- {
- uint8_t Data;
-
- MyI2C_start();//打开I2C通讯
- MyI2C_SendByte(MPU6050_ADDRESS);//从机地址
- MyI2C_ReceiveAck();//返回一个应答位,接收回应
- MyI2C_SendByte(RegAddress);//发送指定寄存器
- MyI2C_ReceiveAck();//返回一个应答位,接收回应
-
- MyI2C_start();//打开I2C通讯
- MyI2C_SendByte(MPU6050_ADDRESS | 0x01);//从机地址+读写位,0是写,1读
- MyI2C_ReceiveAck();//返回一个应答位,接收回应
- Data = MyI2C_ReceiveByte();//读取信息存储到data
- MyI2C_SendAck(1);//1不给从机应答,0给从机应答.
- MyI2C_stop();//停止通讯
-
- return Data;//返回值
- }
-
- void Mpu6050_Init(void)//mpu6050初始化
- {
- MyI2C_inite();//初始化I2C通讯
- MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//陀螺仪时钟
- MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);//六个轴均不待机
- MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//采样率分频 10分频 值越小越快
- MPU6050_WriteReg(MPU6050_CONFIG, 0x06);//配置寄存器
- MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//陀螺仪配置寄存器
- MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//加速度计配置寄存器
- }
-
- uint8_t Mpu6050_GetID(void)//获取mpu6050ID号
- {
- return MPU6050_ReadReg(MPU6050_WHO_AM_I);
- }
-
- void Mpu6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, //陀螺仪三个轴 加速度计三个轴
- int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
- {
- uint8_t DataH, DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);//读取加速度X,Y,Z轴高八位和低八位
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
- *AccX = (DataH << 8) | DataL;//获取16位存入指针
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
- *AccY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
- DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
- *AccZ = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);//读取陀螺仪X,Y,Z轴高八位和低八位
- DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
- *GyroX = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
- DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
- *GyroY = (DataH << 8) | DataL;
-
- DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
- DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
- *GyroZ = (DataH << 8) | DataL;
- }

- #ifndef _Mpu6050_H
- #define _Mpu6050_H
-
- void Mpu6050_WriteReg(uint8_t RegAddress,uint8_t Data); //指定地址写寄存器
- uint8_t Mpu6050_ReadReg(uint8_t RegAddress);
- uint8_t Mpu6050_GetID(void);
- void Mpu6050_Init(void);
- void Mpu6050_GetData(int16_t*AccX,int16_t*AccY,int16_t*AccZ,int16_t*GyroX,int16_t*GyroY,int16_t*GyroZ);
-
- #endif
还需要Mpu6050的寄存器地址
- #ifndef _Mpu6050Reg_H//宏定义mpu6050的寄存器
- #define _Mpu6050Reg_H
-
- #define MPU6050_SMPLRT_DIV 0x19
- #define MPU6050_CONFIG 0x1A
- #define MPU6050_GYRO_CONFIG 0x1B
- #define MPU6050_ACCEL_CONFIG 0x1C
-
- #define MPU6050_ACCEL_XOUT_H 0x3B
- #define MPU6050_ACCEL_XOUT_L 0x3C
- #define MPU6050_ACCEL_YOUT_H 0x3D
- #define MPU6050_ACCEL_YOUT_L 0x3E
- #define MPU6050_ACCEL_ZOUT_H 0x3F
- #define MPU6050_ACCEL_ZOUT_L 0x40
- #define MPU6050_TEMP_OUT_H 0x41
- #define MPU6050_TEMP_OUT_L 0x42
- #define MPU6050_GYRO_XOUT_H 0x43
- #define MPU6050_GYRO_XOUT_L 0x44
- #define MPU6050_GYRO_YOUT_H 0x45
- #define MPU6050_GYRO_YOUT_L 0x46
- #define MPU6050_GYRO_ZOUT_H 0x47
- #define MPU6050_GYRO_ZOUT_L 0x48
-
- #define MPU6050_PWR_MGMT_1 0x6B
- #define MPU6050_PWR_MGMT_2 0x6C
- #define MPU6050_WHO_AM_I 0x75
-
- #endif

实现把Mpu6050数据显示到oled屏幕上
- #include "stm32f10x.h"
- #include "Delay.h"
- #include "OLED.h"
- #include "Mpu6050.h"
-
- uint8_t ID;//存放ID号的变量
- int16_t AX, AY, AZ, GX, GY, GZ;//存放加速度计和陀螺仪的值
-
- int main(void)
- {
- OLED_Init();//初始化OLED
- Mpu6050_Init();//初始化mpu6050
- //显示内容mpu6050的ID号
- OLED_ShowString(1, 1, "ID:");
- ID = Mpu6050_GetID();//获取ID号
- OLED_ShowHexNum(1, 4, ID, 2);
-
- while (1)
- {
- Mpu6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);//获取AX到GZ的值
- //显示加速度计和陀螺仪到OLED
- OLED_ShowSignedNum(2, 1, AX, 5);
- OLED_ShowSignedNum(3, 1, AY, 5);
- OLED_ShowSignedNum(4, 1, AZ, 5);
- OLED_ShowSignedNum(2, 8, GX, 5);
- OLED_ShowSignedNum(3, 8, GY, 5);
- OLED_ShowSignedNum(4, 8, GZ, 5);
- }
- }

参考视视频:
【STM32入门教程-2023持续更新中-哔哩哔哩】 https://b23.tv/mVJHA3h
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。