- 物联网
- 嵌入式
- 操作系统
- 实时系统
【免费下载链接】RIOT
RIOT - The friendly OS for IoT
导读
AIP31068 是一款通过 I2C 接口控制、内部挂载 HD44780 兼容控制器的字符型 LCD 驱动芯片,常用于 16x2、20x4 等小尺寸显示屏。本文以 RIOT OS 官方测试应用 tests/drivers/aip31068/README.md 为骨架,完整讲解该测试程序提供的 20 条 Shell 命令的用法与参数,并深入 tests/drivers/aip31068/main.c 与 drivers/aip31068/aip31068.c 源码,剖析初始化序列、I2C 写协议、自定义字符与进度条(progress bar)的底层实现。读完本文,你将能够在任意支持periph_i2c的 RIOT 板卡上编译、烧录并逐条验证 AIP31068 的全部驱动能力。
测试应用概述:用 Shell 命令逐项验证 LCD 驱动接口
AIP31068 测试应用的核心目标是演示 AIP31068 驱动接口的用法,并通过 Shell 命令对一块真实的 AIP31068 LCD 设备进行逐项功能测试。其入口代码位于 tests/drivers/aip31068/main.c:
int main(void) { int rc = 0; if ((rc = aip31068_init(&aip31068_dev, &aip31068_params[0])) != 0) { printf("Initialization failed! rc = %d", rc); return 1; } aip31068_turn_on(&aip31068_dev); aip31068_set_custom_symbol(&aip31068_dev, CUSTOM_SYMBOL_1, custom_char_heart); char line_buf[SHELL_DEFAULT_BUFSIZE]; shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); return 0; }程序启动后先调用aip31068_init()完成初始化,随后点亮显示屏并把一颗"心形"图案写入自定义字符槽CUSTOM_SYMBOL_1,最后进入 Shell 交互循环等待用户输入命令。整个测试程序仅依赖三个模块,从 tests/drivers/aip31068/Makefile 可以看到:
include ../Makefile.drivers_common USEMODULE += aip31068 USEMODULE += xtimer USEMODULE += shell include $(RIOTBASE)/Makefile.include而驱动本身在 drivers/aip31068/Makefile.dep 中声明了硬件依赖:
FEATURES_REQUIRED += periph_i2c USEMODULE += xtimer即编译该测试应用需要板卡提供I2C 外设,且驱动内部使用xtimer实现初始化与命令执行的时序等待。
设备参数与默认配置
测试程序直接使用驱动提供的默认参数数组aip31068_params[]。默认配置定义在 drivers/aip31068/include/aip31068_params.h:
#ifndef AIP31068_PARAM_I2C_DEV /** I2C device is I2C_DEV(0) */ #define AIP31068_PARAM_I2C_DEV I2C_DEV(0) #endif #ifndef AIP31068_PARAM_I2C_ADDR /** I2C address of device is (0x7c >> 1) */ #define AIP31068_PARAM_I2C_ADDR (0x7c >> 1) #endif #ifndef AIP31068_PARAMS #define AIP31068_PARAMS \ { \ .i2c_dev = AIP31068_PARAM_I2C_DEV, \ .i2c_addr = AIP31068_PARAM_I2C_ADDR, \ .row_count = 2, \ .col_count = 16, \ .font_size = FONT_SIZE_5x8, \ .bit_mode = BITMODE_8_BIT, \ } #endif关键参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
i2c_dev | I2C_DEV(0) | 使用的 I2C 控制器编号 |
i2c_addr | 0x7c >> 1(即 0x3E) | 设备 7 位 I2C 地址,0x7C 是常见 LCD I2C 背板地址的 8 位写法 |
row_count | 2 | 显示行数,驱动断言限制最大为 4 行 |
col_count | 16 | 每行字符列数 |
font_size | FONT_SIZE_5x8 | 字符点阵规格,可选 5x8 或 5x10 |
bit_mode | BITMODE_8_BIT | 接口位宽模式,可选 4 位或 8 位 |
参数结构体aip31068_params_t与枚举aip31068_font_size_t、aip31068_bit_mode_t的定义位于 drivers/include/aip31068.h。测试程序在 tests/drivers/aip31068/main.c 中按默认 2 行 16 列定义了常量:
#define ROW_COUNT 2 #define COL_COUNT 16 /* font is either 5x8 or 5x10, so always 5 columns per character */ #define PIXEL_COLUMNS_PER_CHAR 5若你的 LCD 是 20x4 等规格,可通过在构建时覆盖AIP31068_PARAMS宏(或对应AIP31068_PARAM_*宏)来适配。
20 条 Shell 命令的完整用法
README 列出的全部 20 条命令都在 tests/drivers/aip31068/main.c 的命令表中注册。下面按功能分类逐一给出精确用法与对应驱动函数。
3.1 显示开关与清屏
| 命令 | 用法 | 驱动函数 | 说明 |
|---|---|---|---|
turn_on | turn_on | aip31068_turn_on() | 打开 LCD 显示 |
turn_off | turn_off | aip31068_turn_off() | 关闭 LCD 显示 |
clear | clear | aip31068_clear() | 清空显示内容,光标回到 (0, 0) |
home | home | aip31068_return_home() | 光标回到 (0, 0),并撤销此前所有滚动移位 |
这四条命令不带参数。从源码看,turn_on/turn_off通过置位/清零DISPLAY_CONTROL命令中的显示位(AIP31068_BIT_DISPLAY_CONTROL_DISPLAY)实现,而clear与home在执行后都会等待AIP31068_EXECUTION_TIME_MAX(清屏/归位是耗时最长的操作,见 drivers/aip31068/aip31068.c)。
3.2 光标与文本行为
| 命令 | 用法 | 驱动函数 | 说明 |
|---|---|---|---|
autoscroll | autoscroll <0 or 1> | aip31068_set_auto_scroll_enabled() | 启用/禁用自动滚动 |
cursor_blinking | cursor_blinking <0 or 1> | aip31068_set_cursor_blinking_enabled() | 启用/禁用光标闪烁 |
cursor_visible | cursor_visible <0 or 1> | aip31068_set_cursor_visible() | 显示/隐藏光标 |
cursor_position | cursor_position <row> <column> | aip31068_set_cursor_position() | 设置光标位置,row/column 均从 0 起算 |
text_insertion | text_insertion <mode (0-1)> | aip31068_set_text_insertion_mode() | 设置文本插入方向:0 = LEFT_TO_RIGHT,1 = RIGHT_TO_LEFT |
cursor_left | cursor_left | aip31068_move_cursor_left() | 光标左移一格 |
cursor_right | cursor_right | aip31068_move_cursor_right() | 光标右移一格 |
scroll_left | scroll_left | aip31068_scroll_display_left() | 显示内容整体左移一格 |
scroll_right | scroll_right | aip31068_scroll_display_right() | 显示内容整体右移一格 |
其中带参命令的参数校验逻辑都写在对应处理函数中,例如_cursor_position(tests/drivers/aip31068/main.c)要求恰好两个参数,否则打印用法提示;_text_insertion(tests/drivers/aip31068/main.c)会把数字参数映射为LEFT_TO_RIGHT/RIGHT_TO_LEFT枚举并拒绝 0-1 之外的值。
值得注意的实现细节:scroll_left/scroll_right与cursor_left/cursor_right共用同一条CURSOR_DISPLAY_SHIFT命令,区别仅在于控制位的组合——滚动方向由AIP31068_BIT_CURSOR_DISPLAY_SHIFT_SELECTION(选择移动光标还是滚动显示)与AIP31068_BIT_CURSOR_DISPLAY_SHIFT_DIRECTION(方向)两个位决定,见 drivers/aip31068/include/aip31068_regs.h。
3.3 字符输出与自定义符号
| 命令 | 用法 | 驱动函数 | 说明 |
|---|---|---|---|
print | print <text> | aip31068_print() | 在当前光标处打印字符串 |
create_custom_symbol | create_custom_symbol <symbol (0-7)> <row 0 (0-31)> ... <row 7 (0-31)> | aip31068_set_custom_symbol() | 创建自定义符号(8 行像素数据) |
print_custom_symbol | print_custom_symbol <symbol (0-7)> | aip31068_print_custom_symbol() | 打印自定义符号 |
自定义符号是 HD44780 系 LCD 的经典能力:控制器内置 CGRAM,可存放最多 8 个用户自定义字符。每个字符在 5x8 字体下由 8 行、每行 5 位(0-31)的位图定义。测试程序给出了心形示例(tests/drivers/aip31068/main.c):
static const uint8_t custom_char_heart[] = { 0, 0, 10, 31, 31, 14, 4, 0 };即执行create_custom_symbol 0 0 0 10 31 31 14 4 0即可在槽位 0 写入一颗心,再用print_custom_symbol 0打印。处理函数_create_custom_symbol(tests/drivers/aip31068/main.c)会校验符号索引必须在 0-7 之间。
驱动侧aip31068_set_custom_symbol()的实现揭示了 CGRAM 的地址编码:自定义字符基地址为symbol << 3,并通过SET_CGRAM_ADDR命令定位,随后按字体逐行写入像素数据(5x8 字体写 8 行,5x10 字体写 10 行),见 drivers/aip31068/aip31068.c。aip31068_print_custom_symbol()则直接以符号索引作为数据字节输出。
3.4 进度条功能
| 命令 | 用法 | 说明 |
|---|---|---|
progressbar | progressbar <0 or 1> | 启用/禁用进度条功能 |
progressbar_row | progressbar_row <row> | 设置进度条所在行(默认最后一行) |
progress | progress <progress (0-100)> | 设置进度百分比并刷新显示 |
进度条是测试程序在驱动基础能力之上实现的"彩蛋"功能,它复用了 5 个自定义字符槽位(CUSTOM_SYMBOL_4到CUSTOM_SYMBOL_8)来渲染不同填充宽度的竖条,见 tests/drivers/aip31068/main.c 的_init_progress_bar()。启用进度条时程序会自动:
- 关闭自动滚动并执行
return_home撤销已发生的滚动(否则进度条显示会错位); - 将文本插入模式设为
LEFT_TO_RIGHT; - 向槽位 4-8 写入 5 种逐级变宽的条状图案(像素列宽分别为 1/5 至 5/5)。
绘制算法_set_progress()(tests/drivers/aip31068/main.c)把百分比换算为整行像素列数:
int bar_count = dev->params.col_count * PIXEL_COLUMNS_PER_CHAR; /* 16 列 x 5 像素 = 80 */ int progress_bar_count = bar_count * progress / 100; /* 目标像素列数 */ int full_bar_count = progress_bar_count / PIXEL_COLUMNS_PER_CHAR; /* 完整实心字符数 */ int remainder_bar_count = progress_bar_count % PIXEL_COLUMNS_PER_CHAR; /* 剩余半格 */完整实心部分用CUSTOM_SYMBOL_8填充,余数部分按 1-4 像素分别用CUSTOM_SYMBOL_4~CUSTOM_SYMBOL_7,行尾剩余部分用空格补齐,从而在 2 行 16 列屏上呈现细腻的像素级进度条。
run_demo:一键演示全部功能
run_demo命令无需参数,会在屏幕上顺序演示 9 个场景,是验收驱动与硬件连接是否正常的最快途径(tests/drivers/aip31068/main.c):
- 自定义符号:打印 "Hello world! " 并输出心形符号;
- 滚动演示:先以
LEFT_TO_RIGHT插入模式打印 "scroll right" 并右移 4 次;再以RIGHT_TO_LEFT模式、光标置于第 15 列打印反向文本并左移 5 次(演示双向插入与滚动); - 开关显示:打印 "turning off..." 后
turn_off1 秒,再clear+turn_on恢复; - 自动滚动:第二行打印超长文本,光标移到第 16 列后启用
autoscroll,逐字符打印 "This is a very long line"(每 250ms 一个字符)观察自动滚动,随后关闭; - 归位:
return_home复位; - 光标闪烁:在首行 16 个位置间移动光标,中途反复开关闪烁位;
- 显示与移动光标:打印 0-9,然后光标右移 50 格、左移 50 格;
- 50 字符长文本:
LEFT_TO_RIGHT交替打印 50 个 "A"/"B"(跨行环绕),再以RIGHT_TO_LEFT从第 15 列起反向交替打印 50 个 "X"/"Y"; - 进度条:启用进度条后,在第 10 列实时打印 "0 %" 到 "100 %",同时
_set_progress逐百分比推进,最后关闭并清屏。
整个 demo 依赖xtimer的xtimer_sleep/xtimer_msleep控制节奏。运行run_demo即可直观验证 LCD 的所有功能点。
底层原理:初始化序列与 I2C 写协议
5.1 初始化序列
aip31068_init()(drivers/aip31068/aip31068.c)严格按照 AIP31068 数据手册第 20 页(即其背后 HD44780 的初始化流程)执行:
- 根据
bit_mode/row_count/font_size组装FUNCTION_SET命令的控制位; - 先睡眠 50ms,连续三次发送
FUNCTION_SET(间隔分别为 5ms 与 500us),保证兼容各种实现; - 依次发送
turn_off、clear、set_text_insertion_mode(LEFT_TO_RIGHT)完成收尾。
同时初始化断言params->row_count <= 4,因为aip31068_set_cursor_position()内部使用硬编码的行偏移表row_offsets[4] = {0x00, 0x40, 0x00+col, 0x40+col}计算 DDRAM 地址(drivers/aip31068/aip31068.c),超过 4 行无法寻址。
5.2 I2C 数据帧格式
AIP31068 通过 I2C 传输时,每个数据帧由"控制字节 + 数据字节"组成(drivers/aip31068/aip31068.c):
static inline int _write(aip31068_t *dev, uint8_t data_byte, bool is_cmd) { uint8_t control_byte = 0; if (!is_cmd) { SETBIT(control_byte, AIP31068_BIT_CONTROL_BYTE_RS); /* RS=1 表示数据 */ } uint8_t data[] = { control_byte, data_byte }; return _device_write(dev, data, sizeof(data)); }控制字节的含义定义在 drivers/aip31068/include/aip31068_regs.h:
BIT7(CO):0 表示这是最后一个控制字节,1 表示其后还跟有控制字节;BIT6(RS):0 表示后续数据字节被解释为命令,1 表示被解释为显示数据。
最终通过i2c_acquire()/i2c_write_bytes()/i2c_release()发送到总线上(drivers/aip31068/aip31068.c)。每个命令或数据字节写入后,驱动都会xtimer_usleep(AIP31068_EXECUTION_TIME_DEFAULT)等待指令执行完成。
5.3 驱动 API 一览
驱动对外公开的全部 API 声明在 drivers/include/aip31068.h(共 421 行),包括本文涉及的核心函数:aip31068_init、aip31068_turn_on/off、aip31068_clear、aip31068_return_home、aip31068_set_auto_scroll_enabled、aip31068_set_cursor_blinking_enabled、aip31068_set_cursor_visible、aip31068_set_cursor_position、aip31068_set_text_insertion_mode、aip31068_move_cursor_left/right、aip31068_scroll_display_left/right、aip31068_set_custom_symbol、aip31068_print_custom_symbol、aip31068_print、aip31068_print_char。它们与本文 Shell 命令一一对应,因此在验证完命令后,完全可以直接在业务代码中调用同样的 API 驱动 LCD。
编译、烧录与运行
在支持periph_i2c的任意板卡上(如native之外的各类开发板)按 RIOT 标准流程构建:
make BOARD=<你的板卡名> -C tests/drivers/aip31068 flash term例如使用nucleo-f446re:
make BOARD=nucleo-f446re -C tests/drivers/aip31068 flash term连接 LCD 的 SDA/SCL 到板卡I2C_DEV(0)对应引脚(地址默认 0x3E),上电后终端即可交互。建议按以下顺序验证:
turn_on print Hello RIOT! cursor_position 1 0 print progress test progressbar 1 progress 50 run_demo若aip31068_init返回非 0(如-ENXIO),说明 I2C 总线上未发现设备,请检查接线、地址与I2C_DEV编号;若返回-EIO,通常是设备未正确应答,可优先排查供电与地址配置(详见 drivers/include/aip31068.h 中的返回值说明)。
小结
RIOT OS 的 tests/drivers/aip31068 测试应用以 20 条 Shell 命令完整覆盖了 AIP31068 驱动的显示控制、光标管理、滚动移位、自定义字符与进度条五大能力,其中run_demo一键即可完成全功能验收。配合 drivers/aip31068 驱动源码,开发者既能快速验证硬件,也能把测试程序中的用法直接迁移到自己的业务代码中,是学习 RIOT 字符型 LCD 驱动开发的最佳起点。
- 物联网
- 嵌入式
- 操作系统
- 实时系统
【免费下载链接】RIOT
RIOT - The friendly OS for IoT
相关推荐
如何高效捕获yargs命令行工具的输出:stdout/stderr重定向终极指南
如何高效捕获yargs命令行工具的输出:stdout/stderr重定向终极指南 在开发命令行应用时,高效处理和捕获程序输出是一项关键技能。yargs作为现代、
物联网嵌入式操作系统实时系统猫抓浏览器插件:终极免费资源嗅探工具,轻松下载网页媒体资源
猫抓浏览器插件:终极免费资源嗅探工具,轻松下载网页媒体资源 你是否曾在浏览网页时遇到心仪的视频、音频或图片,却苦于无法保存?猫抓浏览器插件就是你的终极解决方案!
物联网嵌入式操作系统实时系统RIOT 中 PCA9633 I2C PWM 控制器的驱动测试指南:基于 Shell 命令的 LED 调光与闪烁实操
RIOT 中 PCA9633 I2C PWM 控制器的驱动测试指南:基于 Shell 命令的 LED 调光与闪烁实操 PCA9633 是 NXP 推出的一款 4
物联网嵌入式操作系统实时系统
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考