stm32f10x_i2c

STM32F10x I2C 外设标准库函数参考文档

数据类型定义

枚举类型

I2C_Mode_TypeDef - I2C工作模式枚举

typedef enum
{
  I2C_Mode_I2C = 0x0000,           /* 标准I2C模式 */
  I2C_Mode_SMBusDevice = 0x0002,   /* SMBus设备模式 */
  I2C_Mode_SMBusHost = 0x000A      /* SMBus主机模式 */
} I2C_Mode_TypeDef;

说明:

  • I2C_Mode_I2C:标准I2C通信模式
  • I2C_Mode_SMBusDevice:SMBus设备模式,支持SMBus协议
  • I2C_Mode_SMBusHost:SMBus主机模式,具有SMBus主机功能

I2C_DutyCycle_TypeDef - I2C快速模式占空比枚举

typedef enum
{
  I2C_DutyCycle_2 = 0xBFFF,       /* 快速模式占空比 Tlow/Thigh = 2 */
  I2C_DutyCycle_16_9 = 0x4000     /* 快速模式占空比 Tlow/Thigh = 16/9 */
} I2C_DutyCycle_TypeDef;

说明:

  • I2C_DutyCycle_2:快速模式下时钟低电平与高电平比例为2:1
  • I2C_DutyCycle_16_9:快速模式下时钟低电平与高电平比例为16:9

I2C_Ack_TypeDef - I2C应答配置枚举

typedef enum
{
  I2C_Ack_Disable = 0x0000,       /* 失能应答 */
  I2C_Ack_Enable = 0x0400         /* 使能应答 */
} I2C_Ack_TypeDef;

说明:

  • I2C_Ack_Disable:关闭自动应答功能
  • I2C_Ack_Enable:开启自动应答功能

I2C_Direction_TypeDef - I2C传输方向枚举

typedef enum
{
  I2C_Direction_Transmitter = 0x00,  /* 发送器模式 */
  I2C_Direction_Receiver = 0x01      /* 接收器模式 */
} I2C_Direction_TypeDef;

说明:

  • I2C_Direction_Transmitter:主机发送模式
  • I2C_Direction_Receiver:主机接收模式

I2C_AcknowledgedAddress_TypeDef - I2C地址模式枚举

typedef enum
{
  I2C_AcknowledgedAddress_7bit = 0x4000,   /* 7位地址模式 */
  I2C_AcknowledgedAddress_10bit = 0xC000   /* 10位地址模式 */
} I2C_AcknowledgedAddress_TypeDef;

说明:

  • I2C_AcknowledgedAddress_7bit:使用7位设备地址
  • I2C_AcknowledgedAddress_10bit:使用10位设备地址

结构体类型

I2C_InitTypeDef - I2C初始化结构体

typedef struct
{
  uint32_t I2C_ClockSpeed;          /* I2C时钟频率配置 */
  uint16_t I2C_Mode;                /* I2C工作模式选择 */
  uint16_t I2C_DutyCycle;           /* I2C快速模式占空比配置 */
  uint16_t I2C_OwnAddress1;         /* I2C设备自身地址 */
  uint16_t I2C_Ack;                 /* I2C应答功能使能 */
  uint16_t I2C_AcknowledgedAddress; /* I2C地址长度选择 */
} I2C_InitTypeDef;

成员说明:

  • I2C_ClockSpeed:指定I2C时钟频率,范围1Hz到400kHz
  • I2C_Mode:指定I2C工作模式(I2C模式、SMBus设备模式、SMBus主机模式)
  • I2C_DutyCycle:指定快速模式下的占空比配置
  • I2C_OwnAddress1:指定设备自身的第一个地址
  • I2C_Ack:指定应答使能控制
  • I2C_AcknowledgedAddress:指定地址长度选择(7位或10位)

I2C寄存器定义

STM32F10x I2C外设包含以下寄存器:

#define I2C_Register_CR1     ((uint8_t)0x00)  /* 控制寄存器1 */
#define I2C_Register_CR2     ((uint8_t)0x04)  /* 控制寄存器2 */
#define I2C_Register_OAR1    ((uint8_t)0x08)  /* 自身地址寄存器1 */
#define I2C_Register_OAR2    ((uint8_t)0x0C)  /* 自身地址寄存器2 */
#define I2C_Register_DR      ((uint8_t)0x10)  /* 数据寄存器 */
#define I2C_Register_SR1     ((uint8_t)0x14)  /* 状态寄存器1 */
#define I2C_Register_SR2     ((uint8_t)0x18)  /* 状态寄存器2 */
#define I2C_Register_CCR     ((uint8_t)0x1C)  /* 时钟控制寄存器 */
#define I2C_Register_TRISE   ((uint8_t)0x20)  /* 上升时间寄存器 */

I2C中断标志定义

基本中断类型

#define I2C_IT_BUF    ((uint16_t)0x0400)  /* 缓冲区中断 */
#define I2C_IT_EVT    ((uint16_t)0x0200)  /* 事件中断 */
#define I2C_IT_ERR    ((uint16_t)0x0100)  /* 错误中断 */

具体中断标志

#define I2C_IT_SMBALERT  ((uint32_t)0x01008000)  /* SMBus警报中断 */
#define I2C_IT_TIMEOUT   ((uint32_t)0x01004000)  /* 超时/低电平检测中断 */
#define I2C_IT_PECERR    ((uint32_t)0x01001000)  /* PEC错误中断 */
#define I2C_IT_OVR       ((uint32_t)0x01000800)  /* 溢出/欠载中断 */
#define I2C_IT_AF        ((uint32_t)0x01000400)  /* 应答失败中断 */
#define I2C_IT_ARLO      ((uint32_t)0x01000200)  /* 仲裁丢失中断 */
#define I2C_IT_BERR      ((uint32_t)0x01000100)  /* 总线错误中断 */
#define I2C_IT_TXE       ((uint32_t)0x06000080)  /* 数据寄存器空中断 */
#define I2C_IT_RXNE      ((uint32_t)0x06000040)  /* 数据寄存器非空中断 */
#define I2C_IT_STOPF     ((uint32_t)0x02000010)  /* 停止条件检测中断 */
#define I2C_IT_ADD10     ((uint32_t)0x02000008)  /* 10位地址头检测中断 */
#define I2C_IT_BTF       ((uint32_t)0x02000004)  /* 字节传输完成中断 */
#define I2C_IT_ADDR      ((uint32_t)0x02000002)  /* 地址匹配中断 */
#define I2C_IT_SB        ((uint32_t)0x02000001)  /* 起始位检测中断 */

I2C事件定义

主机模式事件

/* 主机模式选择事件 - EV5 */
#define I2C_EVENT_MASTER_MODE_SELECT                      ((uint32_t)0x00030001)

/* 主机发送器模式选择事件 - EV6 */
#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED        ((uint32_t)0x00070082)

/* 主机接收器模式选择事件 - EV6 */
#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED           ((uint32_t)0x00030002)

/* 10位地址模式事件 - EV9 */
#define I2C_EVENT_MASTER_MODE_ADDRESS10                   ((uint32_t)0x00030008)

/* 主机接收到字节事件 - EV7 */
#define I2C_EVENT_MASTER_BYTE_RECEIVED                    ((uint32_t)0x00030040)

/* 主机字节发送中事件 - EV8 */
#define I2C_EVENT_MASTER_BYTE_TRANSMITTING                ((uint32_t)0x00070080)

/* 主机字节发送完成事件 - EV8_2 */
#define I2C_EVENT_MASTER_BYTE_TRANSMITTED                 ((uint32_t)0x00070084)

从机模式事件

/* 从机接收器地址匹配事件 - EV1 */
#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED          ((uint32_t)0x00020002)

/* 从机发送器地址匹配事件 - EV1 */
#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED       ((uint32_t)0x00060082)

/* 从机接收到字节事件 - EV2 */
#define I2C_EVENT_SLAVE_BYTE_RECEIVED                     ((uint32_t)0x00020040)

/* 从机停止条件检测事件 - EV4 */
#define I2C_EVENT_SLAVE_STOP_DETECTED                     ((uint32_t)0x00000010)

/* 从机字节发送完成事件 - EV3 */
#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED                  ((uint32_t)0x00060084)

/* 从机应答失败事件 - EV3_2 */
#define I2C_EVENT_SLAVE_ACK_FAILURE                       ((uint32_t)0x00000400)

标准库函数详解

1. I2C_DeInit

/**
 * @brief  将 I2C 所有寄存器恢复为复位默认值,用于重新配置前清空旧状态或总线异常后恢复
 * @param  I2Cx: 选择要重置的I2C外设,可以是I2C1或I2C2
 * @retval
 * @example
 *     I2C_DeInit(I2C1);
 */
void I2C_DeInit(I2C_TypeDef* I2Cx);

功能说明:

  • 调用后 I2C 回到上电默认配置,传输状态机被重置
  • 切换主从模式或更换时钟频率前可先 DeInit
  • 总线挂死、状态机异常时配合 SoftwareReset 使用

2. I2C_Init

/**
 * @brief  初始化 I2C 外设(时钟频率、主从模式、应答等),决定总线速率与基本工作方式
 * @param  I2Cx: 选择要初始化的I2C外设,可以是I2C1或I2C2
 * @param  I2C_InitStruct: 指向I2C_InitTypeDef结构体的指针,包含配置信息
 * @retval
 * @example
 *     I2C_InitTypeDef I2C_InitStructure;
 *     I2C_InitStructure.I2C_ClockSpeed = 100000;
 *     I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
 *     I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
 *     I2C_Init(I2C1, &I2C_InitStructure);
 */
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);

功能说明:

  • 一次性配置 SCL 频率、7/10 位地址模式、ACK 策略
  • 典型 100kHz(标准)或 400kHz(快速)用于 EEPROM、传感器等
  • 需在 GPIO 复用和时钟使能后、I2C_Cmd 前调用

3. I2C_StructInit

/**
 * @brief  将 I2C_InitTypeDef 成员填为安全默认值,避免未赋值字段导致随机配置
 * @param  I2C_InitStruct: 指向要初始化的I2C_InitTypeDef结构体的指针
 * @retval
 * @example
 *     I2C_InitTypeDef I2C_InitStructure;
 *     I2C_StructInit(&I2C_InitStructure);
 */
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);

功能说明:

  • 默认 100kHz、标准 I2C 模式、7 位地址、应答使能
  • 先 StructInit 再按需修改成员,减少遗漏字段风险
  • 适合快速搭建可工作的初始配置

4. I2C_Cmd

/**
 * @brief  启动或停止 I2C 外设;ENABLE 后外设参与总线通信,DISABLE 后停止
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C外设的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_Cmd(I2C1, ENABLE);
 */
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • I2C_Init 完成后必须 ENABLE 才能发起 START/收发数据
  • DISABLE 可用于低功耗或临时释放总线控制权
  • 从机模式下 ENABLE 后才会响应地址匹配

5. I2C_DMACmd

/**
 * @brief  打开/关闭 I2C 的 DMA 请求,配合 DMA 实现批量收发而无需 CPU 逐字节搬运
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C DMA传输的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_DMACmd(I2C1, ENABLE);
 */
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 使能后 DR 非空/空时自动触发 DMA 搬运
  • 适合大块 EEPROM 读写、传感器 FIFO 读取
  • 需先配置好对应 DMA 通道再打开

6. I2C_DMALastTransferCmd

/**
 * @brief  标记下一次 DMA 传输为最后一笔,用于主机接收结束时自动发送 NACK 并产生 STOP
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: DMA最后传输状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_DMALastTransferCmd(I2C1, ENABLE);
 */
void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 主机 DMA 接收多字节时,最后一字节需 NACK 告知从机结束
  • ENABLE 后硬件在最后一笔 DMA 完成后自动处理 NACK/STOP
  • 避免手动在最后一字节关闭 ACK 的时序问题

7. I2C_GenerateSTART

/**
 * @brief  在总线上产生 START 条件,作为主机发起一次读/写传输的起点
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: START条件产生状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_GenerateSTART(I2C1, ENABLE);
 */
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 主机模式下每次新事务前需产生 START
  • 产生后等待 EV5(主机模式选择)再发从机地址
  • 重复 START(Sr)用于切换读/写方向而不释放总线

8. I2C_GenerateSTOP

/**
 * @brief  在总线上产生 STOP 条件,释放总线并结束当前传输事务
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: STOP条件产生状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_GenerateSTOP(I2C1, ENABLE);
 */
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 一次完整读写结束后必须 STOP 释放 SCL/SDA
  • 未 STOP 时总线保持占用,其他主机无法访问
  • 异常恢复时也可强制 STOP 尝试释放总线

9. I2C_AcknowledgeConfig

/**
 * @brief  控制接收时是否发送 ACK,用于多字节接收中在最后一字节发 NACK 结束传输
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C应答的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_AcknowledgeConfig(I2C1, ENABLE);
 */
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 主机接收时每收到一字节默认回 ACK 请求下一字节
  • 接收最后一字节前 DISABLE,告知从机停止发送
  • 从机发送被 NACK 后应停止发送并释放总线

10. I2C_OwnAddress2Config

/**
 * @brief  配置从机第二自身地址,使同一 I2C 外设可响应两个不同 7 位地址
 * @param  I2Cx: 选择要配置的I2C外设,可以是I2C1或I2C2
 * @param  Address: 指定自身地址2的值
 * @retval
 * @example
 *     I2C_OwnAddress2Config(I2C1, 0x30);
 */
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);

功能说明:

  • 配合 DualAddressCmd 实现双地址从机
  • 适用于同一芯片需模拟两个 I2C 设备的场景
  • 地址 2 仅支持 7 位格式

11. I2C_DualAddressCmd

/**
 * @brief  打开/关闭双地址从机模式,同时监听 OwnAddress1 与 OwnAddress2
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C双地址模式的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_DualAddressCmd(I2C1, ENABLE);
 */
void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • ENABLE 后主机对任一配置地址的寻址都会匹配
  • 需先配置 OAR1 和 OwnAddress2
  • 常用于多功能从机或地址迁移过渡期

12. I2C_GeneralCallCmd

/**
 * @brief  打开/关闭广播呼叫响应,使从机可识别地址 0x00 的全局广播
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C广播呼叫的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_GeneralCallCmd(I2C1, ENABLE);
 */
void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 主机向 0x00 广播时,所有使能的从机同时响应
  • 常用于系统复位、同步配置等广播命令
  • 从机需自行判断广播数据是否针对本设备

13. I2C_Send7bitAddress

/**
 * @brief  发送 7 位从机地址及读写位,选定本次传输的目标从设备与方向
 * @param  I2Cx: 选择要发送地址的I2C外设,可以是I2C1或I2C2
 * @param  Address: 指定要发送的从设备地址
 * @param  I2C_Direction: 指定I2C设备是发送器还是接收器
 * @retval
 * @example
 *     I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
 */
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);

功能说明:

  • START 后紧跟地址字节,最低位 0=写、1=读
  • 地址参数为 8 位格式(7 位地址左移 1 位),库会自动处理 R/W 位
  • 等待 EV6(地址发送/匹配成功)后再读写数据

14. I2C_SendData

/**
 * @brief  向 DR 写入一字节数据,由硬件在 SCL 节拍上串行发出
 * @param  I2Cx: 选择要发送数据的I2C外设,可以是I2C1或I2C2
 * @param  Data: 要发送的数据字节
 * @retval
 * @example
 *     I2C_SendData(I2C1, 0x55);
 */
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);

功能说明:

  • 主机写模式或从机被读时向总线发送数据
  • 写入前需确认 TXE/BTF 标志,避免覆盖未发送完的数据
  • 寄存器地址、命令字、负载均通过此函数发出

15. I2C_ReceiveData

/**
 * @brief  从 DR 读取一字节接收数据,主机读或从机被写时使用
 * @param  I2Cx: 选择要接收数据的I2C外设,可以是I2C1或I2C2
 * @retval 接收到的数据字节
 * @example
 *     uint8_t receivedData = I2C_ReceiveData(I2C1);
 */
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);

功能说明:

  • 读取 RXNE 置位后的 DR 内容
  • 主机读传感器/EEPROM 时循环调用直至收满
  • 读 DR 会自动清除 RXNE,并可能触发下一字节 ACK

16. I2C_ReadRegister

/**
 * @brief  直接读取 I2C 指定寄存器,用于调试或访问库未封装的控制位
 * @param  I2Cx: 选择要读取的I2C外设,可以是I2C1或I2C2
 * @param  I2C_Register: 指定要读取的寄存器
 * @retval 寄存器的值
 * @example
 *     uint16_t regValue = I2C_ReadRegister(I2C1, I2C_Register_SR1);
 */
uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);

功能说明:

  • 可读取 SR1、SR2、CR1 等任意 I2C 寄存器
  • 调试总线状态时比逐位查标志更方便
  • 正常驱动流程优先用 GetFlagStatus/CheckEvent

17. I2C_SoftwareResetCmd

/**
 * @brief  执行 I2C 软件复位,清除内部状态机以从总线死锁或 AF 错误中恢复
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C软件复位的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_SoftwareResetCmd(I2C1, ENABLE);
 */
void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 典型流程:ENABLE 复位 → DISABLE 解除 → 重新 Init/Cmd
  • 用于 BERR、AF 等错误后状态机卡死
  • 复位期间外设不参与总线,需确保物理总线已空闲

18. I2C_NACKPositionConfig

/**
 * @brief  配置双缓冲接收时 NACK 的发送时机,配合 DMA 多字节接收使用
 * @param  I2Cx: 选择要配置的I2C外设,可以是I2C1或I2C2
 * @param  I2C_NACKPosition: 指定NACK位置
 * @retval
 * @example
 *     I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
 */
void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition);

功能说明:

  • Current:在当前字节接收完成后发 NACK
  • Next:在下一字节接收完成后发 NACK
  • 影响 DMA 接收最后一字节的 ACK/NACK 时序

19. I2C_SMBusAlertConfig

/**
 * @brief  驱动 SMBus Alert 引脚电平,用于 SMBus 主机向系统报告警报或响应警报
 * @param  I2Cx: 选择要配置的I2C外设,可以是I2C1或I2C2
 * @param  I2C_SMBusAlert: 指定SMBusAlert引脚电平
 * @retval
 * @example
 *     I2C_SMBusAlertConfig(I2C1, I2C_SMBusAlert_Low);
 */
void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert);

功能说明:

  • SMBus 设备故障时拉低 Alert 通知主机
  • 主机可拉低 Alert 发起 Alert Response Address 访问
  • 仅 SMBus 模式且硬件连接 Alert 引脚时有效

20. I2C_TransmitPEC

/**
 * @brief  控制是否在传输末尾附加 PEC 校验字节,用于 SMBus 数据完整性校验
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C PEC传输的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_TransmitPEC(I2C1, ENABLE);
 */
void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • ENABLE 后硬件在数据后自动发送 CRC-8 校验字节
  • 接收方可用 GetPEC 比对验证
  • SMBus 电池管理等协议常要求 PEC

21. I2C_PECPositionConfig

/**
 * @brief  选择 PEC 字节在当前还是下一数据位置发送/接收,配合双缓冲时序
 * @param  I2Cx: 选择要配置的I2C外设,可以是I2C1或I2C2
 * @param  I2C_PECPosition: 指定PEC位置
 * @retval
 * @example
 *     I2C_PECPositionConfig(I2C1, I2C_PECPosition_Current);
 */
void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition);

功能说明:

  • 与 NACKPosition 类似,控制 PEC 相对数据字节的时序
  • 多字节 SMBus 块读写时需正确配置
  • 配置错误会导致 PEC 错位校验失败

22. I2C_CalculatePEC

/**
 * @brief  打开/关闭硬件 PEC(CRC-8)自动计算,收发过程中实时累加校验值
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C PEC计算的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_CalculatePEC(I2C1, ENABLE);
 */
void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 使能后硬件对地址+数据流自动计算 PEC
  • 无需软件逐字节 CRC,降低 CPU 负担
  • 需配合 TransmitPEC 在帧末发送/接收校验字节

23. I2C_GetPEC

/**
 * @brief  读取硬件已计算的 PEC 值,用于发送前写入或接收后比对校验
 * @param  I2Cx: 选择要获取PEC值的I2C外设,可以是I2C1或I2C2
 * @retval PEC值
 * @example
 *     uint8_t pecValue = I2C_GetPEC(I2C1);
 */
uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);

功能说明:

  • 发送侧:取计算值作为最后一字节发出
  • 接收侧:与对端发来的 PEC 比较判断数据完整性
  • 需在 CalculatePEC 使能且传输完成后读取

24. I2C_ARPCmd

/**
 * @brief  打开/关闭 SMBus ARP(地址解析协议),支持动态分配从机地址
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C ARP的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_ARPCmd(I2C1, ENABLE);
 */
void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • ARP 允许 SMBus 主机为多个相同默认地址的设备分配唯一地址
  • 适用于热插拔、多相同类型从机场景
  • 需配合 SMBus 协议栈使用,标准 I2C 一般不需要

25. I2C_StretchClockCmd

/**
 * @brief  控制从机是否允许时钟延展(拉低 SCL 暂停主机),处理来不及响应的情况
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  NewState: I2C时钟延展的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_StretchClockCmd(I2C1, DISABLE);
 */
void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);

功能说明:

  • 从机接收数据过快时可延展 SCL 争取处理时间
  • DISABLE 后从机不能暂停时钟,响应必须及时
  • 某些实时主机不支持时钟延展,需按从机能力配置

26. I2C_FastModeDutyCycleConfig

/**
 * @brief  设置快速模式(400kHz)下 SCL 高低电平占空比,满足从机时序要求
 * @param  I2Cx: 选择要配置的I2C外设,可以是I2C1或I2C2
 * @param  I2C_DutyCycle: 指定快速模式占空比
 * @retval
 * @example
 *     I2C_FastModeDutyCycleConfig(I2C1, I2C_DutyCycle_2);
 */
void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle);

功能说明:

  • 400kHz 快速模式下 CCR 计算依赖占空比选择
  • DutyCycle_2(2:1)为常用默认;16:9 适配特定从机
  • 仅 ClockSpeed 大于 100kHz 时有效

27. I2C_CheckEvent

/**
 * @brief  轮询检查 I2C 是否进入指定事件状态(如 EV5/EV6),用于无中断的状态机驱动
 * @param  I2Cx: 选择要检查的I2C外设,可以是I2C1或I2C2
 * @param  I2C_EVENT: 指定要检查的事件
 * @retval 事件状态,SUCCESS或ERROR
 * @example
 *     if(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) == SUCCESS)
 *     {
 *         // 主机模式选择事件发生
 *     }
 */
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);

功能说明:

  • 一次判断 SR1+SR2 组合是否匹配预定义事件宏
  • 比单独查多个标志更简洁,适合轮询式主机/从机驱动
  • 超时场景需外层加计数或定时器避免死等

28. I2C_GetLastEvent

/**
 * @brief  读取 SR1 与 SR2 组合编码的当前事件值,供自定义状态机解析
 * @param  I2Cx: 选择要获取事件的I2C外设,可以是I2C1或I2C2
 * @retval 最后一个事件值
 * @example
 *     uint32_t lastEvent = I2C_GetLastEvent(I2C1);
 */
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx);

功能说明:

  • 返回值可与事件宏比较,或 switch 分支处理
  • 中断与轮询均可使用,灵活度高于 CheckEvent
  • 读取后部分标志需配合 ClearFlag 清除

29. I2C_GetFlagStatus

/**
 * @brief  查询单个 I2C 标志位(如 BUSY、TXE、ADDR),判断当前传输进度或错误
 * @param  I2Cx: 选择要检查的I2C外设,可以是I2C1或I2C2
 * @param  I2C_FLAG: 指定要检查的标志位
 * @retval 标志位状态,SET或RESET
 * @example
 *     if(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET)
 *     {
 *         // I2C总线忙
 *     }
 */
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);

功能说明:

  • 常用:BUSY 判断总线空闲、TXE/RXNE 控制收发节奏
  • AF/BERR 等错误标志也需在此检测
  • 比 CheckEvent 粒度更细,适合精细时序控制

30. I2C_ClearFlag

/**
 * @brief  清除指定 I2C 标志(如 ADDR、AF),避免重复触发或阻塞后续传输
 * @param  I2Cx: 选择要清除标志的I2C外设,可以是I2C1或I2C2
 * @param  I2C_FLAG: 指定要清除的标志位
 * @retval
 * @example
 *     I2C_ClearFlag(I2C1, I2C_FLAG_ADDR);
 */
void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);

功能说明:

  • 地址匹配 ADDR 标志需读 SR1/SR2 或调此函数清除
  • 错误标志 AF、BERR 清除后才能继续新事务
  • 部分标志硬件自动清除,以参考手册为准

31. I2C_ITConfig

/**
 * @brief  打开/关闭 I2C 中断源(事件/缓冲/错误),配合 NVIC 实现异步收发
 * @param  I2Cx: 选择要控制的I2C外设,可以是I2C1或I2C2
 * @param  I2C_IT: 指定要使能或失能的I2C中断源
 * @param  NewState: 指定I2C中断的新状态,可以是ENABLE或DISABLE
 * @retval
 * @example
 *     I2C_ITConfig(I2C1, I2C_IT_EVT, ENABLE);
 */
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);

功能说明:

  • EVT:START/ADDR/STOP 等状态变化
  • BUF:TXE/RXNE 数据就绪;ERR:AF/BERR 等
  • 中断驱动可减少轮询 CPU 占用,适合多字节传输

32. I2C_GetITStatus

/**
 * @brief  在中断服务程序中判断具体 I2C 中断源是否挂起
 * @param  I2Cx: 选择要检查的I2C外设,可以是I2C1或I2C2
 * @param  I2C_IT: 指定要检查的I2C中断源
 * @retval 中断状态,SET或RESET
 * @example
 *     if(I2C_GetITStatus(I2C1, I2C_IT_RXNE) == SET)
 *     {
 *         // 接收数据寄存器非空中断
 *     }
 */
ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);

功能说明:

  • 同时检查使能位与挂起位,避免误响应未使能中断
  • ISR 中按 IT 类型分支处理收发或错误
  • 与 GetFlagStatus 类似但面向中断上下文

33. I2C_ClearITPendingBit

/**
 * @brief  清除 I2C 中断挂起位,ISR 处理完毕后必须调用以免重复进中断
 * @param  I2Cx: 选择要清除中断的I2C外设,可以是I2C1或I2C2
 * @param  I2C_IT: 指定要清除的I2C中断待处理位
 * @retval
 * @example
 *     I2C_ClearITPendingBit(I2C1, I2C_IT_ADDR);
 */
void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);

功能说明:

  • 处理完 ADDR/RXNE/AF 等中断后清除对应挂起位
  • 某些标志需先读 DR 再清除,遵循参考手册顺序
  • 未清除会导致中断反复触发

使用示例

基本I2C配置示例

void I2C_Configuration(void)
{
    I2C_InitTypeDef I2C_InitStructure;
    
    // 使能I2C1时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    
    // 配置I2C1参数
    I2C_InitStructure.I2C_ClockSpeed = 100000;          // 100kHz
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x30;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);
}

I2C主机发送数据示例

void I2C_WriteData(uint8_t deviceAddr, uint8_t data)
{
    // 1. 发送START条件
    I2C_GenerateSTART(I2C1, ENABLE);
    
    // 2. 等待EV5事件(START条件发送完成)
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
    
    // 3. 发送从设备地址(写模式)
    I2C_Send7bitAddress(I2C1, deviceAddr, I2C_Direction_Transmitter);
    
    // 4. 等待EV6事件(地址发送完成并收到ACK)
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
    
    // 5. 发送数据
    I2C_SendData(I2C1, data);
    
    // 6. 等待EV8事件(数据发送完成)
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
    // 7. 发送STOP条件
    I2C_GenerateSTOP(I2C1, ENABLE);
}

I2C主机读取数据示例

uint8_t I2C_ReadData(uint8_t deviceAddr)
{
    uint8_t receivedData;
    
    // 1. 发送START条件
    I2C_GenerateSTART(I2C1, ENABLE);
    
    // 2. 等待EV5事件
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
    
    // 3. 发送从设备地址(读模式)
    I2C_Send7bitAddress(I2C1, deviceAddr, I2C_Direction_Receiver);
    
    // 4. 等待EV6事件
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    
    // 5. 失能ACK(准备接收最后一个字节)
    I2C_AcknowledgeConfig(I2C1, DISABLE);
    
    // 6. 等待EV7事件(数据接收完成)
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
    
    // 7. 读取数据
    receivedData = I2C_ReceiveData(I2C1);
    
    // 8. 发送STOP条件
    I2C_GenerateSTOP(I2C1, ENABLE);
    
    // 9. 重新使能ACK
    I2C_AcknowledgeConfig(I2C1, ENABLE);
    
    return receivedData;
}

注意事项

  1. 时钟配置:使用I2C前需要使能相应的APB1时钟
  2. GPIO配置:需要将GPIO引脚配置为开漏输出或复用功能
  3. 上拉电阻:I2C总线需要外部上拉电阻(通常4.7kΩ)
  4. 事件检查:在I2C通信过程中必须检查相应的事件状态
  5. 总线仲裁:多主机环境下要处理总线仲裁丢失的情况
  6. 错误处理:需要处理应答失败、总线错误等异常情况

总结

STM32F10x I2C标准库提供了完整的I2C通信配置和控制功能,通过合理使用这些函数和结构体,可以轻松实现与各种I2C设备的通信。掌握这些API的使用方法,对于开发基于STM32的嵌入式应用具有重要意义。