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等)进行数据交换,适用于各种嵌入式应用。

相关推荐
Mephisto.java10 分钟前
【大数据学习 | flume】flume之常见的channel组件
大数据·学习·flume
zyhhsss36 分钟前
计算机网络
笔记·学习·计算机网络
沐欣工作室_lvyiyi2 小时前
基于单片机的智能奶茶机设计(论文+源码)
stm32·单片机·嵌入式硬件·物联网·毕业设计·智能家居
一棵开花的树,枝芽无限靠近你2 小时前
【element-tiptap】Tiptap编辑器核心概念----结构篇
前端·笔记·学习·编辑器
祭の3 小时前
HttpServletResponse响应对象讲解(笔记)
java·前端·笔记
Qingniu014 小时前
【青牛科技】电动工具直流调速专用集成电路GS069,具有电源电压范围宽、功耗小、抗干扰能力强等特性
科技·单片机·嵌入式硬件·实时音视频·储能
小黄人软件4 小时前
【android USB 串口通信助手】stm32 源码demo 单片机与手机通信 Android studio 20241118
android·stm32·单片机
一水鉴天4 小时前
智能工厂的设计软件 为了监管控一体化的全能Supervisor 的监督学习 之 序6 进化论及科学的信息技术创新:分布式账本/区块链/智能合约
开发语言·人工智能·学习·区块链·智能合约·分布式账本
白书宇4 小时前
13.100ASK_T113-PRO RTC实验
linux·arm开发·驱动开发·嵌入式硬件·物联网·硬件工程