4. LCD1602显示自定义字符

任务说明

LCD1602内置CGRAM(字符生成存储器),地址为0x00~0x07,共8个可自定义字符位,每个字符由8字节数据定义(每字节对应一行5个像素点,仅低5位有效)。本案例以心形图案为例,演示如何将自定义字符写入CGRAM并在屏幕上显示。

硬件连接

STC89C52 (MCU) P2.0~P2.2 → RS, RW, E P0.0~P0.7 → D0~D7 D0~D7 LCD1602 RS (4) RW (5) E (6) D0~D7 (7-14) VSS (1) → GND VDD (2) → +5V V0 (3) → 10k电位器 RS RW E 10k 电位器 V0 GND +5V V0电位器用于调节对比度

心形字符点阵定义

心形图案采用5×8点阵,每字节低5位有效(bit4~bit0对应列4~列0),8字节构成完整字符。定义如下:

// 心形图案:0x00~0x07为CGRAM地址
unsigned char code heart[] = {
    0x0E,  // 0b01110  .XXX.
    0x11,  // 0b10001  X...X
    0x1F,  // 0b11111  XXXXX
    0x0A,  // 0b01010  .X.X.
    0x0A,  // 0b01010  .X.X.
    0x11,  // 0b10001  X...X
    0x11,  // 0b10001  X...X
    0x0E   // 0b01110  .XXX.
};

完整代码实现

#include <reg52.h>
#include <string.h>

#define LCD_DATA P0
sbit RS = P2^0;
sbit RW = P2^1;
sbit E  = P2^2;

// 心形字符点阵(8字节,对应CGRAM地址0x00)
unsigned char code heart[] = {
    0x0E, 0x11, 0x1F, 0x0A,
    0x0A, 0x11, 0x11, 0x0E
};

// 延时约1ms(12MHz晶振)
void delay_ms(unsigned int n) {
    unsigned int i, j;
    for (i = 0; i < n; i++)
        for (j = 0; j < 120; j++);
}

// 检查忙标志(可选,此处用延时替代)
void lcd_ready() {
    delay_ms(2);
}

// 写命令
void lcd_cmd(unsigned char cmd) {
    lcd_ready();
    RS = 0;
    RW = 0;
    LCD_DATA = cmd;
    E = 1;
    delay_ms(1);
    E = 0;
}

// 写数据
void lcd_data(unsigned char dat) {
    lcd_ready();
    RS = 1;
    RW = 0;
    LCD_DATA = dat;
    E = 1;
    delay_ms(1);
    E = 0;
}

// 初始化LCD1602
void lcd_init() {
    delay_ms(15);
    lcd_cmd(0x38);  // 8位模式,2行,5×7点阵
    lcd_cmd(0x0C);  // 显示开,光标关
    lcd_cmd(0x06);  // 写入后地址自动加1
    lcd_cmd(0x01);  // 清屏
    delay_ms(2);
}

// 将自定义字符写入CGRAM
void lcd_write_cgram(unsigned char addr, unsigned char *pattern) {
    unsigned char i;
    lcd_cmd(0x40 | (addr << 3));  // 设置CGRAM地址(0x40 + 字符号×8)
    for (i = 0; i < 8; i++) {
        lcd_data(pattern[i]);
    }
}

// 在指定位置显示字符
void lcd_putchar(unsigned char row, unsigned char col, unsigned char ch) {
    unsigned char addr;
    if (row == 0)
        addr = 0x80 + col;
    else
        addr = 0xC0 + col;
    lcd_cmd(addr);
    lcd_data(ch);
}

void main() {
    lcd_init();
    // 将心形写入CGRAM的0号字符位
    lcd_write_cgram(0x00, (unsigned char *)heart);
    // 清屏后显示
    lcd_cmd(0x01);
    delay_ms(2);
    // 在第一行第3列显示心形(字符码0x00)
    lcd_putchar(0, 2, 0x00);
    // 在第一行第7列再显示一个心形
    lcd_putchar(0, 6, 0x00);
    while (1);
}

编译与烧录

使用Keil C51创建工程,将上述代码保存为main.c,选择芯片型号STC89C52(或AT89S52),编译生成HEX文件。使用STC-ISP软件通过串口将HEX文件烧录至单片机。

验证方法

按电路图连接硬件,V0引脚接10k电位器中间抽头以调节对比度。上电后观察LCD第一行:若在第3列和第7列各显示一个实心心形图案,且形状与点阵定义一致(上圆下尖、左右对称),则验证通过。若显示为方块或乱码,检查数据线连接和CGRAM写入时序。

判定标准

  • LCD能正常显示两行标准字符(初始化成功);
  • 心形图案轮廓清晰,无缺行或错位;
  • 修改heart[]数组中的点阵数据并重新烧录,显示图案随之变化。