上一节,完成了对IIC软件的实验程序,也就是说只要我们编程能够模拟IIC协议规定的时序,所有IIC的外设就能解析IIC的读出我们数据,就能和相关IIC外设进行交互,然后,STM32自带硬件收发电路,接下来我们就进行硬件IIC的学习,(这个插播一句,USART可以用软件实现吗?)
【STM32-I2C学习总结】STM32:硬件-IIC详解 , 固件库编程 , 手把手教你实现IIC_stm32硬件iic-CSDN博客
代码:
硬件IIC配置
MPU6050.c
#include "stm32f10x.h" // Device header #include "MPU6050.h" #include "MPU6050_Reg_Config.h" #define MPU6050_Address 0xD0 // 定义MPU6050的I2C地址 void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) { uint32_t Timeout = 10000; while(!I2C_CheckEvent(I2Cx, I2C_EVENT)) { Timeout--; if(Timeout == 0) { break; } } } // MPU6050初始化函数 void MPU6050_Init(void) { // MyIIC_Init(); // 初始化I2C通信 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_InitStruture; GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStruture.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStruture); I2C_DeInit(I2C2); I2C_InitTypeDef I2C_InitStructrue; I2C_InitStructrue.I2C_Ack = I2C_Ack_Enable; I2C_InitStructrue.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructrue.I2C_ClockSpeed = 100000; I2C_InitStructrue.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructrue.I2C_Mode = I2C_Mode_I2C; I2C_InitStructrue.I2C_OwnAddress1 = 0x00; I2C_Init(I2C2, &I2C_InitStructrue); I2C_Cmd(I2C2,ENABLE); MPU6050_Register_W(MPU_PWR_MGMT1_REG, 0x01); // 设置MPU6050的电源管理寄存器 MPU6050_Register_W(MPU_PWR_MGMT2_REG, 0x00); // 关闭某些休眠模式,确保传感器工作 MPU6050_Register_W(MPU_SAMPLE_RATE_REG, 0x09); // 设置采样率 MPU6050_Register_W(MPU_CFG_REG, 0x06); // 配置低通滤波器 MPU6050_Register_W(MPU_GYRO_CFG_REG, 0x18); // 设置陀螺仪的量程 MPU6050_Register_W(MPU_ACCEL_CFG_REG, 0x18); // 设置加速度计的量程 } // 写寄存器函数 void MPU6050_Register_W(uint8_t MPU6050_Reg_Addr, uint8_t Data) { // MyIIC_Start(); // 启动I2C通信 // MyIIC_SendByte(MPU6050_Address); // 发送MPU6050的I2C地址 // MyIIC_ReceiveAck(); // 接收应答 // MyIIC_SendByte(MPU6050_Reg_Addr); // 发送寄存器地址 // MyIIC_ReceiveAck(); // 接收应答 // MyIIC_SendByte(Data); // 发送数据 // MyIIC_ReceiveAck(); // 接收应答 // MyIIC_Stop(); // 停止I2C通信 I2C_GenerateSTART(I2C2,ENABLE); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2,MPU6050_Address,I2C_Direction_Transmitter); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); I2C_SendData(I2C2, MPU6050_Reg_Addr); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING); I2C_SendData(I2C2, Data); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTOP(I2C2,ENABLE); } // 读取寄存器函数 uint8_t MPU6050_Regiter_R(uint8_t MPU6050_Reg_Addr) { uint8_t Data; // MyIIC_Start(); // 启动I2C通信 // MyIIC_SendByte(MPU6050_Address); // 发送MPU6050的I2C地址 // MyIIC_ReceiveAck(); // 接收应答 // MyIIC_SendByte(MPU6050_Reg_Addr); // 发送寄存器地址 // MyIIC_ReceiveAck(); // 接收应答 // // MyIIC_Start(); // 重新启动I2C通信 // MyIIC_SendByte(MPU6050_Address | 0x01); // 发送读取命令(地址加1) // MyIIC_ReceiveAck(); // 接收应答 // Data = MyIIC_ReveiveByte(); // 读取数据 // MyIIC_SendAck(1); // 发送应答 // MyIIC_Stop(); // 停止I2C通信 I2C_GenerateSTART(I2C2,ENABLE); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2,MPU6050_Address,I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C2, MPU6050_Reg_Addr); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTART(I2C2,ENABLE); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2,MPU6050_Address,I2C_Direction_Receiver); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); I2C_AcknowledgeConfig(I2C2,DISABLE); I2C_GenerateSTOP(I2C2,ENABLE); MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED ); Data = I2C_ReceiveData(I2C2); return Data; // 返回读取到的数据 } // 读取MPU6050传感器的加速度计和陀螺仪数据 void MPU6050_RegState_Data(int16_t* Acce_X, int16_t* Acce_Y, int16_t* Acce_Z, int16_t* GYRO_X, int16_t* GYRO_Y, int16_t* GYRO_Z) { uint8_t DataH, DataL; // 读取加速度计X轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_XOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_XOUTL_REG); *Acce_X = (DataH << 8) | DataL; // 合并高低字节并保存到Acce_X // 读取加速度计Y轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_YOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_YOUTL_REG); *Acce_Y = (DataH << 8) | DataL; // 合并高低字节并保存到Acce_Y // 读取加速度计Z轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_ZOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_ZOUTL_REG); *Acce_Z = (DataH << 8) | DataL; // 合并高低字节并保存到Acce_Z // 读取陀螺仪X轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_XOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_XOUTL_REG); *GYRO_X = (DataH << 8) | DataL; // 合并高低字节并保存到GYRO_X // 读取陀螺仪Y轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_YOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_YOUTL_REG); *GYRO_Y = (DataH << 8) | DataL; // 合并高低字节并保存到GYRO_Y // 读取陀螺仪Z轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_ZOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_ZOUTL_REG); *GYRO_Z = (DataH << 8) | DataL; // 合并高低字节并保存到GYRO_Z } // 读取MPU6050的设备ID uint8_t MPU6050_ID(void) { return MPU6050_Regiter_R(MPU_DEVICE_ID_REG); // 读取并返回设备ID } // 获取MPU6050的传感器数据并返回结构体指针 MPU6050_Data* MPU6050_Struct_Data(void) { static MPU6050_Data sensorData; // 定义静态结构体变量,确保返回的指针有效 uint8_t DataH, DataL; // 读取加速度计 X 轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_XOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_XOUTL_REG); sensorData.Acce_X = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Acce_X // 读取加速度计 Y 轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_YOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_YOUTL_REG); sensorData.Acce_Y = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Acce_Y // 读取加速度计 Z 轴数据 DataH = MPU6050_Regiter_R(MPU_ACCEL_ZOUTH_REG); DataL = MPU6050_Regiter_R(MPU_ACCEL_ZOUTL_REG); sensorData.Acce_Z = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Acce_Z // 读取陀螺仪 X 轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_XOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_XOUTL_REG); sensorData.Gyro_X = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Gyro_X // 读取陀螺仪 Y 轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_YOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_YOUTL_REG); sensorData.Gyro_Y = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Gyro_Y // 读取陀螺仪 Z 轴数据 DataH = MPU6050_Regiter_R(MPU_GYRO_ZOUTH_REG); DataL = MPU6050_Regiter_R(MPU_GYRO_ZOUTL_REG); sensorData.Gyro_Z = (DataH << 8) | DataL; // 合并高低字节并保存到sensorData.Gyro_Z return &sensorData; // 返回结构体指针 }
这是一个用于STM32F10x微控制器的MPU6050传感器I2C通信驱动程序。下面是详细解释:
- 初始化与配置 (
MPU6050_Init()
):
- 配置I2C通信接口(使用I2C2)
- 初始化GPIOB的PB10和PB11引脚用于I2C通信
- 配置MPU6050传感器的基本参数,包括:
- 电源管理
- 采样率
- 低通滤波器配置
- 陀螺仪和加速度计量程设置
- 寄存器读写函数:
MPU6050_Register_W()
: 向MPU6050特定寄存器写入数据MPU6050_Regiter_R()
: 从MPU6050特定寄存器读取数据
- 数据读取函数:
MPU6050_RegState_Data()
: 读取加速度计和陀螺仪的X、Y、Z轴数据MPU6050_Struct_Data()
: 将传感器数据打包到结构体中并返回
- 其他实用函数:
MPU6050_ID()
: 读取MPU6050的设备IDMPU6050_WaitEvent()
: 等待I2C通信事件完成,并设置超时机制关键特点:
- 使用硬件I2C(I2C2)进行通信
- 支持读取加速度计和陀螺仪的原始数据
- 配置了传感器的基本工作参数
- 包含错误处理机制(超时检测)
代码主要用于嵌入式系统中获取MPU6050传感器的运动和姿态数据。
源码:上传明细-CSDN创作中心
这段代码主要涉及 MPU6050 传感器的初始化和数据读取,利用 STM32F10x 微控制器通过 I2C 与 MPU6050 进行通信。以下是对每个部分的详细解释:
头文件和宏定义
c
复制代码
#include "stm32f10x.h" // Device header #include "MPU6050.h" #include "MPU6050_Reg_Config.h" #define MPU6050_Address 0xD0 // 定义MPU6050的I2C地址
#include "stm32f10x.h"
:包含 STM32F10x 系列 MCU 的头文件,提供硬件寄存器的访问和一些标准库函数。#include "MPU6050.h"
和#include "MPU6050_Reg_Config.h"
:包含 MPU6050 相关的函数和寄存器定义头文件。MPU6050_Address 0xD0
:定义了 MPU6050 的 I2C 地址,其中0xD0
是 MPU6050 的 I2C 地址的 8 位形式(设备地址为0x68
,但是加上读/写位后,I2C 地址会变成0xD0
或0xD1
)。
MPU6050_WaitEvent 函数
c
复制代码
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) { uint32_t Timeout = 10000; while(!I2C_CheckEvent(I2Cx, I2C_EVENT)) { Timeout--; if(Timeout == 0) { break; } } }
- 功能:该函数用于等待指定的 I2C 事件发生。
I2C_CheckEvent(I2Cx, I2C_EVENT)
:检查 I2C 是否已触发指定的事件。- 通过
Timeout
控制超时,防止程序在等待时进入死循环。
MPU6050_Init 函数
c
复制代码
void MPU6050_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStruture; GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStruture.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruture); I2C_DeInit(I2C2); I2C_InitTypeDef I2C_InitStructrue; I2C_InitStructrue.I2C_Ack = I2C_Ack_Enable; I2C_InitStructrue.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStructrue.I2C_ClockSpeed = 100000; I2C_InitStructrue.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStructrue.I2C_Mode = I2C_Mode_I2C; I2C_InitStructrue.I2C_OwnAddress1 = 0x00; I2C_Init(I2C2, &I2C_InitStructrue); I2C_Cmd(I2C2, ENABLE); // 设置MPU6050寄存器 MPU6050_Register_W(MPU_PWR_MGMT1_REG, 0x01); // 设置电源管理寄存器 MPU6050_Register_W(MPU_PWR_MGMT2_REG, 0x00); // 关闭休眠模式 MPU6050_Register_W(MPU_SAMPLE_RATE_REG, 0x09); // 设置采样率 MPU6050_Register_W(MPU_CFG_REG, 0x06); // 配置低通滤波器 MPU6050_Register_W(MPU_GYRO_CFG_REG, 0x18); // 设置陀螺仪的量程 MPU6050_Register_W(MPU_ACCEL_CFG_REG, 0x18); // 设置加速度计的量程 }
- 功能:初始化 I2C 总线和 MPU6050 传感器。
- 通过
RCC_APB1PeriphClockCmd
和RCC_APB2PeriphClockCmd
启用 I2C2 和 GPIOB 时钟。 - 配置
GPIOB
的引脚 10 和 11 为 I2C2 的 SDA 和 SCL。 - 设置 I2C 参数,如时钟速率、应答使能、地址模式等。
- 最后,配置 MPU6050 寄存器来启用其工作状态、关闭休眠模式、设置采样率、配置滤波器等。
MPU6050_Register_W 函数
c
复制代码
void MPU6050_Register_W(uint8_t MPU6050_Reg_Addr, uint8_t Data) { I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_Address, I2C_Direction_Transmitter); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); I2C_SendData(I2C2, MPU6050_Reg_Addr); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING); I2C_SendData(I2C2, Data); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTOP(I2C2, ENABLE); }
- 功能:通过 I2C 向 MPU6050 写入数据。
- 先生成启动信号,然后发送设备地址和写操作指令。
- 接着发送寄存器地址和数据,最后生成停止信号。
MPU6050_Regiter_R 函数
c
复制代码
uint8_t MPU6050_Regiter_R(uint8_t MPU6050_Reg_Addr) { uint8_t Data; I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_Address, I2C_Direction_Transmitter); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); I2C_SendData(I2C2, MPU6050_Reg_Addr); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); I2C_GenerateSTART(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); I2C_Send7bitAddress(I2C2, MPU6050_Address, I2C_Direction_Receiver); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); I2C_AcknowledgeConfig(I2C2, DISABLE); I2C_GenerateSTOP(I2C2, ENABLE); MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED); Data = I2C_ReceiveData(I2C2); return Data; }
- 功能:通过 I2C 从 MPU6050 读取数据。
- 首先发送设备地址和寄存器地址,接着生成重复启动信号以切换到接收模式。
- 禁用 ACK 并生成停止信号后,读取接收到的数据。
MPU6050_RegState_Data 函数
c
复制代码
void MPU6050_RegState_Data(int16_t* Acce_X, int16_t* Acce_Y, int16_t* Acce_Z, int16_t* GYRO_X, int16_t* GYRO_Y, int16_t* GYRO_Z) { uint8_t DataH, DataL; // 读取加速度计和陀螺仪的数据 // 合并高低字节并保存到传入的变量 }
- 功能:读取加速度计和陀螺仪的三轴数据,并将结果合并成 16 位数据(高字节和低字节合并)。
- 通过调用
MPU6050_Regiter_R
函数读取每个轴的数据。
MPU6050_ID 函数
c
复制代码
uint8_t MPU6050_ID(void) { return MPU6050_Regiter_R(MPU_DEVICE_ID_REG); // 读取并返回设备ID }
- 功能:读取 MPU6050 的设备 ID。
MPU6050_Struct_Data 函数
c
复制代码
MPU6050_Data* MPU6050_Struct_Data(void) { static MPU6050_Data sensorData; // 定义静态结构体变量,确保返回的指针有效 uint8_t DataH, DataL; // 读取传感器数据并存储到结构体