在 51 单片机(8051)嵌入式系统开发中,RAM 通常用于程序运行过程中的临时数据保存,而 EEPROM 则可以用于保存需要掉电保持的重要参数,例如设备配置、校准数据、用户参数以及系统运行状态等。
HRTOS 4.0 Driver Library 提供了独立的 06_Storage 存储设备驱动模块 ,目前主要针对常用的 24C02 EEPROM,并提供底层软件 I²C 通信实现。
本文将介绍 HRTOS 4.0 06_Storage 模块的整体结构、24C02 EEPROM 驱动、软件 I²C 实现、API 接口、硬件连接以及实际使用方法。
通过该模块,可以在 51 单片机实时操作系统环境下更加方便地实现 EEPROM 数据存储功能。
一、HRTOS 4.0 06_Storage 模块概述
06_Storage 是 HRTOS Driver Library 中面向存储设备的驱动模块。
当前主要支持:
-
24C02 EEPROM
-
软件模拟 I²C 通信
公共头文件:
#include "HRTOS_Storage.h"
驱动实现依赖 HRTOS 硬件抽象层:
#include "hrtos_hal.h"
I²C 延时使用 8051 编译环境提供的:
#include <intrins.h>
并通过 _nop_() 实现基础时序延时。
当前模块主要由两部分组成:
06_Storage
│
└── EEPROM
│
└── EEPROM-IIC
├── 24C02 EEPROM 驱动
└── 软件 I²C 底层实现
二、24C02 EEPROM 简介
24C02 是嵌入式系统中非常常见的串行 EEPROM 器件。
其存储容量为:
2Kbit = 256 Byte
内部地址范围:
0x00 ~ 0xFF
因此可以通过一个 8 位地址访问整个 EEPROM 存储空间。
在 51 单片机应用中,24C02 可以用于保存:
-
系统配置参数
-
用户设置
-
设备编号
-
校准参数
-
运行参数
-
掉电保存数据
HRTOS 4.0 当前提供的是单字节读写驱动。
三、24C02 文件组成
当前 EEPROM 驱动目录:
EEPROM/EEPROM-IIC/
├── 24c02_read.c
├── 24c02_write.c
├── i2c.c
├── i2c_delay.c
├── i2c_read_byte.c
├── i2c_start.c
├── i2c_stop.c
└── i2c_write_byte.c
其中:
24C02 驱动
24c02_read.c
24c02_write.c
负责实现 EEPROM 的上层读写操作。
I²C 底层
i2c_delay.c
i2c_read_byte.c
i2c_start.c
i2c_stop.c
i2c_write_byte.c
负责软件模拟 I²C 总线通信。
i2c.c 当前主要用于头文件引用,本身没有实际功能实现。
这种结构将 EEPROM 操作和 I²C 总线操作进行了分层。
四、24C02 硬件连接
当前 24C02 EEPROM 使用软件 I²C。
引脚定义:
sbit EEPROM_SCL = P2^1;
sbit EEPROM_SDA = P2^0;
对应关系:
| 信号 | 51 单片机引脚 | 功能 |
|---|---|---|
| SDA | P2.0 | I²C 数据 |
| SCL | P2.1 | I²C 时钟 |
因此硬件连接为:
24C02 SDA ─── P2.0
24C02 SCL ─── P2.1
同时需要注意 I²C 总线的电气特性。
SDA 和 SCL 通常需要外部上拉电阻,例如:
4.7kΩ ~ 10kΩ
当前驱动没有实现内部上拉,因此实际硬件电路需要提供合适的外部上拉。
五、24C02 地址空间
24C02 总容量为:
2Kbit
换算:
2Kbit ÷ 8 = 256 Byte
所以内部存储地址:
0x00 ~ 0xFF
也就是:
0 ~ 255
驱动接口使用:
unsigned char
作为 EEPROM 内部地址类型。
例如:
eeprom_24c02_write(0x10, 0x55);
表示向 EEPROM 内部地址 0x10 写入 0x55。
六、24C02 I²C 器件地址
当前驱动使用固定的 24C02 器件地址:
写地址:0xA0
读地址:0xA1
二进制表示:
0xA0 = 1010 0000
0xA1 = 1010 0001
其中最低位用于表示读写方向。
当前驱动按照固定地址实现,因此应用层不需要额外配置器件地址。
需要注意,这里所说的 0xA0/0xA1 是驱动当前使用的 8 位 I²C 地址形式,并不是通常所说的 7 位从机地址表示方式。
七、24C02 写入驱动
7.1 eeprom_24c02_write()
函数原型:
void eeprom_24c02_write(unsigned char addr, unsigned char dat);
功能:
向指定的 EEPROM 地址写入一个字节。
参数:
addr:EEPROM 地址,0x00~0xFF
dat :写入数据,0x00~0xFF
基本通信过程:
I²C START
↓
发送 0xA0
↓
发送 EEPROM 内部地址
↓
发送数据
↓
I²C STOP
↓
等待 EEPROM 写周期
例如:
eeprom_24c02_write(0x10, 0x55);
表示:
EEPROM[0x10] = 0x55
八、24C02 读取驱动
8.1 eeprom_24c02_read()
函数原型:
unsigned char eeprom_24c02_read(unsigned char addr);
功能:
读取 EEPROM 指定地址中的一个字节。
参数:
addr:EEPROM 地址,0x00~0xFF
返回:
0x00~0xFF
读取过程采用随机读取方式:
I²C START
↓
发送写地址 0xA0
↓
发送 EEPROM 内部地址
↓
重复 START
↓
发送读地址 0xA1
↓
读取一个字节
↓
发送 NACK
↓
I²C STOP
例如:
unsigned char data;
data = eeprom_24c02_read(0x10);
即可读取 EEPROM 地址 0x10 中保存的数据。
九、24C02 完整读写示例
下面是一个简单的 EEPROM 数据保存与读取示例:
#include "HRTOS_Storage.h"
void main(void)
{
unsigned char data;
// 写入数据
eeprom_24c02_write(0x00, 0x12);
eeprom_24c02_write(0x01, 0x34);
eeprom_24c02_write(0x02, 0x56);
eeprom_24c02_write(0x03, 0x78);
// 等待 EEPROM 写周期
os_delay_ms(10);
// 读取数据
data = eeprom_24c02_read(0x00);
data = eeprom_24c02_read(0x01);
data = eeprom_24c02_read(0x02);
data = eeprom_24c02_read(0x03);
while(1)
{
// 主循环
}
}
实际应用中可以根据需要,将读取出来的数据进一步交给 HRTOS 任务进行处理。
例如:
EEPROM
↓
读取配置
↓
HRTOS 任务
↓
应用逻辑
↓
控制设备
这样 EEPROM 就可以作为系统参数的非易失性存储空间。
十、软件 I²C 底层实现
24C02 驱动的底层通信采用软件模拟 I²C。
也就是说,驱动并没有依赖单片机专用 I²C 外设,而是直接通过 GPIO 控制:
SDA
SCL
实现 I²C 总线时序。
这对于一些没有硬件 I²C 外设的 51 单片机尤其方便。
十一、I²C 延时
当前 I²C 延时函数:
eeprom_delay();
底层通过 _nop_() 实现:
_nop_();
_nop_();
因此实际延时时间与:
-
单片机系统时钟
-
编译器
-
指令执行周期
等因素有关。
软件 I²C 的实际通信速度也会受到这一延时函数影响。
因此当前驱动的 I²C 时钟频率并不是通过一个固定的硬件分频寄存器产生,而是由软件时序决定。
十二、I²C 起始条件
内部函数:
eeprom_i2c_start();
负责产生 I²C START 条件。
基本时序:
SDA = 1
↓
延时
↓
SCL = 1
↓
延时
↓
SDA = 0
↓
延时
↓
SCL = 0
START 条件的核心就是:
在 SCL 保持高电平时,让 SDA 从高电平变为低电平。
随后总线进入数据传输状态。
十三、I²C 停止条件
内部函数:
eeprom_i2c_stop();
负责产生 STOP 条件。
基本过程:
SDA = 0
↓
延时
↓
SCL = 1
↓
延时
↓
SDA = 1
即:
在 SCL 为高电平期间,让 SDA 从低电平变为高电平。
这表示当前 I²C 通信结束。
十四、I²C 字节写入
内部函数:
unsigned char eeprom_i2c_write_byte(unsigned char dat);
用于向 I²C 总线发送一个字节。
数据采用:
MSB First
即最高位首先发送。
每一位数据大致经过:
SDA = 数据位
↓
延时
↓
SCL = 1
↓
延时
↓
SCL = 0
↓
延时
发送完 8 位数据之后,释放 SDA,并进入 ACK 检测阶段。
十五、I²C ACK 检测
当前 I²C 底层实现包含 ACK 检测。
发送一个字节之后:
释放 SDA
↓
SCL = 1
↓
读取 SDA
如果:
SDA = 0
表示从设备返回 ACK。
如果:
SDA = 1
则表示没有收到 ACK。
当前实现还包含超时检测,最多循环约 200 次。
返回值:
1 → 收到 ACK
0 → 未收到 ACK / 超时
因此底层 I²C 字节写函数具备一定的通信异常检测能力。
十六、I²C 字节读取
内部函数:
unsigned char eeprom_i2c_read_byte(void);
用于从 I²C 总线读取一个字节。
读取过程中:
SCL = 1
↓
读取 SDA
↓
数据左移
↓
SCL = 0
连续执行 8 次,最终得到完整的一个字节。
读取函数本身不负责最终 ACK/NACK 控制,由上层调用者根据通信流程进行处理。
对于 24C02 单字节随机读取,读取完成后发送 NACK,随后产生 STOP 条件。
十七、06_Storage API 汇总
当前模块公开接口包括 EEPROM 操作接口和 I²C 底层接口。
| 类型 | API | 功能 | 返回值 |
|---|---|---|---|
| 24C02 | eeprom_24c02_write() |
写入一个字节 | 无 |
| 24C02 | eeprom_24c02_read() |
读取一个字节 | unsigned char |
| I²C | eeprom_i2c_start() |
I²C 起始条件 | 无 |
| I²C | eeprom_i2c_stop() |
I²C 停止条件 | 无 |
| I²C | eeprom_i2c_write_byte() |
I²C 写入字节 | unsigned char |
| I²C | eeprom_i2c_read_byte() |
I²C 读取字节 | unsigned char |
| I²C | eeprom_delay() |
I²C 时序延时 | 无 |
当前按照接口清单统计,共有:
7 个公开 API。
其中:
24C02:
2 个接口
I²C:
5 个接口
虽然底层 I²C 接口目前也在头文件中公开,但正常应用开发时,更推荐直接使用:
eeprom_24c02_write();
eeprom_24c02_read();
而不是直接操作底层 I²C 时序函数。
十八、24C02 驱动的特点
当前 HRTOS 4.0 24C02 驱动具有以下特点。
1. 接口简单
应用程序不需要了解完整的 I²C 时序,只需要:
eeprom_24c02_write(addr, dat);
或者:
data = eeprom_24c02_read(addr);
即可完成 EEPROM 基本操作。
2. 软件 I²C
不依赖专用 I²C 外设,可以通过普通 GPIO 实现通信。
这对于传统 51 单片机尤其有意义。
3. 单字节操作
当前驱动以单字节为基本操作单位:
1 次写入 → 1 Byte
1 次读取 → 1 Byte
实现简单,也比较适合作为 24C02 驱动的基础版本。
4. 分层设计
整体结构可以理解为:
应用程序
↓
eeprom_24c02_read/write
↓
I²C 底层接口
↓
GPIO
↓
24C02
这种分层结构使 EEPROM 操作和总线时序之间具有比较明确的职责划分。
十九、源码与接口一致性检查
目前对 06_Storage 模块的源码和接口进行了对应检查。
已经确认:
-
HRTOS_Storage.h中声明的公开 API 均有对应实现 -
函数名称与实现一致
-
参数类型与实现一致
-
返回值类型与实现一致
-
EEPROM 引脚定义与源码一致
-
I²C 器件地址与源码一致
-
EEPROM 读写流程与源码一致
-
I²C 起始和停止时序与实现一致
-
ACK 检测逻辑与底层实现一致
-
示例代码中的主要接口均为真实存在的 API
文件覆盖情况:
EEPROM-IIC:
8 个源文件
7 个公开 API
因此当前模块的基本驱动结构已经建立完成。
二十、当前版本需要注意的问题
作为驱动库的一部分,除了能够实现基本功能之外,还需要考虑硬件可靠性和接口完整性。
当前版本有几个值得注意的地方。
1. EEPROM 写周期
24C02 在执行写操作之后,需要一定时间完成内部 EEPROM 写入。
当前 eeprom_24c02_write() 使用的固定延时比较短,因此如果连续快速执行:
eeprom_24c02_write();
eeprom_24c02_write();
可能需要额外等待写周期。
实际应用中建议根据器件规格增加适当的等待时间,例如:
os_delay_ms(5);
或者:
os_delay_ms(10);
更完善的实现则可以采用 ACK Polling 判断 EEPROM 是否已经完成内部写周期。
二十一、当前暂未实现的功能
当前 24C02 驱动主要定位于基础单字节读写,因此暂未实现一些扩展功能。
包括:
-
页写
-
连续读取
-
连续写入
-
ACK Polling
-
更完整的错误返回机制
例如目前:
void eeprom_24c02_write(unsigned char addr,
unsigned char dat);
没有返回写入成功或失败状态。
如果后续进一步增强驱动,可以考虑:
unsigned char eeprom_24c02_write(...);
通过返回值让应用程序判断操作结果。
二十二、I²C 外部上拉
I²C 与普通推挽 GPIO 通信不同,SDA 和 SCL 通常需要通过上拉电阻恢复高电平。
因此实际连接 24C02 时,应注意:
VCC
│
上拉电阻
│
SDA ─────────────── 24C02 SDA
│
P2.0
VCC
│
上拉电阻
│
SCL ─────────────── 24C02 SCL
│
P2.1
常见上拉电阻可以根据实际电路选择,例如:
4.7kΩ
或者:
10kΩ
具体阻值需要结合总线速度、供电电压、线路电容等实际条件确定。
二十三、软件 I²C 与实时操作系统
HRTOS 4.0 的 06_Storage 使用软件模拟 I²C,因此 I²C 的时序由软件代码直接控制。
这意味着在 HRTOS 环境中使用时,需要关注实时系统的任务调度和中断对软件时序的影响。
当前实现没有在 I²C 操作过程中专门关闭中断,因此实际系统中应根据:
-
CPU 主频
-
I²C 时序要求
-
中断响应时间
-
系统任务调度
-
实际总线波形
进行验证。
对于要求严格的 I²C 时序,可以进一步结合逻辑分析仪对:
SCL
SDA
进行实际测量。
这也是嵌入式驱动开发中非常重要的一步:
代码逻辑正确,并不等于实际总线时序一定满足硬件要求。
二十四、HRTOS 4.0 中的存储驱动
对于一个 51 单片机实时操作系统而言,存储设备驱动承担的是数据持久化功能。
例如可以建立这样的应用:
HRTOS 4.0
│
┌─────┴─────┐
│ │
系统任务 控制任务
│ │
└─────┬─────┘
│
06_Storage
│
24C02 EEPROM
│
非易失性数据
系统启动时可以从 EEPROM 读取配置:
EEPROM
↓
读取配置参数
↓
初始化系统
↓
HRTOS任务运行
运行过程中也可以将修改后的参数重新保存:
用户修改参数
↓
应用任务
↓
EEPROM写入
↓
掉电保持
这样,24C02 就不再只是一个简单的实验器件,而可以成为整个 51 单片机应用系统中的参数存储模块。
二十五、HRTOS 4.0 与 51 单片机驱动开发
HRTOS 4.0 Driver Library 的一个重要目标,就是将 51 单片机常见硬件资源逐步整理成更加统一的驱动接口。
06_Storage 所解决的问题,就是将:
24C02
↓
I²C
↓
GPIO
这一套底层硬件操作封装起来。
对于应用程序而言,只需要关注:
eeprom_24c02_write(0x10, 0x55);
data = eeprom_24c02_read(0x10);
而不需要每次重新编写:
-
I²C START
-
I²C STOP
-
字节发送
-
ACK 检测
-
字节读取
-
EEPROM 器件地址
-
EEPROM 内部地址
这正是 51 单片机驱动开发逐步工程化的重要过程。
从操作系统角度来看,Driver Library 也是 HRTOS 与实际硬件之间的重要连接层。
二十六、HRTOS 官方网站
HRTOS 是一个面向 51 单片机 / 8051 的实时操作系统项目,持续完善操作系统内核、API、驱动库、实验例程以及技术文档。
如果希望进一步了解 HRTOS 4.0、Driver Library、API 文档以及 51 单片机实时操作系统相关内容,可以访问:
HRTOS 官方网站:
这里可以进一步了解 HRTOS 项目的整体定位以及相关开发资料。
二十七、总结
HRTOS 4.0 Driver Library 06_Storage 模块目前主要提供 24C02 EEPROM 存储驱动和软件 I²C 底层通信功能。
主要特点包括:
-
支持 24C02 2Kbit EEPROM
-
支持 256 字节地址空间
-
支持单字节读取
-
支持单字节写入
-
使用软件模拟 I²C
-
支持 I²C ACK 检测
-
提供独立的 I²C 底层实现
-
使用统一的存储设备驱动接口
当前模块共提供 7 个公开 API,其中 24C02 上层接口 2 个,I²C 底层接口 5 个。
虽然当前版本仍然属于基础存储驱动,尚未加入页写、连续读写和 ACK Polling 等功能,但已经建立了从 HRTOS 应用层 → EEPROM 驱动 → 软件 I²C → 51 单片机 GPIO → 24C02 的完整基本链路。
对于 51 单片机和 8051 开发者来说,这类驱动不仅可以用于 EEPROM 实验,也可以作为学习 I²C 总线、非易失性存储以及嵌入式驱动开发 的基础。
随着 HRTOS 4.0 Driver Library 的持续完善,更多常用硬件设备可以在统一的驱动接口下接入 HRTOS 实时操作系统,从而进一步完善 51 单片机的软件生态。
HRTOS ------ 面向 8051/51 单片机的实时操作系统。
关键词
HRTOS 4.0、HRTOS、51单片机、8051、51单片机操作系统、实时操作系统、嵌入式操作系统、驱动开发、单片机驱动、存储设备驱动、24C02、EEPROM、I²C、软件I²C、STC12C5A60S2、嵌入式开发