有关于I2C的知识看这篇文章:
【记录】嵌入式经典通信I2C理解
有关于MPU6050的基础知识和手册去看这篇文章:
【记录】MPU6050原理快速入门(附手册)
此篇记录代码编写过程:
直接看汇总: 代码汇总
一、完成CubeMX的配置。
首先分析自身需求:MPU6050需要用到I2C或者是模拟I2C,因为stm32自身具备I2C,故选择使用物理I2C。此外,通过串口来将数据传给电脑,实现在电脑上查看吗,因此需要配置串口,并完成串口的重定向。
使用的控制板是正点原子的探索者,主控芯片是STM32F407ZGT6。
CubeMX的配置请参考其它文章,这里只给出I2C的配置图和最终的引脚配置图。
I2C的配置如图:
最终的引脚配置如图:
二、完成实物接线。
只需要四个引脚,其名称和对应接线为:VCC接3~5V,GND接GND,SDA接PB6,SCL接PB7(这里PB6和PB7根据自己的板子配置)。
三、阅读MPU6050的数据手册,查阅相关寄存器地址。
首先,要知道MPU6050的地址,可以通过数据手册也可以通过代码来查阅。接下来用代码进行查看。
#include <stdio.h>// 包含标准输入输出头文件
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
return ch;
}
int main()
{
for(uint8_t i=0;i<255;i++)
{
if(HAL_I2C_IsDeviceReady(&hi2c,i,1,1000)==HAL_OK)
{
printf("%d\n",i);
break;
}
}
}
通过代码或查阅手册知道MPU6050的设备地址为0xD0。进行宏定义方便使用。
#define mpu_addr 0xD0
为了方便对MPU6050进行读写操作,编写函数。因为MPU6050的使用需要访问寄存器,因此选择能进行读写设备地址和寄存器的地址的语句。
//HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);//只有设备地址
//HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);//有设备地址和寄存器地址
通过上面封装函数的对比,可以完成读写函数的编写。
void mpu_w(uint8_t addr,uint8_t data)//写
{
HAL_I2C_Mem_Write(&hi2c1, mpu_addr, addr, 1, &data, 1, HAL_MAX_DELAY);
}
uint8_t mpu_r(uint8_t addr)//读
{
uint8_t data;
HAL_I2C_Mem_Read(&hi2c1, mpu_addr,addr, 1, &data, 1, HAL_MAX_DELAY);
return data;
}
其次,完成MPU6050的初始化函数。
void mpu_begin(void)//初始化
{
if(mpu_r(0x75)==0x68)//检测
{
mpu_w(0x1B,0x18);//改角速度速率
mpu_w(0x1C,0x10);//改加速度
mpu_w(0x6B,0x01);//关睡眠,改时钟到G
}
}
最后,完成各个函数的编写,重力感应,温度,角速度。文章来源:https://www.toymoban.com/news/detail-598202.html
文章来源地址https://www.toymoban.com/news/detail-598202.html
//X,Y,Z读数据时需要组合
int16_t mpu_acc_x(void) //x重力感应
{
int16_t x=0;
x=mpu_r(0x3B)<<8;
x=x|mpu_r(0x3C);
return x;
}
int16_t mpu_acc_y(void) //y重力感应
{
int16_t y=0;
y=mpu_r(0x3D)<<8;
y=y|mpu_r(0x3E);
return y;
}
int16_t mpu_acc_z(void) //z重力感应
{
int16_t z=0;
z=mpu_r(0x3F)<<8;
z=z|mpu_r(0x40);
return z;
}
int16_t mpu_temp(void) //温度
{
int16_t t=0;
t=mpu_r(0x41)<<8;
t=t|mpu_r(0x42);
return t;
}
int16_t mpu_gy_x(void) //x角速度
{
int16_t x=0;
x=mpu_r(0x43)<<8;
x=x|mpu_r(0x44);
return x;
}
int16_t mpu_gy_y(void) //y角速度
{
int16_t y=0;
y=mpu_r(0x45)<<8;
y=y|mpu_r(0x46);
return y;
}
int16_t mpu_gy_z(void) //z角速度
{
int16_t z=0;
z=mpu_r(0x47)<<8;
z=z|mpu_r(0x48);
return z;
}
代码汇总:
/* USER CODE BEGIN 0 */
#define mpu_addr 0xD0
//完成串口重定向
#include <stdio.h>// 包含标准输入输出头文件
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
return ch;
}
//完成MPU6050相关函数编写
void mpu_w(uint8_t addr,uint8_t data)//写
{
HAL_I2C_Mem_Write(&hi2c1, mpu_addr, addr, 1, &data, 1, HAL_MAX_DELAY);
}
uint8_t mpu_r(uint8_t addr)//读
{
uint8_t data;
HAL_I2C_Mem_Read(&hi2c1, mpu_addr,addr, 1, &data, 1, HAL_MAX_DELAY);
return data;
}
void mpu_begin(void)//初始化
{
if(mpu_r(0x75)==0x68)//检测
{
mpu_w(0x1B,0x18);//改角速度速率
mpu_w(0x1C,0x10);//改加速度
mpu_w(0x6B,0x01);//关睡眠,改时钟到G
}
}
//X,Y,Z读数据时需要组合
int16_t mpu_acc_x(void) //x重力感应
{
int16_t x=0;
x=mpu_r(0x3B)<<8;
x=x|mpu_r(0x3C);
return x;
}
int16_t mpu_acc_y(void) //y重力感应
{
int16_t y=0;
y=mpu_r(0x3D)<<8;
y=y|mpu_r(0x3E);
return y;
}
int16_t mpu_acc_z(void) //z重力感应
{
int16_t z=0;
z=mpu_r(0x3F)<<8;
z=z|mpu_r(0x40);
return z;
}
int16_t mpu_temp(void) //温度
{
int16_t t=0;
t=mpu_r(0x41)<<8;
t=t|mpu_r(0x42);
return t;
}
int16_t mpu_gy_x(void) //x角速度
{
int16_t x=0;
x=mpu_r(0x43)<<8;
x=x|mpu_r(0x44);
return x;
}
int16_t mpu_gy_y(void) //y角速度
{
int16_t y=0;
y=mpu_r(0x45)<<8;
y=y|mpu_r(0x46);
return y;
}
int16_t mpu_gy_z(void) //z角速度
{
int16_t z=0;
z=mpu_r(0x47)<<8;
z=z|mpu_r(0x48);
return z;
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
mpu_begin();
//读取数据通过串口传给电脑
int acc_x,acc_y,acc_z,temp,gy_x,gy_y,gy_z;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
acc_x=mpu_acc_x();
acc_y=mpu_acc_y();
acc_z=mpu_acc_z();
temp=mpu_temp();
gy_x=mpu_gy_x();
gy_y=mpu_gy_y();
gy_z=mpu_gy_z();
printf("%d,%d,%d,%d,%d,%d\n",acc_x,acc_y,acc_z,temp,gy_x,gy_y,gy_z);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
到了这里,关于【记录】自己动手使用HAL库对MPU6050进行编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!