在 51 单片机项目中,LCD1602 是非常经典的一款字符型液晶显示模块。
它虽然属于比较早期的显示器件,但由于接口简单、资料丰富、成本低,在 8051 单片机学习、实验以及一些小型嵌入式项目中仍然具有一定的使用价值。
在 HRTOS 4.0 驱动库中,对 LCD1602 进行了封装。应用层无需直接操作 LCD1602 的底层时序,只需要调用对应的驱动 API,即可完成初始化、设置光标以及字符串显示。
本文通过一个简单的实例,演示如何在 HRTOS 4.0 中使用 LCD1602。
一、示例功能
本例实现一个最简单的 LCD1602 显示程序。
上电运行后:
-
LCD1602 初始化
-
第 1 行显示
HRTOS 4.0 -
第 2 行显示
LCD1602 Demo
最终显示效果类似:
HRTOS 4.0
LCD1602 Demo
这个例子虽然非常简单,但可以直观体现 HRTOS 4.0 驱动库的基本使用方式。
二、程序代码
完整示例代码如下:
#include "hrtos_hal.h"
/**
* @brief LCD1602显示示例
*
* 功能:
* 第1行显示:HRTOS 4.0
* 第2行显示:LCD1602 Demo
*/
void app_lcd1602_example(void)
{
/* LCD1602初始化 */
drv_lcd1602_init();
/* 第1行 */
drv_lcd1602_set_cursor(0, 0);
drv_lcd1602_write_string("HRTOS 4.0");
/* 第2行 */
drv_lcd1602_set_cursor(0, 1);
drv_lcd1602_write_string("LCD1602 Demo");
while(1);
}
void hrtos_main()
{
os_task_create(app_lcd1602_example, 2, 2, 5);
}
可以看到,整个应用程序非常简洁。
LCD1602 的底层初始化、数据写入以及控制时序都由驱动层完成,应用代码只需要关注:
-
初始化 LCD1602
-
设置显示位置
-
输出字符串
-
创建应用任务
三、包含 HRTOS HAL 头文件
程序首先包含:
#include "hrtos_hal.h"
HRTOS 4.0 将硬件相关的驱动接口进行统一封装,应用程序通过 HAL 层使用对应的硬件驱动。
因此,应用代码不需要直接包含 LCD1602 驱动内部的底层实现文件。
这种方式可以让应用层和具体硬件实现之间保持一定的隔离。
对于使用者来说,更接近:
应用程序
↓
HRTOS HAL / Driver
↓
LCD1602硬件
而不是直接在应用程序中操作 LCD1602 的底层时序。
四、LCD1602初始化
首先调用:
drv_lcd1602_init();
完成 LCD1602 的初始化。
初始化是使用 LCD1602 前必须进行的步骤。
在传统的 51 单片机裸机程序中,开发者通常需要自己处理 LCD1602 的初始化流程,包括:
-
控制数据线
-
控制 RS
-
控制 EN
-
发送初始化命令
-
控制时序
-
等待 LCD1602 完成操作
而在 HRTOS 4.0 驱动库中,这些底层工作已经封装到:
drv_lcd1602_init();
应用程序直接调用即可。
这也是驱动层存在的意义之一:
将硬件细节封装在驱动层,将简单、统一的 API 提供给应用层。
五、设置 LCD1602 光标位置
初始化完成之后,就可以设置显示位置。
第一行使用:
drv_lcd1602_set_cursor(0, 0);
然后输出:
drv_lcd1602_write_string("HRTOS 4.0");
第二行使用:
drv_lcd1602_set_cursor(0, 1);
然后输出:
drv_lcd1602_write_string("LCD1602 Demo");
这里的:
drv_lcd1602_set_cursor(x, y);
可以理解为设置 LCD1602 当前的显示坐标。
本例中:
(0, 0)
表示第一行第一个位置。
而:
(0, 1)
表示第二行第一个位置。
因此程序最终形成:
HRTOS 4.0
LCD1602 Demo
六、字符串显示
LCD1602 的字符串显示通过:
drv_lcd1602_write_string();
完成。
例如:
drv_lcd1602_write_string("HRTOS 4.0");
即可将字符串显示到当前光标位置。
第二行:
drv_lcd1602_write_string("LCD1602 Demo");
同样可以直接输出字符串。
相比于在应用程序中自己编写 LCD1602 的逐字节发送代码,这种接口明显更加直观。
例如应用层只需要表达:
drv_lcd1602_write_string("HRTOS 4.0");
而无需关心:
发送一个字符
↓
写数据命令
↓
设置数据线
↓
产生EN脉冲
↓
等待
↓
发送下一个字符
这些细节由驱动层负责。
七、为什么应用函数最后使用 while(1)
本例最后有:
while(1);
这里需要特别说明。
这个例子属于静态显示示例。
LCD1602 完成显示之后,没有继续执行其他周期性任务,因此应用函数不需要不断重复刷新 LCD。
因此程序在完成显示之后保持运行状态:
while(1);
这样 LCD1602 会保持当前显示内容。
如果实际项目需要动态刷新 LCD1602,例如:
温度:25.6℃
湿度:61%
那么就可以将应用任务改写成周期性任务,例如:
void app_lcd1602_example(void)
{
drv_lcd1602_init();
while(1)
{
drv_lcd1602_set_cursor(0, 0);
drv_lcd1602_write_string("Temp: 25.6C");
os_task_delay(1000);
}
}
具体延时 API 可以根据实际 HRTOS 4.0 API 进行调整。
这样 LCD1602 就可以成为一个真正的周期性显示任务。
八、创建 HRTOS 任务
最后在:
void hrtos_main()
中创建 LCD1602 应用任务:
os_task_create(app_lcd1602_example, 2, 2, 5);
这样,LCD1602 的显示程序就成为 HRTOS 中的一个独立任务。
从应用程序结构来看:
hrtos_main()
│
└── app_lcd1602_example()
│
├── LCD1602初始化
├── 设置第一行
├── 显示 HRTOS 4.0
├── 设置第二行
└── 显示 LCD1602 Demo
这种结构和传统裸机程序相比更加清晰。
在裸机程序中,经常会出现大量代码全部堆积在:
while(1)
{
...
}
中的情况。
而在 HRTOS 中,可以根据功能将程序划分成多个独立任务。
例如一个实际项目可以设计成:
LCD显示任务
温度采集任务
按键扫描任务
串口通信任务
蜂鸣器任务
控制任务
每个功能分别由对应任务负责。
九、HRTOS 4.0 驱动库的使用方式
从这个 LCD1602 示例也可以看出 HRTOS 4.0 驱动库的一个基本特点。
应用层主要使用统一的:
drv_xxx_xxx()
形式的接口。
例如:
drv_lcd1602_init();
drv_lcd1602_set_cursor();
drv_lcd1602_write_string();
应用程序不需要深入了解驱动内部实现。
从软件结构上可以形成:
┌─────────────────────────┐
│ Application │
│ │
│ app_lcd1602_example() │
└────────────┬────────────┘
│
↓
┌─────────────────────────┐
│ HRTOS Driver │
│ │
│ drv_lcd1602_xxx() │
└────────────┬────────────┘
│
↓
┌─────────────────────────┐
│ LCD1602 │
│ Hardware │
└─────────────────────────┘
这样做的好处是,当应用程序需要更换硬件或者修改底层实现时,可以尽量减少对上层应用代码的影响。
十、从裸机到 HRTOS 的一个简单变化
如果采用传统裸机方式,LCD1602 程序通常会直接围绕硬件操作展开。
而在 HRTOS 4.0 中,可以进一步把它组织成一个独立应用任务:
void app_lcd1602_example(void)
{
drv_lcd1602_init();
drv_lcd1602_set_cursor(0, 0);
drv_lcd1602_write_string("HRTOS 4.0");
drv_lcd1602_set_cursor(0, 1);
drv_lcd1602_write_string("LCD1602 Demo");
while(1);
}
然后:
void hrtos_main()
{
os_task_create(app_lcd1602_example, 2, 2, 5);
}
这其实就是 HRTOS 4.0 应用开发的一个基本思路:
驱动负责硬件,任务负责功能,内核负责任务调度。
应用开发者不需要在每个功能模块中重新实现底层硬件控制逻辑。
十一、总结
本文通过一个简单的 LCD1602 示例,介绍了 HRTOS 4.0 中 LCD1602 驱动的基本使用方法。
完整流程可以概括为:
包含 HRTOS HAL
↓
LCD1602初始化
↓
设置显示位置
↓
输出字符串
↓
创建应用任务
核心 API 包括:
drv_lcd1602_init();
drv_lcd1602_set_cursor();
drv_lcd1602_write_string();
对于一个最基本的 LCD1602 显示程序,应用层只需要几十行代码即可完成。
而随着项目复杂度提高,还可以进一步将 LCD1602 与传感器、按键、通信、控制等功能组合起来,通过 HRTOS 的多任务机制构建完整的 8051 应用系统。
这也是 HRTOS 4.0 驱动库希望提供的一种开发方式:
让 8051 应用开发从直接操作硬件,逐步过渡到面向驱动和任务进行开发。
后续还可以继续使用同样的方式扩展 LED、按键、数码管、DHT11、DS18B20、HC-SR04 等常用 51 外设和传感器。