news 2026/6/10 12:56:25

简单理解:软件 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/6/10 9:26:07

算法题 单调数列

单调数列 问题描述 如果数组 nums 是单调递增或单调递减的&#xff0c;那么它是单调的。 如果对于所有 i < j&#xff0c;nums[i] < nums[j]&#xff0c;那么数组 nums 是单调递增的。 如果对于所有 i < j&#xff0c;nums[i] > nums[j]&#xff0c;那么数组 nums …

作者头像 李华
网站建设 2026/6/10 9:23:33

为什么 hatch 和 pipenv 在 PyCharm 里“行为异常”?——EPGF 架构下的工具真实定位与责任边界(认知纠偏篇)

【笔记】PyCharm 2025.2 EAP 创建 Poetry 和 Hatch 环境的踩坑实录与反馈 命令行创建项目本地的 hatch 环境及工具本地化实战演示——基于《Python 多版本与开发环境治理架构设计》的最佳实践 Anaconda 全环境工具链 路径树管理 和 环境创建 指南&#xff08;Poetry、Pipenv、v…

作者头像 李华
网站建设 2026/6/10 9:26:15

通过 HeidiSQL 连接 CentOS 7 中的 MySQL 5.7

通过 HeidiSQL 连接 CentOS 7 中的 MySQL 5.7 本教程将指导如何使用 HeidiSQL 客户端工具连接到已安装在 CentOS 7 服务器&#xff08;虚拟机、物理机或云服务器&#xff09;中的 MySQL 5.7 数据库。 软件版本 本文基于以下软件版本进行操作演示。 操作系统: CentOS 7.9MyS…

作者头像 李华
网站建设 2026/6/10 11:57:47

AI产学研实训平台:让技术学习“真刀真枪”不脱节

高校里学AI&#xff0c;课本是几年前的案例&#xff0c;实验数据是虚拟的&#xff1b;企业招AI人才&#xff0c;新人上手要3个月适应&#xff1b;高校的科研成果&#xff0c;躺在论文里难落地——这是AI领域的“三方痛点”。而AI产学研一体化实训平台&#xff0c;就像一座“技术…

作者头像 李华
网站建设 2026/5/30 16:16:54

香港科技大学:让AI摄像师精准控制视角,深度信息成为关键武器

这项由香港科技大学&#xff08;广州&#xff09;张洪飞、陈康昊等研究团队完成的突破性研究&#xff0c;发表于2025年的计算机视觉与模式识别会议&#xff08;CVPR&#xff09;&#xff0c;论文编号为arXiv:2511.23127v2。研究团队还包括来自复旦大学、深圳大学等多所知名学府…

作者头像 李华
网站建设 2026/6/10 11:30:00

中科院突破:虚拟仿真实现自动驾驶真车驾驶训练

这项由中国科学院自动化研究所的田浩晨领导的研究团队&#xff0c;联合香港大学和小米汽车等机构完成的研究发表于2025年11月的arXiv预印本平台&#xff0c;论文编号为arXiv:2511.23369v1。对这项突破性研究感兴趣的读者可以通过该编号查询完整论文内容。 想象这样一个场景&…

作者头像 李华