STM32F103C8T6芯片I2C功能详细描述+通用模板+关键代码参数修改解析

1. I2C模块概述

STM32F103C8T6芯片内置2个独立的I2C接口(I2C1和I2C2),支持标准I2C协议(最高400 kHz)和SMBus协议(系统管理总线)。其核心功能包括:

  • 多主机/从机模式:支持多设备总线竞争及仲裁。
  • 双向通信:通过串行数据线(SDA)和时钟线(SCL)实现半双工通信。
  • 硬件从地址识别:可编程7位或10位从机地址,支持广播呼叫。
  • 时钟控制:主模式下可配置SCL时钟频率,支持时钟拉伸(Clock Stretching)。
  • 中断/DMA支持:通过事件中断或DMA提升数据传输效率。

2. I2C架构与核心组件
  • 时钟生成器

    • 由APB1总线时钟分频产生SCL时钟频率,公式为:
      fSCL​=(2×CCR)fAPB1​​
      其中CCR为I2C时钟控制寄存器的分频值。
    • 支持标准模式(100 kHz)和快速模式(400 kHz)。
  • 数据寄存器(DR)​

    • 8位寄存器,用于发送或接收数据字节。
    • 写操作自动触发数据发送,读操作自动接收数据。
  • 控制逻辑

    • 通过状态寄存器(SR1/SR2)监控通信状态(如起始条件、地址匹配、数据收发完成等)。
    • 支持自动生成起始条件(START)、重复起始条件(Repeated START)和停止条件(STOP)。

3. 工作模式
主模式(Master Mode)​
  • 主发送模式
    主机发起通信,向从机发送数据。流程:

    1. 发送起始条件(START)。
    2. 发送从机地址(含读/写位)。
    3. 发送数据字节。
    4. 发送停止条件(STOP)或重复起始条件。
  • 主接收模式
    主机发起通信,从从机接收数据。流程:

    1. 发送起始条件(START)。
    2. 发送从机地址(读标志位)。
    3. 接收数据字节。
    4. 发送停止条件(STOP)。
从模式(Slave Mode)​
  • 从发送模式
    从机响应主机请求并发送数据。需预先配置自身地址。

  • 从接收模式
    从机接收主机发送的数据。支持地址匹配和广播呼叫(Broadcast Call)检测。


4. 中断与事件管理
  • 中断类型

    • 通信事件:起始条件检测、地址匹配、数据字节收发完成。
    • 错误事件:总线错误(Bus Error)、仲裁丢失(Arbitration Loss)、ACK故障(ACK Failure)。
    • 缓冲区事件:DMA请求、数据寄存器空/满。
  • 中断配置

    • 通过I2C_CR2寄存器使能中断源(如ITEVTEN、ITERREN)。
    • 中断服务函数需手动清除标志位(通过读SR1/SR2寄存器或写DR寄存器)。

5. 关键特性与配置参数
  • 时钟配置

    • 标准模式:tHIGH​/tLOW​ 时间符合I2C规范(最小4.7 μs)。
    • 快速模式:支持时钟占空比调节(可通过I2C_CCR寄存器配置)。
  • 从地址配置

    • 7位地址模式:支持112个独立地址。
    • 10位地址模式:扩展地址范围,需两次地址发送。
  • 总线超时检测

    • 可选总线空闲超时(Timeout)功能,防止总线死锁。

6. 错误处理机制
  • 仲裁丢失(ARLO)​
    多主机竞争时,若检测到自身发送电平与总线实际电平不一致,自动切换为从机模式。

  • 总线错误(BERR)​
    检测到非法的起始/停止条件时触发,需软件复位总线。

  • ACK故障(AF)​
    从机未应答地址或数据时触发,主机可重试或终止传输。


7. DMA支持
  • 数据传输优化

    • 通过DMA通道实现数据批量传输,减少CPU占用。
    • 发送和接收方向可独立配置DMA请求。
  • 配置步骤

    1. 使能I2C的DMA请求(I2C_DLEN设置数据长度)。
    2. 配置DMA通道,指定内存与外设地址(I2C_DR)。
    3. 启动DMA传输。

8.上完整程序模版,复制可用,已详细注释
/* 包含STM32标准外设库头文件 */
#include "stm32f10x.h"

/* 硬件配置宏(示例:I2C1,SCL-PB6,SDA-PB7,目标从机地址0xA0) */
#define I2Cx               I2C1
#define I2C_SCL_PIN        GPIO_Pin_6
#define I2C_SDA_PIN        GPIO_Pin_7
#define I2C_GPIO_PORT      GPIOB
#define I2C_CLOCK          RCC_APB1Periph_I2C1
#define SLAVE_ADDRESS      0xA0    // 7位地址左移1位后的值(0xA0 = 0x50 << 1)
#define I2C_SPEED          400000  // 通信速率(单位:Hz,范围:0-400k)

/**
  * @brief  I2C初始化配置函数
  * @param  无
  * @retval 无
  */
void I2C_Config(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
    I2C_InitTypeDef I2C_InitStruct;
    
    /* 1. 使能时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // GPIOB时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);   // I2C1时钟

    /* 2. 配置GPIO为复用开漏模式 */
    GPIO_InitStruct.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;          // 复用开漏模式
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;        // 高速模式
    GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStruct);

    /* 3. I2C参数配置 */
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;              // 标准I2C模式
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;      // 时钟占空比(2:1,仅快速模式有效)
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;               // 主机自身地址(从机模式时有效)
    I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;             // 使能ACK响应
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7位地址模式
    I2C_InitStruct.I2C_ClockSpeed = I2C_SPEED;           // 通信速率(最大400kHz)
    I2C_Init(I2Cx, &I2C_InitStruct);

    /* 4. 使能I2C模块 */
    I2C_Cmd(I2Cx, ENABLE);
}

/**
  * @brief  I2C发送数据函数
  * @param  devAddr: 从机地址(7位地址左移1位后的值)
  * @param  regAddr: 寄存器地址
  * @param  pData: 待发送数据指针
  * @param  len: 数据长度
  * @retval 状态:0-成功,1-失败
  */
uint8_t I2C_Write(uint8_t devAddr, uint8_t regAddr, uint8_t *pData, uint16_t len) {
    uint32_t timeout = 10000;  // 超时计数器

    /* 1. 发送START条件 */
    I2C_GenerateSTART(I2Cx, ENABLE);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) { // 等待EV5事件
        if (--timeout == 0) return 1;
    }

    /* 2. 发送从机地址(写模式) */
    I2C_Send7bitAddress(I2Cx, devAddr, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { // 等待EV6事件
        if (--timeout == 0) return 1;
    }

    /* 3. 发送寄存器地址 */
    I2C_SendData(I2Cx, regAddr);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { // 等待EV8_2事件
        if (--timeout == 0) return 1;
    }

    /* 4. 发送数据字节 */
    for (uint16_t i = 0; i < len; i++) {
        I2C_SendData(I2Cx, pData[i]);
        while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
            if (--timeout == 0) return 1;
        }
    }

    /* 5. 发送STOP条件 */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    return 0;
}

/**
  * @brief  I2C接收数据函数
  * @param  devAddr: 从机地址(7位地址左移1位后的值)
  * @param  regAddr: 寄存器地址
  * @param  pData: 接收数据缓冲区指针
  * @param  len: 数据长度
  * @retval 状态:0-成功,1-失败
  */
uint8_t I2C_Read(uint8_t devAddr, uint8_t regAddr, uint8_t *pData, uint16_t len) {
    uint32_t timeout = 10000;

    /* 1. 发送寄存器地址(写模式) */
    I2C_GenerateSTART(I2Cx, ENABLE);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) {
        if (--timeout == 0) return 1;
    }
    I2C_Send7bitAddress(I2Cx, devAddr, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) {
        if (--timeout == 0) return 1;
    }
    I2C_SendData(I2Cx, regAddr);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) {
        if (--timeout == 0) return 1;
    }

    /* 2. 重新发送START条件(切换为读模式) */
    I2C_GenerateSTART(I2Cx, ENABLE);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)) {
        if (--timeout == 0) return 1;
    }

    /* 3. 发送从机地址(读模式) */
    I2C_Send7bitAddress(I2Cx, devAddr, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { // 等待EV6事件
        if (--timeout == 0) return 1;
    }

    /* 4. 接收数据 */
    for (uint16_t i = 0; i < len; i++) {
        if (i == len - 1) {
            I2C_AcknowledgeConfig(I2Cx, DISABLE);  // 最后1字节发送NACK
        }
        while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)) { // 等待EV7事件
            if (--timeout == 0) return 1;
        }
        pData[i] = I2C_ReceiveData(I2Cx);
    }

    /* 5. 发送STOP条件 */
    I2C_GenerateSTOP(I2Cx, ENABLE);
    I2C_AcknowledgeConfig(I2Cx, ENABLE);  // 恢复ACK使能
    return 0;
}

/*********************​ 模板使用示例 ​*********************
int main(void) {
    uint8_t data[2] = {0xAA, 0x55};
    uint8_t recv[2];
    
    SystemInit();
    I2C_Config();
    
    // 向地址0xA0的寄存器0x01写入2字节数据
    I2C_Write(SLAVE_ADDRESS, 0x01, data, 2);
    
    // 从地址0xA0的寄存器0x01读取2字节数据
    I2C_Read(SLAVE_ADDRESS, 0x01, recv, 2);
    
    while(1);
}
********************************************************/

9.模板程序功能说明

  1. 硬件抽象封装
    宏定义硬件连接参数(I2C端口、引脚、地址),便于移植修改。

  2. 完整I2C流程实现

    • I2C_Config():完成GPIO复用配置、时钟设置、I2C参数初始化。
    • I2C_Write():实现带寄存器地址的数据写入(常见于EEPROM、传感器)。
    • I2C_Read():实现带寄存器地址的数据读取(支持多字节连续读)。
  3. 错误处理
    使用超时机制防止总线死锁,返回操作状态码。


​10.关键参数详解

  1. I2C模式参数

    I2C_Mode_I2C          // 标准I2C模式
    I2C_DutyCycle_2       // 快速模式占空比2:1(t_low=2*t_high)
    I2C_Ack_Enable        // 使能ACK自动响应
  2. 事件标志(用于状态检测)​

    I2C_EVENT_MASTER_MODE_SELECT          // START条件已发送(EV5)
    I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED // 从机地址已应答(EV6)
    I2C_EVENT_MASTER_BYTE_TRANSMITTED     // 数据字节发送完成(EV8_2)
    I2C_EVENT_MASTER_BYTE_RECEIVED        // 数据字节接收完成(EV7)
  3. 地址格式

    • 7位从机地址需左移1位后传入(例如:设备地址0x50 → 0x50 << 1 = 0xA0)。
    • 读/写模式通过I2C_Direction_TransmitterI2C_Direction_Receiver指定。

​11.使用注意事项

  1. 硬件连接

    • SCL/SDA必须外接4.7kΩ上拉电阻至3.3V。
    • 长距离通信需考虑总线电容(建议加缓冲器)。
  2. 时序匹配

    • 确保从机支持主机的时钟速率(例如:EEPROM通常最高支持400kHz)。
  3. 错误恢复

    • 检测超时后建议执行总线复位操作:
      I2C_SoftwareResetCmd(I2Cx, ENABLE);
      I2C_SoftwareResetCmd(I2Cx, DISABLE);
  4. 多设备管理

    • 同一总线上多个从机需分配唯一地址,避免冲突。
12. 应用场景
  • 传感器通信:连接温度传感器(如LM75)、加速度计(MPU6050)。
  • 存储设备读写:访问EEPROM(AT24Cxx系列)。
  • 多设备管理:控制LCD屏、RTC时钟(DS3231)等外设。
  • 系统监控:通过SMBus管理电源或电池状态。

13. 使用注意事项
  • 引脚配置

    • SDA和SCL需配置为复用开漏模式(GPIO_Mode_AF_OD),并外接4.7kΩ上拉电阻。
    • 避免长距离布线,防止信号衰减或干扰。
  • 时序兼容性

    • 从机设备需支持主机的时钟频率,否则需启用时钟拉伸功能。
  • 总线冲突处理

    • 多主机系统中,需设计重试机制(如随机延迟后重新发起传输)。
  • 低功耗模式

    • I2C模块在睡眠模式下可保持活动,但需配置相应唤醒源(如地址匹配中断)。

14. 性能限制
  • 最大速率
    • 快速模式下理论速率为400 kbps,实际速率受APB1时钟和布线质量影响。
  • 从机地址容量
    • 单个I2C总线最多支持112个7位地址设备,实际数量受总线电容限制。
  • 中断延迟
    • 高优先级任务可能影响实时性,需结合DMA或优化中断服务函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值