2. 显示ASCII字符
任务说明
本案例目标是在LCD TFT显示屏上显示字符串“Hello World”。为此需要完成两项核心工作:一是从标准ASCII码表中提取字符点阵数据,建立字符库;二是实现字符与字符串显示函数,将点阵数据写入LCD显存。最终通过调用显示函数在屏幕上呈现目标字符串。
字符点阵提取原理
ASCII字符显示的本质是将每个字符映射为固定尺寸的点阵图案。本案例采用8×16点阵格式,即每个字符由16个字节表示,每个字节的8个bit对应字符的一行像素(bit为1时点亮,为0时熄灭)。标准ASCII码表(0x20~0x7F)共96个可打印字符,每个字符16字节,完整字库大小为1536字节。
字库数据的提取方式:从标准ASCII码表(如系统自带字体文件或公开字库)中,按字符编码顺序(从0x20空格开始)依次取出每个字符的16字节点阵数据,按顺序排列成数组。显示时,通过 (char_code - 0x20) * 16 计算该字符在字库数组中的起始偏移,即可定位到对应点阵数据。
硬件接口与坐标映射
本案例假设LCD控制器为ILI9341(常见TFT屏),分辨率240×320,RGB565颜色格式。显示字符时,将字符点阵的每个bit映射到屏幕上的一个像素点:点阵行号对应屏幕Y坐标偏移,点阵列号对应屏幕X坐标偏移。字符显示区域为8像素宽、16像素高。
代码实现
以下代码实现了完整的ASCII字符显示功能。代码分为三个部分:字库数据(仅展示部分字符)、字符显示函数、字符串显示函数。字库数据完整版需包含0x20~0x7F共96个字符,此处为节省篇幅仅列出'H'、'e'、'l'、'o'、'W'、'r'、'd'等所需字符,实际使用时需替换为完整字库。
// font8x16.h - 8x16 ASCII字库头文件
#ifndef FONT8X16_H
#define FONT8X16_H
#include <stdint.h>
// 字库数据: 按ASCII码顺序存储, 每个字符16字节
// 索引方式: (ch - 0x20) * 16
// 此处仅列出"Hello World"所需字符, 完整字库需包含0x20-0x7F全部96个字符
const uint8_t font8x16[] = {
// 0x20 空格
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x48 'H'
0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,
// 0x65 'e'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6C 'l'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x6F 'o'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x57 'W'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x72 'r'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
// 0x64 'd'
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif // FONT8X16_H
// lcd_ascii.c - ASCII字符显示实现
#include "lcd_ascii.h"
#include "font8x16.h"
// 在指定位置显示一个ASCII字符
// x: 字符左上角X坐标
// y: 字符左上角Y坐标
// ch: 要显示的字符
// color: 前景色(RGB565)
// bgcolor: 背景色(RGB565)
void LCD_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgcolor)
{
uint8_t i, j;
uint8_t temp;
uint16_t char_index;
// 计算字符在字库中的偏移
// 仅支持可打印字符(0x20-0x7F)
if (ch < 0x20 || ch > 0x7F) {
ch = ' '; // 不支持的控制字符显示为空格
}
char_index = (ch - 0x20) * 16;
// 逐行扫描点阵数据
for (i = 0; i < 16; i++) {
temp = font8x16[char_index + i]; // 取第i行点阵数据
// 逐位扫描, bit7对应最左侧像素
for (j = 0; j < 8; j++) {
if (temp & (0x80 >> j)) {
// bit为1, 画前景色像素
LCD_DrawPoint(x + j, y + i, color);
} else {
// bit为0, 画背景色像素
LCD_DrawPoint(x + j, y + i, bgcolor);
}
}
}
}
// 在指定位置显示字符串
// x: 起始X坐标
// y: 起始Y坐标
// str: 要显示的字符串
// color: 前景色
// bgcolor: 背景色
void LCD_ShowString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgcolor)
{
while (*str) {
// 显示当前字符
LCD_ShowChar(x, y, *str, color, bgcolor);
// 移动到下一个字符位置 (字符宽度8像素 + 2像素间距)
x += 10;
// 检查是否超出屏幕右边界 (假设宽度240)
if (x > 232) {
x = 0; // 换行
y += 20; // 下一行 (字符高度16 + 4像素行距)
}
str++; // 指向下一个字符
}
}
// lcd_ascii.h - 接口声明
#ifndef LCD_ASCII_H
#define LCD_ASCII_H
#include <stdint.h>
// LCD底层驱动函数(由平台相关代码提供)
void LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t color);
// ASCII显示接口
void LCD_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bgcolor);
void LCD_ShowString(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bgcolor);
#endif // LCD_ASCII_H
// main.c - 主函数调用示例
#include "lcd_ascii.h"
#include "lcd_init.h" // LCD初始化函数
int main(void)
{
// LCD初始化 (由平台相关代码实现)
LCD_Init();
// 清屏为黑色
LCD_Clear(0x0000);
// 在屏幕中央显示 "Hello World"
// 白色文字, 黑色背景
// 屏幕宽度240, 字符串11字符, 每个字符占10像素(含间距)
// 总宽度 = 11*10 - 2 = 108, 起始X = (240-108)/2 = 66
// 屏幕高度320, 字符高16, 起始Y = (320-16)/2 = 152
LCD_ShowString(66, 152, "Hello World", 0xFFFF, 0x0000);
while (1) {
// 主循环
}
return 0;
}
关键实现说明
字库索引计算:每个字符的起始位置通过 (ch - 0x20) * 16 计算。例如字符'H'(0x48)的偏移为 (0x48-0x20)*16 = 0x280,即字库数组的第640字节开始。这种线性索引方式使得任意字符的查找时间为O(1)。
点阵到像素映射:显示函数逐行读取字库字节,对每个字节的8个bit逐位判断。bit7对应字符最左侧像素,bit0对应最右侧像素。bit为1时绘制前景色,为0时绘制背景色,从而实现字符与背景的区分。
字符串布局:字符间距设为2像素(每个字符占10像素宽度),行距设为4像素(每行占20像素高度)。当字符超出屏幕右边界时自动换行。
编译与运行
本案例代码需要与LCD底层驱动(如ILI9341初始化、画点函数)配合使用。编译时需包含以下文件:
font8x16.h— 字库数据(需替换为完整96字符字库)lcd_ascii.c/h— ASCII显示函数lcd_init.c/h— LCD初始化与底层画点函数(平台相关)main.c— 主程序入口
验证方法
功能验证:编译烧录后,观察LCD屏幕中央是否显示白色文字“Hello World”。字符应清晰可辨,无乱码或错位。
判定标准:
- 屏幕中央显示“Hello World”字符串,文字为白色、背景为黑色;
- 字符尺寸为8×16像素,字符间距均匀;
- 字符串整体水平居中(起始X坐标66,总宽108,左右留白66像素)。
预期输出:LCD屏幕中央显示白色“Hello World”文字,背景为黑色,文字清晰无花屏。