900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【stm32】stm32学习笔记(江科大)-详解stm32获取Mpu6050陀螺仪和加速度

【stm32】stm32学习笔记(江科大)-详解stm32获取Mpu6050陀螺仪和加速度

时间:2019-12-30 10:42:30

相关推荐

【stm32】stm32学习笔记(江科大)-详解stm32获取Mpu6050陀螺仪和加速度

目录

I2C

起始条件:

终止条件:

发送一个字节

接收一个字节

接收发送应答

代码

I2C

I2C.C

I2C.h

Mpu6050

Mpu6050.c

Mpu6050.h

Mpu6050Reg.h

main.c

结果

要想获取Mpu6050陀螺仪和加速度那就需要了解一下Mpu6050。Mpu6050使用的是I2C通讯

先了解一下

I2C

起始条件:

SCL高电平期间,SDA从高电平切换到低电平

终止条件:

SCL高电平期间,SDA从低电平切换到高电平

发送一个字节

接收一个字节

接收发送应答

代码

下来让我们用代码实现一下I2C通讯:

I2C

I2C.C

#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再拉低SCLMyI2C_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);//先释放SDAfor(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;}

I2C.h

#ifndef __MYI2C_H#define __MYI2C_Hvoid 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的代码

Mpu6050

Mpu6050.c

#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();//读取信息存储到dataMyI2C_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;}

Mpu6050.h

#ifndef _Mpu6050_H#define _Mpu6050_Hvoid 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的寄存器地址

Mpu6050Reg.h

#ifndef _Mpu6050Reg_H//宏定义mpu6050的寄存器#define _Mpu6050Reg_H#defineMPU6050_SMPLRT_DIV0x19#defineMPU6050_CONFIG0x1A#defineMPU6050_GYRO_CONFIG0x1B#defineMPU6050_ACCEL_CONFIG0x1C#defineMPU6050_ACCEL_XOUT_H0x3B#defineMPU6050_ACCEL_XOUT_L0x3C#defineMPU6050_ACCEL_YOUT_H0x3D#defineMPU6050_ACCEL_YOUT_L0x3E#defineMPU6050_ACCEL_ZOUT_H0x3F#defineMPU6050_ACCEL_ZOUT_L0x40#defineMPU6050_TEMP_OUT_H0x41#defineMPU6050_TEMP_OUT_L0x42#defineMPU6050_GYRO_XOUT_H0x43#defineMPU6050_GYRO_XOUT_L0x44#defineMPU6050_GYRO_YOUT_H0x45#defineMPU6050_GYRO_YOUT_L0x46#defineMPU6050_GYRO_ZOUT_H0x47#defineMPU6050_GYRO_ZOUT_L0x48#defineMPU6050_PWR_MGMT_10x6B#defineMPU6050_PWR_MGMT_20x6C#defineMPU6050_WHO_AM_I0x75#endif

实现把Mpu6050数据显示到oled屏幕上

main.c

#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();//初始化OLEDMpu6050_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的值//显示加速度计和陀螺仪到OLEDOLED_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入门教程-持续更新中-哔哩哔哩】 https://b23.tv/mVJHA3h

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。