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

相关推荐
泉飒1 小时前
lua注意事项
开发语言·笔记·lua
拾忆-eleven2 小时前
NLP学习路线图(十五):TF-IDF(词频-逆文档频率)
人工智能·学习·自然语言处理·nlp
茯苓gao2 小时前
STM32G4 电机外设篇(三) TIM1 发波 和 ADC COMP DAC级联
stm32·单片机·嵌入式硬件
君鼎2 小时前
STM32——CAN总线
stm32·单片机·嵌入式硬件
阿川!2 小时前
嵌入式软件--stm32 DAY 8.5 基础复习总结
stm32·单片机·嵌入式硬件
viperrrrrrrrrr72 小时前
大数据学习(125)-hive数据分析
大数据·学习
lulinhao3 小时前
VLAN的作用和原理
网络·笔记·vlan
moxiaoran57534 小时前
uni-app学习笔记十八--uni-app static目录简介
笔记·学习·uni-app
航Hang*4 小时前
WEBSTORM前端 —— 第3章:移动 Web —— 第4节:移动适配-VM
前端·笔记·edge·less·css3·html5·webstorm
Studying 开龙wu4 小时前
机器学习有监督学习sklearn实战二:六种算法对鸢尾花(Iris)数据集进行分类和特征可视化
学习·算法·机器学习