news 2026/4/16 13:30:45

基于Keil的LCD显示程序编写指南:新手实战入门

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Keil的LCD显示程序编写指南:新手实战入门

从零开始点亮LCD:基于Keil与STM32的实战驱动指南

你有没有过这样的经历?手里的开发板已经焊好,电源灯亮了,但屏幕却一片漆黑——不是坏了,而是你还没“唤醒”它。

在嵌入式世界里,让第一行文字出现在屏幕上,就像程序员写下的第一个Hello World!一样具有仪式感。而今天我们要做的,就是用最基础的方式,在一块常见的1602字符型LCD屏上,显示属于你的第一句问候。

整个过程将围绕Keil MDK + STM32展开,不依赖图形库、不调用复杂框架,只靠C语言和对时序的理解,亲手写出驱动代码。这不仅是一次入门训练,更是一场深入硬件底层的思维历练。


为什么是1602 LCD?因为它够“原始”,也够真实

市面上的显示屏五花八门:OLED炫酷、TFT多彩、触摸屏智能……但它们的背后,往往藏着层层抽象。对于初学者来说,直接上手这些高级模块,容易陷入“会用不会懂”的困境。

HD44780控制器驱动的1602 LCD不同。它没有SPI或I²C的“优雅”接口,也没有自动刷新机制。你要亲自控制每一个引脚、模拟每一个脉冲、等待每一段延时。正是这种“笨拙”,让我们得以看清人机交互最本质的一面:

显示,本质上是精确时序下的电平变化

这块屏只有16列×2行,只能显示ASCII字符,但它能教会你比任何高端屏幕都多的东西。


核心组件速览:搞清楚我们面对的是谁

参数
控制器HD44780 或兼容芯片
接口类型并行(8位/4位可选)
工作电压5V(部分支持3.3V逻辑输入)
关键引脚RS, R/W, E, D0~D7
显示容量2×16 字符
内置字符集标准 ASCII + 自定义符号(CGROM)

其中最关键的三个控制信号:

  • RS(Register Select):决定当前操作是命令(RS=0)还是数据(RS=1)
  • R/W(Read/Write):通常接地设为写模式(因为我们很少读状态)
  • E(Enable):上升沿锁存数据,必须精准触发

数据总线可以工作在8位全宽模式4位半宽模式。本文采用后者,原因很简单:省IO。

STM32F103C8T6这类常用MCU的GPIO资源并不富裕,使用4位模式只需占用6个IO(RS、E + D4~D7),性价比极高。


驱动原理拆解:LCD是怎么“听懂”指令的?

别被“控制器”这个词吓到。HD44780其实像个固执的老工匠——你得按它的规矩来,一步都不能乱。

第一步:上电稳定

刚通电时,LCD内部电路处于不确定状态。必须等待至少15ms,等电源爬升到位。这是很多新手忽略的第一坑:程序跑得太快,LCD还没醒。

第二步:进入4位模式

有趣的是,即使你想用4位模式,初始化也必须通过发送三次0x3来“唤醒”。这个设计源于早期硬件兼容性需求,如今成了必经流程:

发 0x3 → 等 >4.1ms 发 0x3 → 等 >100μs 发 0x3 → 再发 0x2 表示切换至4位数据长度

完成后,才能开始正常通信。

第三步:功能设置

接下来发送0x28指令,含义如下:

bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 0 0 1 0 DL=1 N=1 F=0 X

其中:
-DL=1:数据长度为4位
-N=1:双行显示
-F=0:字符点阵为5×8

这条指令决定了屏幕的基本形态。

第四步:开启显示

最后通过0x0C开启显示并关闭光标(若不需要闪烁光标)。至此,LCD才真正准备好接收内容。

整个过程像极了一台老式收音机:先预热,再调频,最后打开扬声器。


Keil工程搭建:从新建项目到烧录运行

虽然现在有STM32CubeIDE等集成环境,但Keil μVision仍是许多工程师心中的“白月光”——轻量、稳定、调试直观。

创建工程步骤简述:

  1. 打开Keil,选择New uVision Project
  2. 选定目标芯片,如STM32F103C8
  3. 添加启动文件(startup_stm32f103xb.s)
  4. 包含HAL库或标准外设库(本文使用HAL)
  5. 设置包含路径:Inc,Drivers/CMSIS/*,Drivers/STM32F1xx_HAL_Driver/*
  6. 配置晶振频率(HSE=8MHz)、优化等级(-O0便于调试)

编译器推荐使用Arm Compiler 6,对C99支持更好,语法更现代。


关键代码详解:每一行都在和硬件对话

下面这段代码不是复制粘贴就能成功的魔法咒语,而是你与LCD之间的“摩尔斯电码”。

引脚定义清晰化

// lcd.h #define LCD_RS_PIN GPIO_PIN_0 #define LCD_RW_PIN GPIO_PIN_1 #define LCD_E_PIN GPIO_PIN_2 #define LCD_DATA_PORT GPIOB #define LCD_CTRL_PORT GPIOB // 数据端口宏定义(高4位 D4-D7) #define LCD_DATA_MASK 0xF0

这里假设所有控制线和数据线都接在GPIOB上。实际布线时应尽量集中,减少走线干扰。


脉冲信号生成:E引脚的艺术

static void LCD_EnablePulse(void) { HAL_GPIO_WritePin(LCD_CTRL_PORT, LCD_E_PIN, GPIO_PIN_SET); Delay_us(1); // 高电平持续至少1μs HAL_GPIO_WritePin(LCD_CTRL_PORT, LCD_E_PIN, GPIO_PIN_RESET); Delay_us(50); // 下降沿后保持稳定期 }

这个小小的脉冲,就是通知LCD:“嘿,看我刚刚送来的数据!”

注意两个延时:tdsw(数据建立时间)和tdh(数据保持时间),必须满足手册要求。


半字节传输函数:4位模式的核心

static void LCD_Write4Bits(uint8_t data) { // 清除原数据位(利用BSRR低16位清零,高16位置1) LCD_DATA_PORT->BSRR = (LCD_DATA_MASK << 16); // 逐位写入高4位 if (data & 0x10) LCD_DATA_PORT->BSRR = GPIO_PIN_4; if (data & 0x20) LCD_DATA_PORT->BSRR = GPIO_PIN_5; if (data & 0x40) LCD_DATA_PORT->BSRR = GPIO_PIN_6; if (data & 0x80) LCD_DATA_PORT->BSRR = GPIO_PIN_7; LCD_EnablePulse(); // 触发锁存 }

这里用了STM32特有的BSRR寄存器实现原子级写操作,避免中间状态被干扰。


命令与数据分离:RS是关键

void LCD_WriteCmd(uint8_t cmd) { HAL_GPIO_WritePin(LCD_CTRL_PORT, LCD_RS_PIN, GPIO_PIN_RESET); // 命令模式 HAL_GPIO_WritePin(LCD_CTRL_PORT, LCD_RW_PIN, GPIO_PIN_RESET); // 写操作 LCD_Write4Bits(cmd & 0xF0); // 发送高4位 LCD_Write4Bits((cmd << 4) & 0xF0); // 发送低4位 // 不同命令执行时间不同 if (cmd <= 3) Delay_ms(5); else Delay_ms(1); }

你会发现有些指令(如清屏0x01)需要较长延迟,因为它们涉及内部内存重置。


初始化流程:不能跳过的仪式

void LCD_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); // 配置控制引脚 GPIO_InitStruct.Pin = LCD_RS_PIN | LCD_RW_PIN | LCD_E_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LCD_CTRL_PORT, &GPIO_InitStruct); // 配置数据引脚 D4-D7 GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; HAL_GPIO_Init(LCD_DATA_PORT, &GPIO_InitStruct); Delay_ms(30); // 上电延时 // 进入4位模式三连击 LCD_Write4Bits(0x30); Delay_ms(5); LCD_Write4Bits(0x30); Delay_us(150); LCD_Write4Bits(0x30); LCD_Write4Bits(0x20); // 切换为4位模式 Delay_ms(1); // 正式配置 LCD_WriteCmd(0x28); // 4位、双行、5x8点阵 LCD_WriteCmd(0x08); // 关闭显示 LCD_WriteCmd(0x01); // 清屏 LCD_WriteCmd(0x06); // 地址自增,无移位 LCD_WriteCmd(0x0C); // 开启显示,关闭光标 }

这一段顺序严格,不可颠倒。尤其是那三个0x3,少了任何一个,LCD都不会回应。


主函数登场:终于能看到成果

int main(void) { HAL_Init(); SystemClock_Config(); // 72MHz主频 Delay_Init(); // 基于SysTick的微秒延时 LCD_Init(); LCD_Print("Hello World!"); LCD_SetCursor(1, 0); // 第二行起始位置 LCD_Print("Keil & STM32"); while (1) { // 主循环空转 } }

几分钟后,当你看到那两行字静静躺在蓝绿背景上,你会明白:这不是简单的输出,这是你第一次真正“指挥”了硬件。


坑点与秘籍:那些手册不会明说的事

🔌 电源噪声导致乱码?

在VDD和GND之间加一个0.1μF陶瓷电容,紧挨LCD模块。开关电源的纹波足以让HD44780误判数据。

🎚 对比度调不出来?

V0引脚不要直接接地或接VCC。使用10kΩ可调电阻构成分压电路,中间抽头接V0,否则可能全黑或全白。

⚡ 3.3V MCU驱动5V LCD?

虽然部分LCD模块允许3.3V输入,但为了可靠,建议:
- 使用上拉电阻至5V(限流1kΩ以上)
- 或采用专用电平转换芯片(如TXS0108E)

🕳 写完内容出现“鬼影”?

避免频繁清屏。每次0x01指令耗时约1.52ms,在此期间不能再发其他命令。可用空格覆盖代替清屏。

⏱ 延时不准确怎么办?

确保Delay_Init()正确配置SysTick。若系统时钟非72MHz,需重新计算计数值。


它还能做什么?不止是“Hello World”

一旦掌握了基本驱动,你可以轻松扩展出更多实用功能:

  • 动态显示传感器数据(温度、湿度、电压)
  • 实现简易菜单系统(配合按键)
  • 显示倒计时、状态提示、错误码
  • 自定义字符(比如画个电池图标、箭头)

甚至可以用它做教学演示平台,让学生亲手体验“从0到1”的完整开发链路。


写在最后:简单,才是最强大的起点

也许几年后,你会开发搭载LVGL的彩色TFT界面,会做带触控反馈的工业HMI。但在那个时刻回望,最初的那块1602 LCD依然值得尊敬。

因为它教会你:
- 如何阅读数据手册
- 如何理解时序图
- 如何用代码操控物理世界

这些能力,不会随着技术迭代而过时。

所以,如果你还在犹豫该从哪里开始嵌入式之旅,不妨先买一块1602 LCD,接上杜邦线,打开Keil,写下属于你的第一行显示代码。

当那句“Hello World”终于亮起时,你就已经是一名真正的嵌入式开发者了。

如果你在实现过程中遇到了其他挑战,欢迎在评论区分享讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 13:06:50

大麦抢票全攻略:5步轻松搞定演唱会门票

大麦抢票全攻略&#xff1a;5步轻松搞定演唱会门票 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 还在为抢不到心仪演唱会门票而烦恼吗&#xff1f;大麦抢票脚本让你告别手动刷票的焦虑&#xf…

作者头像 李华
网站建设 2026/4/16 13:01:49

Unity游戏本地化完全指南:XUnity自动翻译器5大核心技巧

Unity游戏本地化完全指南&#xff1a;XUnity自动翻译器5大核心技巧 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 还在为外语游戏中的生涩对话和复杂菜单而烦恼吗&#xff1f;&#x1f3ae; 语言障碍是否…

作者头像 李华
网站建设 2026/4/16 13:01:27

3个窗口管理痛点,一个AlwaysOnTop解决方案

3个窗口管理痛点&#xff0c;一个AlwaysOnTop解决方案 【免费下载链接】AlwaysOnTop Make a Windows application always run on top 项目地址: https://gitcode.com/gh_mirrors/al/AlwaysOnTop 你是不是也经常遇到这样的场景&#xff1f;正在对照文档编写代码&#xff…

作者头像 李华
网站建设 2026/4/16 14:49:14

视频嗅探神器猫抓:轻松下载网页视频的终极指南

视频嗅探神器猫抓&#xff1a;轻松下载网页视频的终极指南 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为无法保存网页视频而烦恼吗&#xff1f;猫抓这款专业的视频嗅探工具正是你需要的解决方…

作者头像 李华
网站建设 2026/4/16 3:39:44

SAM 3实战案例:社交媒体内容自动标记系统构建

SAM 3实战案例&#xff1a;社交媒体内容自动标记系统构建 1. 背景与需求分析 随着社交媒体平台内容的爆炸式增长&#xff0c;图像和视频成为用户表达的主要形式。然而&#xff0c;海量非结构化视觉数据给内容管理、推荐系统和广告投放带来了巨大挑战。传统的人工标注方式效率…

作者头像 李华
网站建设 2026/4/16 3:23:09

网易云音乐NCM加密文件终极解密指南:让音乐重获自由

网易云音乐NCM加密文件终极解密指南&#xff1a;让音乐重获自由 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他设备播放而困扰吗&#xff1f;这款专业的NCM解密工具将彻底解决你的烦恼…

作者头像 李华