配置I2C![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/66ee2d8167ace9be7daf8414384f54f7.png)
配置串口
其余按默认
导出
配置时钟
1.printf重定义
//printf重定向
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFF);
return ch;
}
2.六轴i2c协议
2.1 检查MCU与MPU6050通信是否成功
// 1.检查MCU与MPU6050通信是否成功
//初始化MPU6050
int MPU6050_CheckCommunication()
{
uint8_t data;
HAL_StatusTypeDef status;
// 发送读取WHO_AM_I命令 0xD0
status = HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDRESS, 0x75, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
if (status != HAL_OK)
{
return -1;
}
// 检查WHO_AM_I寄存器的值是否等于0x68
if (data != 0x68)
{
return -1;
}
return 0;
}
2.2设置MPU6050为复位状态
// 2.设置MPU6050为复位状态
void MPU6050_Reset()
{
uint8_t data = 0x80; //1000 0000
//写入复位命令到PWR_MGMT_1寄存器 0xD0 0x6B 0x80
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
//延时等待复位完成 100毫秒
HAL_Delay(MPU6050_RESET_DELAY);
}
2.3唤醒MPU6050并选择PLL为时钟源
// 3.唤醒MPU6050并选择PLL为时钟源
void MPU6050_WakeUp()
{
uint8_t data = 0x01;//0000 0001
//写入唤醒命令到PWR_MGMT_1寄存器 0xD0 0X6B 0x01
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
2.4配置6轴数据输出
// 4.配置6轴数据输出
void MPU6050_ConfigureDataOutput()
{
uint8_t data = 0x00;//0000 0000
// 配置CONFIG寄存器,使能加速度计和陀螺仪的所有轴
// 0xD0 0x1A 0x00
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
2.5禁止所有中断
// 5.禁止所有中断
void MPU6050_DisableInterrupts()
{
uint8_t data = 0x00; //0000 0000
// 写入0到INT_ENABLE寄存器,禁止所有中断
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, 0x37, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
2.6设置内部采样频率和低通滤波器
void MPU6050_SetSamplingRateAndFilter()
{
uint8_t data = 0x06; //0000 0110
// 写入6到CONFIG寄存器,设置采样频率为1kHz,低通滤波器带宽为5Hz
// 0xD0 0x1A
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
2.7设置陀螺仪和加速度计的满量程范围
// 7.设置陀螺仪和加速度计的满量程范围
void MPU6050_SetFullScaleRange()
{
uint8_t data = 0x18;
// 写入0到GYRO_CONFIG寄存器,设置陀螺仪的满量程范围为±2000°/s
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_GYRO_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
uint8_t daty = 0x00;
// 写入0到ACCEL_CONFIG寄存器,设置加速度计的满量程范围为±2g
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_ACCEL_CONFIG, I2C_MEMADD_SIZE_8BIT, &daty, 1, HAL_MAX_DELAY);
}
2.8主处理芯片访问MPU6050辅助I2C
void MPU6050_AccessAuxiliaryI2C()
{
// 这里可以编写主处理芯片访问MPU6050辅助I2C的代码
}
3读取数据
3.1读取陀螺仪的数据
//读取陀螺仪的数据
void Read_Mpu_Gyro(void)
{
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,GYRO_XOUT_H,I2C_MEMADD_SIZE_8BIT,I2C_Gyro_Buf,6, HAL_MAX_DELAY);
gx=(I2C_Gyro_Buf[0]<<8)+I2C_Gyro_Buf[1]-gx_l;
gy=(I2C_Gyro_Buf[2]<<8)+I2C_Gyro_Buf[3]-gy_l;
gz=(I2C_Gyro_Buf[4]<<8)+I2C_Gyro_Buf[5]-gz_l;
}
3.2读取加速度的数据
//读取加速度的数据
void Read_Mpu_Accel(void)
{
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,ACCEL_XOUT_H,I2C_MEMADD_SIZE_8BIT,I2C_Accel_Buf,6, HAL_MAX_DELAY);
ax=(I2C_Accel_Buf[0]<<8)+I2C_Accel_Buf[1]-ax_l;
ay=(I2C_Accel_Buf[2]<<8)+I2C_Accel_Buf[3]-ay_l;
az=(I2C_Accel_Buf[4]<<8)+I2C_Accel_Buf[5]-az_l;
}
3.3读取温度数据
//读取温度
void Read_Mpu_temp(void)
{
short temp2;
// 0xD0 0x41
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,TEMP_OUT_H,I2C_MEMADD_SIZE_8BIT,I2C_temp_Buf,2, HAL_MAX_DELAY);
temp2= (I2C_temp_Buf[0] << 8) | I2C_temp_Buf[1];
temp=((double) temp2/340.0)+36.53;
}
4.数据校准
//校准
#define CL_cnt 128
void MPU6050_calibrate(void)
{
unsigned short i;
signed int tempe[6]={0};
for(i=0;i<CL_cnt;i++)
{
HAL_Delay(10);
Read_Mpu_Gyro();
Read_Mpu_Accel();
tempe[0]+=ax;
tempe[1]+=ay;
tempe[2]+=az;
tempe[3]+=gx;
tempe[4]+=gy;
tempe[5]+=gz;
}
ax_l=tempe[0]/CL_cnt;
ay_l=tempe[1]/CL_cnt;
az_l=tempe[2]/CL_cnt - (0xffff>>2); //平放时z轴有重力加速度g,减去g值
gx_l=tempe[3]/CL_cnt;
gy_l=tempe[4]/CL_cnt;
gz_l=tempe[5]/CL_cnt;
}
5.main函数中代码:
// 检查通信是否成功
if (MPU6050_CheckCommunication() == 0)
{
printf("Communication successful\n");
// 设置MPU6050为复位状态
MPU6050_Reset();
// 唤醒MPU6050并选择PLL为时钟源
MPU6050_WakeUp();
// 配置6轴数据输出
MPU6050_ConfigureDataOutput();
// 禁止所有中断
MPU6050_DisableInterrupts();
// 设置内部采样频率和低通滤波器
MPU6050_SetSamplingRateAndFilter();
// 设置陀螺仪和加速度计的满量程范围
MPU6050_SetFullScaleRange();
// 主处理芯片访问MPU6050辅助I2C
MPU6050_AccessAuxiliaryI2C();
//校准
MPU6050_calibrate();
}
else
{
// 通信失败
printf("Communication failed\n");
}
6.while (1)循环里代码:
printf("---------------读取数据如下---------------------\r\n");
//读取陀螺仪的数据
Read_Mpu_Gyro();
printf("加速度:ax=%1.3fg,ay=%1.3fg,az=%1.3fg\r\n",(float)ax/(0xffff/4),(float)ay/(0xffff/4),(float)az/(0xffff/4));
//读取加速度的数据
Read_Mpu_Accel();
printf("陀螺仪:gx=%.3fdeg/s,gy=%.3fdeg/s,gz=%.3fdeg/s\r\n",(float)gx/(0xffff/500),(float)gy/(0xffff/500),(float)gz/(0xffff/500));
//读取温度
Read_Mpu_temp();
printf("温度:temp=%d°C\r\n",temp);
HAL_Delay(100);//延迟0.1秒
7.其他
7.1需要加入的头文件:
在重定向printf时需引入下面的头文件。
#include "stdio.h"
7.2printf重定向函数:
//printf重定向
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFF);
return ch;
}
8.代码实现:
读取陀螺仪数据、加速度数据、温度数据代码实现。
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
// MPU6050器件地址
#define MPU6050_ADDRESS 0xD0
// MPU6050寄存器地址
#define MPU6050_REG_PWR_MGMT_1 0x6B //MPU6050的电源管理寄存器1的地址,用于控制设备的电源管理
#define MPU6050_REG_CONFIG 0x1A //MPU6050的配置寄存器的地址,用于配置设备的采样率和低通滤波器
#define MPU6050_REG_GYRO_CONFIG 0x1B //MPU6050的陀螺仪配置寄存器的地址,用于配置陀螺仪的满量程范围
#define MPU6050_REG_ACCEL_CONFIG 0x1C //MPU6050的加速度计配置寄存器的地址,用于配置加速度计的满量程范围
#define MPU6050_REG_ACCEL_XOUT_H 0x3B
//加速度计 数据寄存器地址
#define ACCEL_XOUT_H 0x3B // 存储最近的X轴、Y轴、Z轴加速度感应器的测量值 */
#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 // 存储最近的X轴、Y轴、Z轴陀螺仪感应器的测量值 */
#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
// MPU6050复位延时时间(单位:毫秒)
#define MPU6050_RESET_DELAY 100
//两个无符号字符数组 I2C_Accel_Buf 和 I2C_Gyro_Buf,用于存储通过 I2C 总线读取的加速度和陀螺仪数据。
unsigned char I2C_Accel_Buf[6];
unsigned char I2C_Gyro_Buf[6];
unsigned char I2C_temp_Buf[2];
//加速度计
signed short ax;
signed short ay;
signed short az;
//陀螺仪
signed short gx;
signed short gy;
signed short gz;
//温度
signed short temp;
//校准
signed short ax_l=0;
signed short ay_l=0;
signed short az_l=0;
signed short gx_l=0;
signed short gy_l=0;
signed short gz_l=0;
//printf重定向
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFF);
return ch;
}
// 1.检查MCU与MPU6050通信是否成功
//初始化MPU6050
int MPU6050_CheckCommunication()
{
uint8_t data;
HAL_StatusTypeDef status;
// 发送读取WHO_AM_I命令 0xD0
status = HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDRESS, 0x75, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
if (status != HAL_OK)
{
return -1;
}
// 检查WHO_AM_I寄存器的值是否等于0x68
if (data != 0x68)
{
return -1;
}
return 0;
}
// 2.设置MPU6050为复位状态
void MPU6050_Reset()
{
uint8_t data = 0x80; //1000 0000
//写入复位命令到PWR_MGMT_1寄存器 0xD0 0x6B 0x80
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
//延时等待复位完成 100毫秒
HAL_Delay(MPU6050_RESET_DELAY);
}
// 3.唤醒MPU6050并选择PLL为时钟源
void MPU6050_WakeUp()
{
uint8_t data = 0x01;//0000 0001
//写入唤醒命令到PWR_MGMT_1寄存器 0xD0 0X6B 0x01
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
// 4.配置6轴数据输出
void MPU6050_ConfigureDataOutput()
{
uint8_t data = 0x00;//0000 0000
// 配置CONFIG寄存器,使能加速度计和陀螺仪的所有轴
// 0xD0 0x1A 0x00
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
// 5.禁止所有中断
void MPU6050_DisableInterrupts()
{
uint8_t data = 0x00; //0000 0000
// 写入0到INT_ENABLE寄存器,禁止所有中断
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, 0x37, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
// 6.设置内部采样频率和低通滤波器
void MPU6050_SetSamplingRateAndFilter()
{
uint8_t data = 0x06; //0000 0110
// 写入6到CONFIG寄存器,设置采样频率为1kHz,低通滤波器带宽为5Hz
// 0xD0 0x1A
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
}
// 7.设置陀螺仪和加速度计的满量程范围
void MPU6050_SetFullScaleRange()
{
uint8_t data = 0x18;
// 写入0到GYRO_CONFIG寄存器,设置陀螺仪的满量程范围为±2000°/s
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_GYRO_CONFIG, I2C_MEMADD_SIZE_8BIT, &data, 1, HAL_MAX_DELAY);
uint8_t daty = 0x00;
// 写入0到ACCEL_CONFIG寄存器,设置加速度计的满量程范围为±2g
HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_ACCEL_CONFIG, I2C_MEMADD_SIZE_8BIT, &daty, 1, HAL_MAX_DELAY);
}
// 8.主处理芯片访问MPU6050辅助I2C
void MPU6050_AccessAuxiliaryI2C()
{
// 这里可以编写主处理芯片访问MPU6050辅助I2C的代码
}
//读取陀螺仪的数据
void Read_Mpu_Gyro(void)
{
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,GYRO_XOUT_H,I2C_MEMADD_SIZE_8BIT,I2C_Gyro_Buf,6, HAL_MAX_DELAY);
gx=(I2C_Gyro_Buf[0]<<8)+I2C_Gyro_Buf[1]-gx_l;
gy=(I2C_Gyro_Buf[2]<<8)+I2C_Gyro_Buf[3]-gy_l;
gz=(I2C_Gyro_Buf[4]<<8)+I2C_Gyro_Buf[5]-gz_l;
}
//读取加速度的数据
void Read_Mpu_Accel(void)
{
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,ACCEL_XOUT_H,I2C_MEMADD_SIZE_8BIT,I2C_Accel_Buf,6, HAL_MAX_DELAY);
ax=(I2C_Accel_Buf[0]<<8)+I2C_Accel_Buf[1]-ax_l;
ay=(I2C_Accel_Buf[2]<<8)+I2C_Accel_Buf[3]-ay_l;
az=(I2C_Accel_Buf[4]<<8)+I2C_Accel_Buf[5]-az_l;
}
//读取温度
void Read_Mpu_temp(void)
{
short temp2;
// 0xD0 0x41
HAL_I2C_Mem_Read(&hi2c1,MPU6050_ADDRESS,TEMP_OUT_H,I2C_MEMADD_SIZE_8BIT,I2C_temp_Buf,2, HAL_MAX_DELAY);
temp2= (I2C_temp_Buf[0] << 8) | I2C_temp_Buf[1];
temp=((double) temp2/340.0)+36.53;
}
//校准
#define CL_cnt 128
void MPU6050_calibrate(void)
{
unsigned short i;
signed int tempe[6]={0};
for(i=0;i<CL_cnt;i++)
{
HAL_Delay(10);
Read_Mpu_Gyro();
Read_Mpu_Accel();
tempe[0]+=ax;
tempe[1]+=ay;
tempe[2]+=az;
tempe[3]+=gx;
tempe[4]+=gy;
tempe[5]+=gz;
}
ax_l=tempe[0]/CL_cnt;
ay_l=tempe[1]/CL_cnt;
az_l=tempe[2]/CL_cnt - (0xffff>>2); //平放时z轴有重力加速度g,减去g值
gx_l=tempe[3]/CL_cnt;
gy_l=tempe[4]/CL_cnt;
gz_l=tempe[5]/CL_cnt;
}
/*
// 定义存储加速度和角加速度的变量
int16_t accelX, accelY, accelZ;
int16_t gyroX, gyroY, gyroZ;
int16_t temperature;
// 读取加速度和角加速度数据
void MPU6050_ReadAccelGyroData()
{
uint8_t buffer[14];
// 从ACCEL_XOUT_H寄存器开始连续读取14个字节的数据
HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDRESS, MPU6050_REG_ACCEL_XOUT_H, I2C_MEMADD_SIZE_8BIT, buffer, 14, HAL_MAX_DELAY);
// 解析加速度数据
accelX = (buffer[0] << 8) | buffer[1];
accelY = (buffer[2] << 8) | buffer[3];
accelZ = (buffer[4] << 8) | buffer[5];
// 解析角加速度数据
gyroX = (buffer[8] << 8) | buffer[9];
gyroY = (buffer[10] << 8) | buffer[11];
gyroZ = (buffer[12] << 8) | buffer[13];
// 解析温度数据
temperature = (buffer[6] << 8) | buffer[7];
float temperature_C = (float)temperature / 340.0 + 36.53;
}
*/
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
//static void MPU_Initialize(void);
static void MPU_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* 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();
/* MPU Configuration--------------------------------------------------------*/
MPU_Config();
/* 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 */
/* USER CODE END 2 */
// 检查通信是否成功
if (MPU6050_CheckCommunication() == 0)
{
printf("Communication successful\n");
// 设置MPU6050为复位状态
MPU6050_Reset();
// 唤醒MPU6050并选择PLL为时钟源
MPU6050_WakeUp();
// 配置6轴数据输出
MPU6050_ConfigureDataOutput();
// 禁止所有中断
MPU6050_DisableInterrupts();
// 设置内部采样频率和低通滤波器
MPU6050_SetSamplingRateAndFilter();
// 设置陀螺仪和加速度计的满量程范围
MPU6050_SetFullScaleRange();
// 主处理芯片访问MPU6050辅助I2C
MPU6050_AccessAuxiliaryI2C();
//校准
MPU6050_calibrate();
}
else
{
// 通信失败
printf("Communication failed\n");
}
//HAL_I2C_Mem_Read(&hi2c1,0xA1,0,I2C_MEMADD_SIZE_8BIT,&data1,8,1000);
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
printf("---------------读取数据如下---------------------\r\n");
//读取陀螺仪的数据
Read_Mpu_Gyro();
printf("加速度:ax=%1.3fg,ay=%1.3fg,az=%1.3fg\r\n",(float)ax/(0xffff/4),(float)ay/(0xffff/4),(float)az/(0xffff/4));
//读取加速度的数据
Read_Mpu_Accel();
printf("陀螺仪:gx=%.3fdeg/s,gy=%.3fdeg/s,gz=%.3fdeg/s\r\n",(float)gx/(0xffff/500),(float)gy/(0xffff/500),(float)gz/(0xffff/500));
//读取温度
Read_Mpu_temp();
printf("温度:temp=%d°C\r\n",temp);
HAL_Delay(100);
//MPU6050_ReadAccelGyroData();
//printf("%d,%d,%d,%d,%d,%d,%d\n",accelX, accelY, accelZ,gyroX, gyroY, gyroZ,temperature);
//HAL_Delay(1000);
//printf("写入ok\r\n");
//HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}