news 2026/9/12 10:13:22

简单理解:软件 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/9/9 6:42:17

中科大团队突破性解决视觉语言动作模型的视野局限

这项由中国人民大学、北京大学、香港中文大学联合开展的研究发表于2024年11月&#xff0c;论文编号为arXiv:2511.19433v1。研究团队由董靖、王钢、刘佳琪、唐维亮、孙泽龙、姚云超、魏振宇、刘云辉、陆志武、丁明宇等学者组成&#xff0c;他们首次系统性地解决了视觉语言动作模…

作者头像 李华
网站建设 2026/9/2 23:17:14

浙江大学等机构联合开发ViSAudio,让无声视频秒变立体声大片

如果你曾经被电影院里震撼的音效深深吸引&#xff0c;比如《阿凡达》中飞机从左边飞到右边时那种立体声效果&#xff0c;或是《泰坦尼克号》中海浪声从四面八方涌来的沉浸感&#xff0c;那你一定会对这项最新研究感到惊喜。由浙江大学、上海人工智能实验室、上海交通大学、斯坦…

作者头像 李华
网站建设 2026/9/6 7:57:52

KAIST团队破解长视频理解难题:WorldMM让AI拥有“超级记忆力“

想象一下&#xff0c;你能记住一周前某个下午朋友随口说过的话&#xff0c;或者准确回忆起三天前在某个地点做过的事情。对人类来说&#xff0c;这样的记忆能力已经相当不错&#xff0c;但对于人工智能来说&#xff0c;理解和记忆长达几小时甚至几天的视频内容&#xff0c;一直…

作者头像 李华
网站建设 2026/9/7 6:46:51

springboot+vue的二手交易平台_4682y024

目录系统架构核心功能模块技术亮点扩展性与优化开发技术核心代码参考示例1.建立用户稀疏矩阵&#xff0c;用于用户相似度计算【相似度矩阵】2.计算目标用户与其他用户的相似度总结源码文档获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;系统架构…

作者头像 李华
网站建设 2026/9/7 15:31:50

VisionPro二开之加载ToolBlock

VisionPro二开之加载ToolBlock 一 设置x64平台二 添加VP引用 Cognex.VisionPro.Controls.dll Cognex.VisionPro.ToolGroup.Controls.dll三 添加显示控件添加控件Dock填充Fill

作者头像 李华