目录
I2C
起始条件:
终止条件:
发送一个字节
接收一个字节
接收发送应答
代码
I2C
I2C.C
I2C.h
Mpu6050
Mpu6050.c
Mpu6050.h
Mpu6050Reg.h
main.c
结果
文章来源地址https://www.toymoban.com/news/detail-574360.html
要想获取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再拉低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;
}
I2C.h
#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的代码
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();//读取信息存储到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;
}
Mpu6050.h
#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的寄存器地址
Mpu6050Reg.h
#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屏幕上
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();//初始化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
文章来源:https://www.toymoban.com/news/detail-574360.html
到了这里,关于【stm32】stm32学习笔记(江科大)-详解stm32获取Mpu6050陀螺仪和加速度的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!