零基础STM32单片机编程入门(九)IIC总线详解及EEPROM实战含源码视频
文章目录
- 一.概要
- 二.IIC总线基本概念
- 1.总体特征
- 2.通讯流程
- 三.EEPROM介绍
- 1.M24C08基本介绍
- 2.向M24C08写一个字节时序图
- 3.从M24C08读一个字节时序图
- 四.GPIO模拟IIC驱动M24C08读写
- 五.CubeMX工程源代码下载
- 六.讲解视频链接地址
- 七.小结
一.概要
IIC(Inter-Integrated Circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。
二.IIC总线基本概念
I2C 总线,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。

1.总体特征

2.通讯流程



三.EEPROM介绍
EEPROM( Electrically Erasable Programmable Read Only Memory )全称是电可擦除可编程只读存储器,是非易失存储器,可以访问到每个字节,容量比较小。目前的EEPROM一般是IIC接口或者SPI接口的。
1.M24C08基本介绍
M24C08是ST公司(意法半导体公司)的串行接口的EEPROM存储芯片,它的容量是8K bit。

芯片功能描述:
M24C08系列支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器;数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式。
芯片特性介绍:
1.两线串行接口(SDA、SCL)
2.有用于硬件数据保护的写保护引脚
3.自定时写入周期(5毫秒),因为内部有页缓冲区,向M24C08写入数据之后,还需要等待M24C08将缓冲区数据写入到内部EEPROM区域
4.数据保存可达100年
5.100万次擦写周期
6.高数据传送速率为400KHz、低速100KHZ和IIC总线兼容
7.16字节页写缓冲区
这个缓冲区大小与芯片具体型号有关: 8字节页(1K、2K)、16字节页(4K、8K、16K)

M24C08的E2(3脚)一般接地,E1,E0是容量大点的EEPROM才有,这样M24C08这个器件,写操作时候的地址就是0xA0,读操作时候的地址是0xA1。
2.向M24C08写一个字节时序图
写操作过程中只有ACK是M24C08发出的,其他信号都是单片机发出的。

3.从M24C08读一个字节时序图
读操作过程中ACK跟返回的数据是M24C08发出的,其他信号都是单片机发出的。

四.GPIO模拟IIC驱动M24C08读写
硬件准备:
STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口,
STM32F103C8T6小系统板跟EEPROM模块连接:
板子G----模块GND
板子3.3–模块VCC
板子PB10—模块SCL
板子PB11—模块SDA

打开STM32CubeMX软件,新建工程

Part Number处输入STM32F103C8,再双击就创建新的工程

配置下载口引脚

配置外部晶振引脚

配置系统主频

配置工程文件名,保存路径,KEIL5工程输出方式

生成工程

用Keil5打开工程

添加代码


主要代码
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();//8M外部晶振,系统主频72M/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */EE_IIC_Init();//管脚初始化EE_EE_IIC_SendByteToSlave(0xA0,0x00,0x55);//0地址写入0x55HAL_Delay(10);//等待10msEE_IIC_ReadByteFromSlave(0xA0,0x00,&EEDATA);//从0地址读取内容存储到变量/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}#include "main.h"
#define EE_ADDR 0xa0
#define EE_SCL_PIN GPIO_PIN_10 //模拟IIC的SCL信号 1.修改引脚即可修改IIC接口
#define EE_SDA_PIN GPIO_PIN_11 //模拟IIC的SDA信号void EE_SDA_IN(void) //配置成输入 { GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_11;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
void EE_SDA_OUT(void)//配置成输出
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_11;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);}void EE_SCK_OUT(void) //配置成输出
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_10;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}#define EE_IIC_SCL(val) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10,val) //SCL 2.修改引脚即可修改IIC接口
#define EE_IIC_SDA(val) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11,val) //SDA unsigned char EE_READ_SDA(void)
{
return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11);
} /******************************************************************************
*函 数:void EE_IIC_Delay(void)
*功 能:IIC延时
*参 数:无
*返回值:无
*备 注: 移植时只需要将EE_IIC_Delay()换成自己的延时即可
*******************************************************************************/
void EE_IIC_Delay(uint8_t us)
{for(int i = 0; i < 20; i++) {__asm("NOP");//core bus 160M 情况下大概IIC速率 400K}}
/******************************************************************************
*函 数:void IIC_Init(void)
*功 能:IIC初始化
*参 数:无
*返回值:无
*备 注:无
*******************************************************************************/void EE_IIC_Init(void)
{ __HAL_RCC_GPIOB_CLK_ENABLE();EE_SCK_OUT();EE_SDA_OUT();EE_IIC_SCL(1);EE_IIC_SDA(1);}void EE_IIC_Start(void)
{EE_SDA_OUT(); //sda线输出 EE_IIC_SDA(1); EE_IIC_SCL(1);EE_IIC_Delay(4);EE_IIC_SDA(0); //START:when CLK is high,DATA change form high to low EE_IIC_Delay(4);EE_IIC_SCL(0); //钳住I2C总线,准备发送或接收数据
}void EE_IIC_Stop(void)
{EE_SDA_OUT(); //sda线输出EE_IIC_SCL(0);EE_IIC_SDA(0); //STOP:when CLK is high DATA change form low to highEE_IIC_Delay(4);EE_IIC_SCL(1); EE_IIC_SDA(1); //发送I2C总线结束信号EE_IIC_Delay(4);
}uint8_t EE_IIC_WaitAck(void)
{uint8_t ucErrTime=0;EE_SDA_IN(); //SDA设置为输入 (从机给一个低电平做为应答) EE_IIC_SDA(1);EE_IIC_Delay(1); EE_IIC_SCL(1);EE_IIC_Delay(1);; while(EE_READ_SDA()){ucErrTime++;if(ucErrTime>250){EE_IIC_Stop();return 1;}}EE_IIC_SCL(0); //时钟输出0 return 0;
} void EE_IIC_Ack(void)
{EE_IIC_SCL(0);EE_SDA_OUT();EE_IIC_SDA(0);EE_IIC_Delay(1);EE_IIC_SCL(1);EE_IIC_Delay(2);EE_IIC_SCL(0);
}void EE_IIC_NAck(void)
{EE_IIC_SCL(0);EE_SDA_OUT();EE_IIC_SDA(1);EE_IIC_Delay(1);EE_IIC_SCL(1);EE_IIC_Delay(1);EE_IIC_SCL(0);
} void EE_IIC_SendByte(uint8_t data)
{ uint8_t t; EE_SDA_OUT(); EE_IIC_SCL(0); //拉低时钟开始数据传输for(t=0;t<8;t++){ EE_IIC_SDA((data&0x80)>>7);EE_IIC_Delay(1); EE_IIC_SCL(1);data<<=1;EE_IIC_Delay(1);EE_IIC_SCL(0); }EE_IIC_Delay(1);
} uint8_t EE_IIC_ReadByte(uint8_t ack)
{uint8_t i,receive=0;EE_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据for(i=0;i<8;i++ ){EE_IIC_SCL(0); EE_IIC_Delay(1);EE_IIC_SCL(1);receive<<=1;if(EE_READ_SDA())receive++; //从机发送的电平EE_IIC_Delay(1); } if(ack)EE_IIC_Ack(); //发送ACK elseEE_IIC_NAck(); //发送nACK return receive;
}uint8_t EE_IIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf)
{EE_IIC_Start(); EE_IIC_SendByte(I2C_Addr); //发送从机地址if(EE_IIC_WaitAck()) //如果从机未应答则数据发送失败{EE_IIC_Stop();return 1;}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck(); EE_IIC_Start();EE_IIC_SendByte(I2C_Addr+1); //进入接收模式 EE_IIC_WaitAck();*buf=EE_IIC_ReadByte(0); EE_IIC_Stop(); //产生一个停止条件return 0;
}uint8_t EE_EE_IIC_SendByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{EE_IIC_Start();EE_IIC_SendByte(I2C_Addr); //发送从机地址if(EE_IIC_WaitAck()){EE_IIC_Stop();return 1; //从机地址写入失败}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck(); EE_IIC_SendByte(data); if(EE_IIC_WaitAck()){EE_IIC_Stop(); return 1; //数据写入失败}EE_IIC_Stop(); //产生一个停止条件return 0;
}
五.CubeMX工程源代码下载
链接:https://pan.baidu.com/s/1MMYww6IgUNa3wPaN-pWqdw
提取码:d39f
如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行
六.讲解视频链接地址
IIC总线讲解
七.小结
学会使用模拟IIC,能适应各种平台,不管是STM32的单片机,还是其他牌子的单片机,都能很快实现对EEPROM等IIC总线的设备进行数据读写。
相关文章:
零基础STM32单片机编程入门(九)IIC总线详解及EEPROM实战含源码视频
文章目录 一.概要二.IIC总线基本概念1.总体特征2.通讯流程 三.EEPROM介绍1.M24C08基本介绍2.向M24C08写一个字节时序图3.从M24C08读一个字节时序图 四.GPIO模拟IIC驱动M24C08读写五.CubeMX工程源代码下载六.讲解视频链接地址七.小结 一.概要 IIC(Inter-Integrated …...
数据库的操作
【一】库的增删改查 【0】导入数据文件 source D:\bjpowernode.sql 【1】创建数据库 语法: create database [if not exists] 数据库名 [character set 编码字符集]; create databases db1; # 设置库的默认编码 create databases db1 charsetgbk; 【2】查看数据…...
常见的认证方式
认证机制是一种用户确定用户身份或者权限的安全措施,比如用来验证某个用户是否有权限访问一个资源,如果认证通过,用户就可以成功访问,反之则会访问失败 常见的认证方式有四种,分别是 Basic、Digest、OAuth 和 Bearer …...
DolphinScheduler部署安装or基础介绍(一)
DolphinScheduler概述 Apache DolphinScheduler是一个分布式、易扩展的可视化DAG工作流任务调度平台。致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用 DolphinScheduler核心架构 DolphinScheduler的主要角色如下: Ma…...
Failed building wheel for pyaudio Running setup.py clean for pyaudio
从错误信息来看,问题出在 pyaudio 包的构建过程中。具体来说,缺少 portaudio.h 头文件,这通常是因为系统上没有安装 portaudio 库。 以下是解决此问题的步骤: 安装系统依赖: 在大多数基于 Debian 的系统(如…...
【ARMv8/v9 GIC- 700 系列 1 -- Programmers model for GIC-700】
请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC-700 Programmers model寄存器实现和访问模式接口宽度和数据格式访问类型安全寄存器访问地址映射和页面GIC-700 Register map pagesSummaryGIC-700 Programmers model GIC-700是ARM的一种通用中断控制器,它遵循GICv3和GICv4架构…...
exel带单位求和,统计元素个数
如果exel表格中,如果数据有单位,无法直接用 自动求和 直接求和。如下图所示,求和结果为0,显然不是我们想要的。 用下面的公式求和,单位不是“个”的时候记得替换单位。统计范围不是“C1:C7”也记得换一下啊!…...
JavaScript里方括号[]的使用
我们知道可用方括号来表示数组或者JSON对象的属性值,其实在特定场合,方括号还有妙用的。 比如我有数据源是一组JSON,其中有一个属性是时间字符串,我想对时间的小时、星期、日、月分别进行处理。每条JSON都各自生成一条新的JSON&am…...
俯卧撑计数器(Python)
通过 MediaPipe 检测人体姿态,计算俯卧撑角度和计数,并在图像上进行可视化展示 需要有cv2库和mediapipe库 mediapipe库: MediaPipe是Google开源的机器学习框架,用于构建实时音频、视频和多媒体处理应用程序。它提供了一组预训练的…...
UVA12342 Tax Calculator 题解
题目传送门 题目大意 题目描述 某国所得税计算十分复杂。该国政府指定你制作一个自动计算所得税的程序。以下是该国计算所得税的规则: 所得税免征额为 180000 180000 180000 元。应纳税额中不超过 300000 300000 300000 元的所得额,按 10 % 10\% …...
WebKit中Websockets的全面支持:实现高效实时通信
WebKit中Websockets的全面支持:实现高效实时通信 Websockets是一种网络通信协议,它允许在单个TCP连接上进行全双工通信,从而实现服务器与客户端之间的实时数据交换。WebKit作为许多流行浏览器的底层引擎,对Websockets提供了全面的…...
微信小程序的智慧物流平台-计算机毕业设计源码49796
目 录 摘要 1 绪论 1.1 研究背景 1.2 研究意义 1.3研究方法 1.4开发技术 1.4.1 微信开发者工具 1.4.2 Node.JS框架 1.4.3 MySQL数据库 1.5论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 用户登录流程 2.2.2 数据删除流程 2.3 系统功能分…...
旅游 | 西岳华山
得到了再失去, 总比从来没有得到更伤人。 ——胡赛尼《追风筝的人》 目录 旅游 | 西岳华山00 | 旅游导图01 | 旅游路线1.1 北上西下(徒步)1.2 北上西下(索道)1.3 西上北下(索道)1.4 西上西下&am…...
如何优化Java中的内存占用?
如何优化Java中的内存占用? 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 1. 理解Java内存管理机制 Java的内存管理主要由JVM负责,开发人员在编写代码时需要注意如何有效地…...
2024这三家上海闵行装修公司,值得一看
在繁华的上海闵行区,随着居民对生活品质追求的提升,越来越多人开始重视居住环境的打造。然而,面对众多装修公司的选择,不少消费者往往感到迷茫和困惑。今天,我们就来揭晓闵行区口碑与实力兼备的三家装修公司。 1、首先…...
K8S学习教程(三):在PetaExpress KubeSphere 容器部署 Wiki 系统 wiki.js 并启用中文全文检索
背景 wiki.js 是非常优秀的开源 Wiki 系统,尽管在与 xwiki 功能相比 ,还不算完善,但也在不断进步。 常用的功能还是比较实用的,如:Wiki 写 作、分享、权限管理功能还是非常实用的,UI 设计非常的漂亮&#x…...
服务器该如何抵御CC攻击
CC攻击也是分布式拒绝服务攻击的一种类型,同时CC攻击也属于网络流量攻击,但是CC攻击主要是用来攻击网站页面的,向着目标网络服务器发送一些请求,以此来消耗目标网络服务器的资源,导致目标服务器无法响应正常请求&#…...
关于centos7自带的nginx1.20.1开启https后,XP系统的IE6和IE8无法显示网页的问题
CentOS7自带的nginx-1.20.1是支持HTTP/2和TLS1.3的。 软件包名称:nginx-1.20.1-10.el7.x86_64 CentOS7默认开启了HTTP/2,但没有开启TLS1.3,以及IE6和IE8的https访问。 开启方法: ssl_ciphers HIGH:!aNULL:!MD5;改为ssl_ciphers…...
Zotero软件翻译插件Translate for Zotero的API接入方法--百度垂直领域翻译
首先注册通用文本翻译API的token:百度翻译开放平台 (baidu.com)(可以免费认证 升级为高级版) 之后点击管理控制台,选择总览右侧最下方可以看到个人的id和密码 点击文档与支持, 在这里可以选择领域。 支持传入值描述支持语言方向…...
python实现接口自动化
代码实现自动化相关理论 代码编写脚本和工具实现脚本区别是啥? 代码: 优点:代码灵活方便缺点:学习成本高 工具: 优点:易上手缺点:灵活度低,有局限性。 总结: 功能脚本:工…...
ThinkPad开机嘀嘀响或报2100/2110错误?可能是硬盘松了!自己动手检测与修复指南
ThinkPad开机嘀嘀响或报2100/2110错误?三步排查硬盘接触不良问题ThinkPad用户对那个标志性的开机"嘀嘀"声再熟悉不过——正常情况下它意味着系统自检通过。但当这个声音变成急促的报警音,伴随屏幕上出现"2100 Detection error"或&qu…...
Kerberos身份认证原理与实战排错指南
1. 为什么今天还要花时间搞懂 Kerberos?——一个被低估的“老协议”正在悄悄支撑着你的日常你每天登录公司内网查邮件、访问财务系统提交报销、用 Jenkins 构建代码、甚至在 Windows 域环境中打开一台同事的共享文件夹……这些看似顺滑的操作背后,大概率…...
手把手教你为WCH CH582移植CherryUSB主机栈(基于RT-Thread,含中断优化)
基于RT-Thread的WCH CH582 USB主机协议栈深度移植指南在嵌入式开发领域,USB主机功能的实现往往意味着设备能够直接连接各类USB外设,从简单的键盘鼠标到复杂的存储设备。对于使用WCH CH582这类RISC-V内核MCU的开发者而言,原厂SDK提供的USB主机…...
2026 西安 AI 问答曝光搭建技术解析:GEO 知识图谱 + 深度测评
随着大语言模型技术的快速普及,AI 搜索已经成为用户获取企业信息、商家服务的核心入口。根据中国互联网信息中心 2026 年发布的《中国人工智能搜索发展报告》显示,2025 年国内 AI 搜索用户规模突破 8.2 亿,日均搜索请求超过 20 亿次ÿ…...
Gofile批量下载自动化工具:5步实现高效文件管理解决方案
Gofile批量下载自动化工具:5步实现高效文件管理解决方案 【免费下载链接】gofile-downloader Download files from https://gofile.io 项目地址: https://gitcode.com/gh_mirrors/go/gofile-downloader 在当今数字化工作环境中,技术团队经常需要从…...
碧蓝航线自动化脚本终极指南:3小时学会全自动游戏管理
碧蓝航线自动化脚本终极指南:3小时学会全自动游戏管理 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研,全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 还在为碧蓝…...
告别数据饥荒:用PyTorch手把手实现原型网络(Prototypical Networks)做电影评论情感分类
告别数据饥荒:用PyTorch手把手实现原型网络做电影评论情感分类 在自然语言处理领域,情感分析一直是热门研究方向,但现实中的开发者常面临一个尴尬困境:标注数据太少。传统深度学习方法动辄需要成千上万的标注样本,而实…...
taotoken如何帮助ubuntu开发者应对大模型api的频繁更新与版本迭代
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Taotoken如何帮助Ubuntu开发者应对大模型API的频繁更新与版本迭代 对于在Ubuntu环境下进行开发的工程师而言,大模型API…...
PCL 基于强度的双边滤波【2026最新版】
目录 一、算法原理 1、计算步骤 2、算法源码 3、函数解析 4、参考文献 二、代码实现 三、结果展示 四、滤波后未发生变化的原因 五、解决办法 六、结果展示 七、相关链接 本文由CSDN点云侠原创,博客长期更新,本文最近一次更新时间为:2026年5月24日。 一、算法原理 1、计算…...
保姆级教程:在Windows 10上用QEMU+Kylin搭建可内外网访问的完整开发环境
在Windows 10上构建QEMUKylin全功能开发环境的终极指南当开发者需要在本地快速搭建一个隔离的国产操作系统开发环境时,QEMU虚拟化方案配合银河麒麟系统能提供高度灵活的沙箱体验。本文将手把手带你完成从零配置到内外网联通的完整工作流,涵盖虚拟化环境部…...
