news 2026/3/14 15:28:52

简单理解:软件 I2C 和硬件 I2C 的区别

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单理解:软件 I2C 和硬件 I2C 的区别

通过代码直观看到软件 I2C 和硬件 I2C 的区别,这个思路特别好!我以 STM32F103 为例,分别给出驱动同一个 I2C 设备(比如温湿度传感器)的核心代码,你对比着看就能立刻明白差异。

一、软件 I2C 核心代码(模拟时序)

软件 I2C 完全用 GPIO 口模拟 SCL/SDA 的高低电平变化,所有时序都靠代码手动控制:

#include "stm32f10x.h" // 定义软件I2C引脚(可任意选GPIO) #define I2C_SCL_PIN GPIO_Pin_0 #define I2C_SDA_PIN GPIO_Pin_1 #define I2C_GPIO_PORT GPIOB #define I2C_GPIO_CLK RCC_APB2Periph_GPIOB // 引脚电平控制(核心:手动改电平) #define SCL_HIGH() GPIO_SetBits(I2C_GPIO_PORT, I2C_SCL_PIN) #define SCL_LOW() GPIO_ResetBits(I2C_GPIO_PORT, I2C_SCL_PIN) #define SDA_HIGH() GPIO_SetBits(I2C_GPIO_PORT, I2C_SDA_PIN) #define SDA_LOW() GPIO_ResetBits(I2C_GPIO_PORT, I2C_SDA_PIN) #define SDA_READ() GPIO_ReadInputDataBit(I2C_GPIO_PORT, I2C_SDA_PIN) // 软件I2C初始化(就是配置GPIO为推挽输出) void Soft_I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(I2C_GPIO_CLK, ENABLE); // SCL引脚配置 GPIO_InitStruct.GPIO_Pin = I2C_SCL_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStruct); // SDA引脚配置 GPIO_InitStruct.GPIO_Pin = I2C_SDA_PIN; GPIO_Init(I2C_GPIO_PORT, &GPIO_InitStruct); // 初始电平拉高 SCL_HIGH(); SDA_HIGH(); } // 软件I2C起始信号(手动模拟时序) void Soft_I2C_Start(void) { SDA_HIGH(); SCL_HIGH(); delay_us(2); // 必须加延时保证时序,否则通信失败 SDA_LOW(); delay_us(2); SCL_LOW(); } // 软件I2C发送一个字节(每一位都要手动控制时钟) uint8_t Soft_I2C_Send_Byte(uint8_t data) { uint8_t i; for(i=0; i<8; i++) // 逐位发送 { if(data & 0x80) SDA_HIGH(); // 最高位先发送 else SDA_LOW(); data <<= 1; SCL_HIGH(); // 时钟拉高,从机读取数据 delay_us(2); SCL_LOW(); // 时钟拉低,准备下一位 delay_us(2); } // 等待从机应答 SDA_HIGH(); SCL_HIGH(); delay_us(2); uint8_t ack = SDA_READ(); SCL_LOW(); return ack; } // 其他停止、接收字节等函数都是类似的手动时序控制...

二、硬件 I2C 核心代码(外设自动处理)

硬件 I2C 只需要配置寄存器,剩下的时序由硬件自动完成:

#include "stm32f10x.h" #define I2Cx I2C1 #define I2C_CLK RCC_APB1Periph_I2C1 #define I2C_GPIO_CLK RCC_APB2Periph_GPIOB #define I2C_SCL_PIN GPIO_Pin_6 #define I2C_SDA_PIN GPIO_Pin_7 // 硬件I2C初始化(配置外设参数,引脚是固定的) void Hard_I2C_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct; // 1. 使能时钟 RCC_APB1PeriphClockCmd(I2C_CLK, ENABLE); RCC_APB2PeriphClockCmd(I2C_GPIO_CLK, ENABLE); // 2. 配置引脚为复用开漏输出(硬件I2C必须用固定引脚+复用模式) 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(GPIOB, &GPIO_InitStruct); // 3. 配置I2C外设参数 I2C_DeInit(I2Cx); I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; I2C_InitStruct.I2C_OwnAddress1 = 0x00; // 主机模式,自己的地址随便设 I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_InitStruct.I2C_ClockSpeed = 400000; // 400KHz高速模式 I2C_Cmd(I2Cx, ENABLE); I2C_Init(I2Cx, &I2C_InitStruct); } // 硬件I2C发送一个字节(调用外设函数,不用管时序) void Hard_I2C_Send_Byte(uint8_t addr, uint8_t data) { // 1. 等待I2C总线空闲 while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY)); // 2. 发送起始信号(硬件自动生成时序) I2C_GenerateSTART(I2Cx, ENABLE); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT)); // 3. 发送设备地址(硬件自动处理时钟和应答) I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 4. 发送数据(硬件自动移位,不用逐位控制) I2C_SendData(I2Cx, data); while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 5. 发送停止信号 I2C_GenerateSTOP(I2Cx, ENABLE); }

三、核心区别一眼看明白

对比项软件 I2C硬件 I2C
引脚控制任意 GPIO,手动改高低电平固定引脚,复用模式,硬件自动控制
时序实现靠 delay_us () 和循环逐位模拟硬件逻辑自动生成,无需手动延时
CPU 占用高(全程要 CPU 盯着)低(配置完 CPU 可干别的)
代码复杂度简单(直接操作 GPIO)稍复杂(配置外设寄存器)
灵活性极高(可自定义时序)低(引脚 / 时序固定)

总结

  1. 软件 I2C:像你手动掰开关控制电路,代码直观、引脚随便选,但要自己控制每一步时序,CPU 不能干别的;
  2. 硬件 I2C:像你给机器人下指令,只需要告诉它 “发什么数据”,剩下的由硬件自动完成,CPU 解放出来,但必须用固定引脚;
  3. 新手做简单项目(比如读单个传感器)选软件 I2C 更易上手,需要高频通信 / 多设备时选硬件 I2C 更稳定。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/10 21:06:01

量化评估:GEO人才六大核心能力的科学测度体系

引言&#xff1a;从定性描述到量化测度的能力评估革命在地理空间智能与AI搜索深度融合的时代&#xff0c;对GEO人才能力的评估已不能再依赖传统的学历认证或经验年限等粗放指标。如何科学、客观、可操作地量化评估前文所述的六大核心能力维度&#xff0c;成为教育机构、企业和行…

作者头像 李华
网站建设 2026/3/4 11:31:22

漫剧制作智能体系统设计与实现

漫剧制作智能体系统设计与实现 摘要 本文介绍了一个基于Python的漫剧制作智能体系统的设计与实现。该系统整合了剧本生成、角色设计、场景构建、分镜制作和动画生成等多个模块,利用人工智能技术实现漫剧创作的自动化与智能化。系统采用模块化架构设计,支持从创意到成品的全…

作者头像 李华
网站建设 2026/2/28 19:32:14

北大与清华联手突破:机器人实现专业级精准操作能力

这项由北京大学与清华大学合作的研究团队在2025年12月发表的最新研究成果&#xff0c;为解决机器人在复杂环境中的"笨拙"问题提供了全新思路。研究论文《DiG-Flow: Discrepancy-Guided Flow Matching for Robust VLA Models》发表在顶级学术期刊上&#xff0c;感兴趣…

作者头像 李华
网站建设 2026/3/14 4:01:12

北京大学研究团队:音视频联合训练提升AI多模态理解力

北京大学计算机学院的吴建宗团队联合阿里巴巴集团&#xff0c;在2025年12月发表了一项颠覆性的研究成果。这项名为"Does Hearing Help Seeing? Investigating Audio–Video Joint Denoising for Video Generation"的研究首次系统性地证明了一个令人惊奇的发现&#…

作者头像 李华
网站建设 2026/3/4 19:37:01

基于FPGA的DDS信号发生器:探索数字信号生成的奇妙之旅

基于FPGA的DDS信号发生器任意信号发生器&#xff0c;实物VerilogVHDL 本设计是在FPGA开发板上实现一个DDS信号发生器&#xff0c;输出波形有正弦波、方波、三角波和锯齿波等&#xff0c;输出波形频率范围0到20MHZ可调&#xff0c;波形最大幅度在0到5V之间可调&#xff0c;相位也…

作者头像 李华