经过持续开发、测试与完善,HRTOS 4.0 今天正式上线。
HRTOS 4.0 在内核稳定性的基础上,进一步完善了外围软件生态。其中一个重要组成部分,就是新的 HRTOS Driver Library(驱动库)。
驱动库的定位并不是简单地收集一些单片机例程,而是希望在 HRTOS 内核与具体硬件之间建立一个更加清晰的接口层:
应用程序 → HRTOS → Driver Library → Hardware
这样可以让应用程序尽量减少对底层寄存器和硬件细节的直接依赖,同时也让驱动代码能够独立维护、测试和扩展。
本文首先介绍 Driver Library 中的 01_Basic 基础外设驱动模块。
一、HRTOS Driver Library 是什么?
HRTOS Driver Library 是 HRTOS 4.0 配套的硬件驱动软件库。
目前驱动库按照功能进行模块化组织,例如:
Driver Library
│
├── 01_Basic
├── 02_Display
├── 03_Sensor
├── 04_Communication
├── ...
└── ...
其中:
01_Basic 主要负责最基础、最常用的单片机外设。
包括:
-
Buzzer 蜂鸣器
-
KEY 独立按键
-
KEY_Matrix 矩阵键盘
-
LED
-
Timer1
-
INT0
-
INT1
对于学习 8051、编写 HRTOS 应用程序以及构建基础实验而言,这些驱动是最常用的一部分。
二、01_Basic 基础外设驱动
2.1 模块定位
01_Basic 是 Driver Library 的基础模块。
它主要解决的是一些最基本的硬件控制问题,例如:
-
控制 LED
-
控制蜂鸣器
-
读取独立按键
-
扫描矩阵键盘
-
配置定时器
-
配置外部中断
模块通过:
#include "HRTOS_Basic.h"
向上层提供统一的 API 接口。
目前公开驱动函数统一采用:
drv_xxx_xxx()
形式命名。
这种命名方式可以比较直观地区分:
-
HRTOS 内核 API
-
Driver Library API
-
应用层函数
三、Buzzer 蜂鸣器驱动
蜂鸣器是 51 单片机实验中非常常见的基础外设。
HRTOS Driver Library 提供了完整的蜂鸣器基础控制接口,包括:
-
初始化
-
开启
-
关闭
-
状态切换
3.1 文件结构
Buzzer/
├── beep_init.c
├── beep_on.c
├── beep_off.c
└── beep_toggle.c
一个功能对应一个实现文件,便于后续维护和模块化管理。
3.2 硬件接口
当前默认蜂鸣器控制引脚为:
sbit beep = P3^6;
控制关系:
| 状态 | 电平 |
|---|---|
| BEEP_ON | 0 |
| BEEP_OFF | 1 |
也就是说,当前硬件设计采用低电平有效。
3.3 API
drv_beep_init()
void drv_beep_init(void);
初始化蜂鸣器,并将其设置为关闭状态。
drv_beep_on()
void drv_beep_on(void);
开启蜂鸣器。
drv_beep_off()
void drv_beep_off(void);
关闭蜂鸣器。
drv_beep_toggle()
void drv_beep_toggle(void);
切换蜂鸣器当前状态。
例如:
drv_beep_init();
drv_beep_on();
// 其他操作
drv_beep_off();
如果需要实现连续蜂鸣、提示音等效果,可以在应用层结合延时或任务调度机制实现。
四、KEY 独立按键驱动
独立按键是最基本的人机输入设备之一。
01_Basic 提供了 4 个独立按键的轮询扫描接口。
4.1 文件结构
KEY/
├── key_init.c
└── key_scan.c
4.2 硬件连接
当前默认使用:
sbit key1 = P3^2;
sbit key2 = P3^3;
sbit key3 = P3^4;
sbit key4 = P3^5;
按键状态:
0:按下
1:释放
对应关系:
| 按键 | 引脚 | 返回值 |
|---|---|---|
| key1 | P3.2 | KEY_1 |
| key2 | P3.3 | KEY_2 |
| key3 | P3.4 | KEY_3 |
| key4 | P3.5 | KEY_4 |
4.3 API
初始化:
void drv_key_init(void);
按键扫描:
unsigned char drv_key_scan(void);
例如:
unsigned char key;
key = drv_key_scan();
if(key == KEY_1)
{
// KEY1 被按下
}
如果没有检测到按键:
KEY_NONE
将作为返回值。
4.4 扫描方式
当前按键扫描采用轮询方式:
KEY1
↓
KEY2
↓
KEY3
↓
KEY4
检测到按键后立即返回。
因此当前版本具有以下特点:
-
不支持多键同时检测
-
不检测按键释放事件
-
驱动层不加入消抖延时
-
应用层可以根据实际需求实现消抖
这样的设计可以避免把特定的消抖策略强制加入底层驱动。
五、KEY_Matrix 矩阵键盘驱动
除了独立按键之外,Driver Library 还提供 4×4 矩阵键盘驱动。
4×4 矩阵键盘可以提供:
16 个按键输入。
5.1 文件结构
KEY_Matrix/
├── matrixkey_init.c
└── matrixkey_scan.c
5.2 硬件接口
当前矩阵键盘使用:
#define GPIO_KEY P1
即通过 P1 端口完成矩阵扫描。
5.3 API
初始化:
void drv_matrixkey_init(void);
扫描:
unsigned char drv_matrixkey_scan(void);
返回值:
0 ~ 15 有按键
0xFF 无按键
例如:
unsigned char key;
key = drv_matrixkey_scan();
if(key != MATRIXKEY_NONE)
{
// 处理矩阵键盘输入
}
5.4 扫描过程
矩阵键盘采用行列扫描方式。
基本过程:
设置行
↓
读取列
↓
确定行位置
↓
确定列位置
↓
计算键码
最终得到:
0 ~ 15
范围内的键码。
需要注意的是,具体键码与实际键帽位置的对应关系,需要根据具体硬件连接确定。
六、LED 驱动
LED 是 HRTOS 示例程序和开发板实验中使用频率非常高的外设。
因此 LED 驱动也是 01_Basic 中非常基础的一部分。
6.1 文件结构
LED/
├── led_init.c
├── led_on.c
├── led_off.c
├── led_toggle.c
└── led_write.c
可以看到,LED 驱动不仅提供单个 LED 控制,还提供了整个端口的批量控制。
6.2 硬件接口
当前 LED 使用:
#define LED_PORT P1
对应:
P1.0 → LED0
P1.1 → LED1
P1.2 → LED2
P1.3 → LED3
P1.4 → LED4
P1.5 → LED5
P1.6 → LED6
P1.7 → LED7
当前采用低电平点亮:
0 → LED ON
1 → LED OFF
6.3 API
初始化
void drv_led_init(void);
初始化后:
LED_PORT = 0xFF;
即所有 LED 熄灭。
点亮指定 LED
void drv_led_on(unsigned char led);
例如:
drv_led_on(0);
点亮 LED0。
熄灭指定 LED
void drv_led_off(unsigned char led);
例如:
drv_led_off(0);
熄灭 LED0。
状态切换
void drv_led_toggle(unsigned char led);
例如:
drv_led_toggle(0);
可以快速实现 LED 闪烁控制。
批量写入
void drv_led_write(unsigned char value);
这是 LED 驱动中比较方便的一个接口。
例如:
drv_led_write(0x00);
表示:
8 个 LED 全部点亮。
而:
drv_led_write(0xFF);
表示:
8 个 LED 全部熄灭。
例如:
drv_led_write(0x55);
可以实现:
LED0 ON
LED1 OFF
LED2 ON
LED3 OFF
LED4 ON
LED5 OFF
LED6 ON
LED7 OFF
这种接口非常适合流水灯、状态指示、二进制显示等应用。
七、Timer1 定时器驱动
Timer1 是 8051 系统中非常重要的基础外设。
HRTOS Driver Library 提供 Timer1 初始化接口,可以设置定时器初始重装值。
7.1 文件结构
Timer1/
└── timer1_init.c
7.2 工作模式
当前配置:
Timer1
模式1
16位定时器
涉及的主要寄存器包括:
TMOD
TH1
TL1
ET1
TR1
7.3 API
void drv_timer1_init(
unsigned char reload_h,
unsigned char reload_l
);
其中:
reload_h → 重装值高8位
reload_l → 重装值低8位
初始化完成后:
ET1 = 1
TR1 = 1
即开启 Timer1 中断并启动定时器。
例如,在 11.0592 MHz 系统时钟下,需要配置约 1 ms 定时,可以使用:
drv_timer1_init(0xFC, 0x66);
Timer1 溢出后,用户需要在中断服务函数中重新装载:
TH1 = 0xFC;
TL1 = 0x66;
八、INT0 / INT1 外部中断
01_Basic 中还包含 INT0 和 INT1 的底层实现。
其中:
INT0 → P3.2
INT1 → P3.3
分别对应 8051 的两个外部中断输入。
当前实现支持:
0 → 电平触发
1 → 下降沿触发
对应初始化函数:
drv_int0_init(unsigned char mode);
drv_int1_init(unsigned char mode);
不过需要特别说明:
当前版本中 INT0、INT1 尚未作为 HRTOS_Basic.h 的公开 API 暴露。
因此,它们目前属于驱动库中的内部实现,而不是正式公开接口。
这也是 HRTOS Driver Library 在持续整理过程中需要明确区分的一点:
源码中存在的函数,不一定都属于稳定的公开 API。
公开 API 以头文件中的接口声明为准。
九、硬件资源复用说明
由于 8051 的 GPIO 资源有限,一些功能存在硬件引脚复用关系。
当前 01_Basic 需要特别注意以下资源冲突。
P3.2
KEY1
INT0
二者共用 P3.2。
P3.3
KEY2
INT1
二者共用 P3.3。
P1
LED
KEY_Matrix
LED 和矩阵键盘均使用 P1。
因此,在实际硬件设计中,需要根据具体应用选择相应功能,不能简单地认为所有基础驱动可以同时启用。
这也是 8051 资源受限环境下进行系统设计时需要考虑的问题。
十、01_Basic API 汇总
目前 01_Basic 对外提供 14 个公开 API:
| 模块 | API | 功能 |
|---|---|---|
| Buzzer | drv_beep_init | 蜂鸣器初始化 |
| Buzzer | drv_beep_on | 开启蜂鸣器 |
| Buzzer | drv_beep_off | 关闭蜂鸣器 |
| Buzzer | drv_beep_toggle | 蜂鸣器状态切换 |
| KEY | drv_key_init | 独立按键初始化 |
| KEY | drv_key_scan | 独立按键扫描 |
| KEY_Matrix | drv_matrixkey_init | 矩阵键盘初始化 |
| KEY_Matrix | drv_matrixkey_scan | 矩阵键盘扫描 |
| LED | drv_led_init | LED 初始化 |
| LED | drv_led_on | 点亮 LED |
| LED | drv_led_off | 熄灭 LED |
| LED | drv_led_toggle | LED 状态切换 |
| LED | drv_led_write | LED 批量控制 |
| Timer1 | drv_timer1_init | Timer1 初始化 |
另外,INT0 和 INT1 当前属于内部实现,不计入公开 API 数量。
十一、驱动库与 HRTOS 的关系
HRTOS Driver Library 并不是 HRTOS 内核本身。
两者在设计上具有明确的层次关系。
可以简单理解为:
┌──────────────────────────┐
│ Application │
│ 应用程序 │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ HRTOS Driver Library │
│ 硬件驱动库 │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ HRTOS HAL │
│ hrtos_hal.h │
└────────────┬─────────────┘
│
▼
┌──────────────────────────┐
│ 8051 Hardware │
│ MCU / Peripherals │
└──────────────────────────┘
其中,驱动实现依赖:
#include "hrtos_hal.h"
通过硬件抽象层访问底层硬件。
这样的结构能够让驱动代码与 HRTOS 内核保持相对独立。
十二、为什么 HRTOS 4.0 要开始建设驱动库?
对于一个操作系统来说,只有内核并不能形成完整的使用体验。
尤其是在 8051 这种资源受限的平台上,用户最终还是需要面对大量具体硬件:
LED
按键
蜂鸣器
LCD
数码管
传感器
串口
RS485
Modbus
定时器
...
如果每个应用都重新编写一套底层代码,那么:
-
重复工作较多
-
API 不统一
-
示例程序之间差异较大
-
驱动代码难以维护
-
用户学习成本较高
因此,HRTOS 4.0 开始逐步建立 Driver Library。
它的目标并不是一开始就覆盖所有 8051 外设,而是:
先把常用的驱动整理好,再持续扩展。
这也是 HRTOS 目前整体开发路线的一部分。
十三、从"例程"走向"驱动库"
过去很多 51 单片机项目中的代码,实际上更接近:
一个实验
+
一份程序
+
一套硬件
而 Driver Library 希望进一步将其整理成:
硬件驱动
↓
统一 API
↓
应用程序
例如过去控制 LED 可能直接写:
P1 = 0xFE;
而使用驱动库后可以写:
drv_led_on(0);
对于简单程序而言,两者的代码量差异并不重要。
真正重要的是软件边界发生了变化。
应用程序开始关注:
"我要点亮 LED0。"
而不是:
"我要把 P1 的哪一位寄存器写成什么值。"
这也是 Driver Library 存在的意义。
十四、当前版本的设计特点
HRTOS Driver Library 目前仍然处于持续完善阶段,因此并没有刻意追求"大而全"。
当前更关注几个方面:
1. 接口清晰
通过统一的:
drv_xxx_xxx()
命名方式建立驱动 API。
2. 模块化
不同外设分别组织在独立目录中。
3. 与 HAL 配合
底层硬件访问依赖:
hrtos_hal.h
而不是让所有驱动直接依赖复杂的系统内部实现。
4. 保持轻量
HRTOS 的目标平台是资源非常有限的 8051。
因此驱动库不会为了抽象而抽象,也不会为了追求复杂架构而增加没有必要的软件开销。
5. 持续扩展
01_Basic 只是整个 Driver Library 的开始。
后续还会逐步完善:
Display
Sensor
Communication
Control
...
等更多驱动模块。
十五、源码与接口一致性
在 HRTOS 4.0 Driver Library 的整理过程中,我也对 01_Basic 模块进行了源码与接口对应检查。
目前确认:
-
公开 API 均能够找到对应实现
-
函数名称与声明一致
-
参数类型一致
-
返回值类型一致
-
主要硬件引脚定义与源码一致
-
示例程序使用的 API 均来自公开接口
同时,也保留了一些需要在后续版本中继续优化的地方,例如:
-
INT0 / INT1 是否正式公开
-
KEY 初始化接口进一步完善
-
矩阵键盘消抖机制
-
矩阵键盘阻塞行为优化
-
部分 GPIO 配置进一步抽象
这也是一个持续维护项目应该有的状态。
不是把所有东西包装成"完美",而是明确当前版本已经做到什么,以及下一步准备做什么。
十六、结语
HRTOS 4.0 的发布,不只是 HRTOS 内核版本号的变化。
随着 Driver Library、Examples、Shell、Modbus 以及相关文档逐步完善,HRTOS 正在从一个单纯的实时内核项目,逐步形成更加完整的 8051 实时操作系统软件体系。
而 Driver Library 是其中非常重要的一环。
目前介绍的 01_Basic 基础外设驱动只是整个驱动库的一部分。
后续我还会继续介绍其他驱动模块,并逐步公开各模块的:
-
功能说明
-
文件结构
-
硬件接口
-
API
-
使用示例
-
注意事项
-
实际测试情况
希望通过这种方式,把 HRTOS 的驱动体系完整地记录下来。
HRTOS 4.0,正式上线。
这一次,不只是内核更新,也是 HRTOS 软件生态进一步完善的开始。
项目名称:HRTOS
版本:HRTOS 4.0
模块:HRTOS Driver Library / 01_Basic
项目主页
HRTOS 官方网站:
HRTOS - Hard Real-Time Operating System | 硬实时操作系统
欢迎访问 HRTOS 官方网站,获取项目介绍、开发文档、API 文档、驱动库及最新版本信息。
HRTOS ------ 面向 8051 的实时操作系统。