STM32 I2C通信协议详解(一):基础知识与软件实现指南
2025-09-29 来源:cnblogs
一、I2C基础知识
1)I2C通信
I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线
两根通信线:SCL(Serial Clock)、SDA(Serial Data)
同步,半双工
带数据应答
支持总线挂载多设备(一主多从、多主多从)

所有I2C设备的SCL连接在一起,SDA连接在一起
每个从机有一个7位地址,部分地址可以通过引脚灵活切换
所有SCL和SDA都配置为开漏输出模式
防止电源短路,所有设备禁止强上拉模式
避免了输入输出的频繁切换
通过“线与”实现多主机模式下的时钟同步和总线仲裁
SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右

起始条件:SCL高电平期间,SDA从高电平切换到低电平
终止条件:SCL高电平期间,SDA从低电平切换到高电平

发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节

接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
指定地址写
对于指定设备(Slave Address 0xD0),在指定地址(Reg Address 0x19)下,写入指定数据(Data 0xAA)

当前地址读
对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)
读取操作会读取到上次主机读取的地址的下一位,所以要指定地址读的话就先进行指定地址写的操作,在主机写完后再次发送起始命令就可以直接进行读的操作了
主机可以不应答,就是告诉从机不想要数据了,然后再结束

MPU6050是一个6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角(欧拉角),常应用于平衡车、飞行器等需要检测自身姿态的场景
3轴加速度计(Accelerometer):测量X、Y、Z轴的加速度
3轴陀螺仪传感器(Gyroscope):测量X、Y、Z轴的角速度

16位ADC采集传感器的模拟信号,量化范围:-32768~32767
加速度计满量程选择:±2、±4、±8、±16(g)
陀螺仪满量程选择: ±250、±500、±1000、±2000(°/sec)
可配置的数字低通滤波器,是输出数据平缓
可配置的时钟源
可配置的采样分频,控制AD转换的速度
I2C从机地址:1101000(AD0=0) 1101001(AD0=1),不融入读写位为0x68,融入读写位为0xD0
硬件电路,通过自测响应判断好坏,同时具有温度传感器,内部有电荷泵(用来升压 )

其他资料详见手册
可以把AD0引脚接高电平修改MPU的名称,改了后记得地址为0xD2
关键代码:
2)I2C硬件电路
2)I2C时序基本单元
3)I2C完整时序
4)MPU6050简介
二、实验
1)软件I2C读写MPU6050
//写一个字节
void MPU6050_WriteReg(u8 RegAddress, u8 Data){
MyI2C_Start();
MyI2C_SendByte(0xD0);
MyI2C_ReceiveAck();
MyI2C_SendByte(RegAddress);
MyI2C_ReceiveAck();
MyI2C_SendByte(Data);
MyI2C_ReceiveAck();
MyI2C_Stop();
}
//读一个字节
u8 MPU6050_ReadReg(u8 RegAddress){
MyI2C_Start();
MyI2C_SendByte(0xD0);
MyI2C_ReceiveAck();
MyI2C_SendByte(RegAddress);
MyI2C_ReceiveAck();
MyI2C_Start();
MyI2C_SendByte(0xD1);
MyI2C_ReceiveAck();
u8 Data = MyI2C_ReceiveByte();
MyI2C_SendAck(1);
MyI2C_Stop();
return Data;
}
u8 MPU6050_GetID(void){
return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}
void MPU6050_Init(void){
MyI2C_Init();
MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);
MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);
MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x00);
MPU6050_WriteReg(MPU6050_CONFIG, 0x06);
MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);
MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);
}
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t*AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ){
int16_t DataH, DataL;
DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
*AccX = DataH << 8 | DataL;
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);
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;
}
下一篇:STM32 I2C硬件读写详解
- 意法半导体中国本地造STM32微控制器启动规模量产
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 基于机智云与STM32的智能拐杖安全监测系统在养老物联网中的应用
- 内置全栈安全,一站式满足CRA法案与IEC 62443标准——米尔STM32MP257核心板
- 如何用 STM32 FLASH 实现等效 100 万次擦写的 EEPROM 功能?
- 实战解析:通过一个小项目掌握STM32所有外设
- STM32学了两年半,却还是不会做项目
- 意法半导体推出最新STM32MP21微处理器,兼具高性价比、低功耗、高灵活性
- 基于STM32的矿井作业环境监测系统设计与实现
- 六大全新产品系列推出,MCX A微控制器家族迎来创新
- 意法半导体全新STM32C5系列,重新定义入门级微控制器性能与价值,赋能万千智能设备
- 模组复用与整机重测在SRRC、CCC、CTA/NAL认证中的实践操作指南
- 有源晶振与无源晶振的六大区别详解
- 从控制到系统:TI利用边缘AI重塑嵌入式MCU的边界
- 英飞凌持续巩固全球微控制器市场领导地位
- 使用 Keil Studio for Visual Studio Code开发 STM32 设备
- 蓝牙信道探测技术原理与开发套件实践
- Microchip 推出生产就绪型全栈边缘 AI 解决方案,赋能MCU和MPU实现 智能实时决策
- LoRa、LoRaWAN、NB-IoT与4G DTU技术对比及工业无线方案选型分析




