单片机
返回首页

STM32 I2C通信协议详解(一):基础知识与软件实现指南

2025-09-29 来源:cnblogs

一、I2C基础知识

1)I2C通信

  • I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线

  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)

  • 同步,半双工

  • 带数据应答

  • 支持总线挂载多设备(一主多从、多主多从)

  • 2)I2C硬件电路

  • 所有I2C设备的SCL连接在一起,SDA连接在一起

  • 每个从机有一个7位地址,部分地址可以通过引脚灵活切换

  • 所有SCL和SDA都配置为开漏输出模式

    1. 防止电源短路,所有设备禁止强上拉模式

    2. 避免了输入输出的频繁切换

    3. 通过“线与”实现多主机模式下的时钟同步和总线仲裁

  • SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右

  • 2)I2C时序基本单元

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

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

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

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

  • 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答

  • 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

  • 3)I2C完整时序

  • 指定地址写

  • 对于指定设备(Slave Address 0xD0),在指定地址(Reg Address 0x19)下,写入指定数据(Data 0xAA)

  • 当前地址读

  • 对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)

  • 读取操作会读取到上次主机读取的地址的下一位,所以要指定地址读的话就先进行指定地址写的操作,在主机写完后再次发送起始命令就可以直接进行读的操作了

  • 主机可以不应答,就是告诉从机不想要数据了,然后再结束

  • 4)MPU6050简介

  • 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

  • 硬件电路,通过自测响应判断好坏,同时具有温度传感器,内部有电荷泵(用来升压 )

  • 其他资料详见手册

  • 二、实验

    1)软件I2C读写MPU6050

  • 可以把AD0引脚接高电平修改MPU的名称,改了后记得地址为0xD2

  • 关键代码:

//写一个字节

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;

}


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 1瓦四级调频发射机

  • 500W MOS场效应管电源逆变器,12V转110V/220V

  • 红外开关

  • LM317过压保护

  • 0-30V/20A 大功率稳压电源(采用LM338)

    相关电子头条文章