STM32学习笔记-----I2C协议

STM32的I2C(Inter-Integrated Circuit)是一个串行通信协议,用于微控制器和其他外部设备之间的数据交换。STM32的I2C外设支持多种模式,能够方便地进行设备之间的低速、低功耗数据传输。以下是STM32使用标准库的I2C配置和使用方法的详细介绍

I2C基础概念

I2C总线是一个双线制协议,包含两条信号线:

  • SCL:时钟线(Clock),由主设备提供时钟信号。
  • SDA:数据线(Data),用于传输数据,支持双向传输。

I2C设备分为:

  • 主设备:负责启动和停止通信,并生成时钟信号。STM32通常作为主设备。
  • 从设备:接收或发送数据,响应主设备的命令。

STM32 I2C标准库配置

STM32的I2C功能可以通过标准库(STM32固件库)进行配置。主要的配置步骤包括:

  1. 初始化I2C外设:设置I2C的工作模式、时钟、地址模式、波特率等。
  2. 配置GPIO:I2C的SCL和SDA信号线需要进行相应的GPIO配置。
  3. 数据传输:进行I2C通信,包括写数据、读数据、地址设置等。

1. I2C初始化

首先,需要初始化I2C外设并配置相关参数。以下是一个基于标准库的I2C初始化例子:

cpp 复制代码
#include "stm32f4xx.h"

void I2C_Init_Config(void)
{
    // 使能I2C时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    // 使能GPIO时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // 配置GPIO(SCL和SDA)
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_9;  // SCL为PB6,SDA为PB9
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;            // 复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;          // 开漏输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;            // 上拉
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 设置I2C复用功能(PB6为SCL,PB9为SDA)
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);

    // 配置I2C
    I2C_InitTypeDef I2C_InitStructure;
    I2C_InitStructure.I2C_ClockSpeed = 100000;      // I2C时钟频率100kHz
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;      // 工作模式I2C
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  // 占空比2:1
    I2C_InitStructure.I2C_OwnAddress1 = 0x30;        // 设置设备的地址
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;      // 使能ACK应答
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7位地址模式
    I2C_Init(I2C1, &I2C_InitStructure);

    // 使能I2C1外设
    I2C_Cmd(I2C1, ENABLE);
}

在上面的代码中:

  • I2C_ClockSpeed:设置I2C的时钟频率。常见的I2C时钟频率有100kHz(标准模式)和400kHz(快速模式)。
  • I2C_OwnAddress1:设置STM32的I2C从地址。
  • I2C_Ack:使能应答功能,允许设备进行数据确认。
  • I2C_AcknowledgedAddress:选择7位或10位地址模式。

2. 数据传输

I2C通信一般包括两种操作:写数据读数据

写数据到I2C设备

在写数据时,首先发送设备地址,然后发送数据。以下是通过I2C写数据的例子:

cpp 复制代码
void I2C_Write(uint8_t slaveAddress, uint8_t regAddress, uint8_t data)
{
    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

    // 发送启动信号
    I2C_GenerateSTART(I2C1, ENABLE);

    // 等待START信号发送完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    // 发送从设备地址
    I2C_Send7bitAddress(I2C1, slaveAddress, I2C_Direction_Transmitter);

    // 等待地址传输完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    // 发送寄存器地址
    I2C_SendData(I2C1, regAddress);

    // 等待数据传输完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    // 发送数据
    I2C_SendData(I2C1, data);

    // 等待数据传输完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);
}
从I2C设备读取数据

读取数据时,首先发送设备地址和寄存器地址,然后进行数据读取。以下是读取数据的代码:

cpp 复制代码
uint8_t I2C_Read(uint8_t slaveAddress, uint8_t regAddress)
{
    uint8_t receivedData;

    // 等待I2C总线空闲
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

    // 发送启动信号
    I2C_GenerateSTART(I2C1, ENABLE);

    // 等待START信号发送完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    // 发送从设备地址
    I2C_Send7bitAddress(I2C1, slaveAddress, I2C_Direction_Transmitter);

    // 等待地址传输完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    // 发送寄存器地址
    I2C_SendData(I2C1, regAddress);

    // 等待数据传输完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    // 发送重复启动信号
    I2C_GenerateSTART(I2C1, ENABLE);

    // 等待重复启动完成
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

    // 发送从设备地址,设置为接收模式
    I2C_Send7bitAddress(I2C1, slaveAddress, I2C_Direction_Receiver);

    // 等待数据接收
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    // 接收数据
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    receivedData = I2C_ReceiveData(I2C1);

    // 发送停止信号
    I2C_GenerateSTOP(I2C1, ENABLE);

    return receivedData;
}

3. 错误处理与常见问题

I2C通信中常见的问题包括:

  • 总线忙碌 :通过检查I2C_FLAG_BUSY标志位来确认I2C是否处于忙碌状态。
  • 超时错误:如果操作时间过长,可能会引发超时错误。可以设置一个超时计数器,并定期检查。

4. 总结

使用STM32的标准库配置和使用I2C外设涉及初始化I2C外设、配置GPIO、进行数据传输等步骤。理解I2C的工作原理和每个步骤的细节是保证通信稳定性的关键。

通过标准库的I2C功能,STM32可以高效地与外部设备(如传感器、EEPROM等)进行数据交换,适用于各种嵌入式应用。

相关推荐
Asa3196 分钟前
STM32-按键扫描配置
stm32·单片机·嵌入式硬件
南城花随雪。24 分钟前
单片机:实现驱动超声波(附带源码)
单片机·嵌入式硬件
嵌入式科普25 分钟前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
biter008829 分钟前
opencv(15) OpenCV背景减除器(Background Subtractors)学习
人工智能·opencv·学习
车轮滚滚__40 分钟前
uniapp对接unipush 1.0 ios/android
笔记
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
QQ同步助手2 小时前
如何正确使用人工智能:开启智慧学习与创新之旅
人工智能·学习·百度
流浪的小新2 小时前
【AI】人工智能、LLM学习资源汇总
人工智能·学习
A懿轩A3 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
云边有个稻草人3 小时前
【优选算法】—复写零(双指针算法)
笔记·算法·双指针算法