STM32并行驱动CH12864B液晶屏(ST7920控制器)方案

STM32并行驱动CH12864B液晶屏(ST7920控制器)方案


一、硬件连接配置

1. 引脚映射表
STM32引脚 功能 ST7920引脚 说明
PA0 RS(寄存器选择) RS 数据/指令选择
PA1 RW(读写控制) R/W 读操作时需拉高
PA2 E(使能信号) E 上升沿锁存数据
PA3 RST(复位) RST 低电平有效复位
PD0-PD7 数据总线 D0-D7 并行数据传输
3.3V VDD VDD 电源供电
GND GND GND 共地
2. 硬件连接注意事项

二、软件驱动实现

1. GPIO初始化
void LCD_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    // 使能GPIOA和GPIOD时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
    
    // 配置控制引脚(PA0-PA2, PA3)
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // 配置数据总线(PD0-PD7)
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All;
    GPIO_Init(GPIOD, &GPIO_InitStruct);
}
2. 忙信号检测
uint8_t LCD_CheckBusy(void) {
    GPIO_ResetBits(GPIOA, GPIO_Pin_0); // RS=0(指令寄存器)
    GPIO_ResetBits(GPIOA, GPIO_Pin_1); // RW=1(读模式)
    GPIO_SetBits(GPIOA, GPIO_Pin_2);   // E=1(使能)
    
    volatile uint8_t busy = (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_7) << 7);
    
    GPIO_ResetBits(GPIOA, GPIO_Pin_2); // E=0
    return busy;
}
3. 指令与数据写入
void LCD_WriteCmd(uint8_t cmd) {
    while(LCD_CheckBusy()); // 等待空闲
    GPIO_ResetBits(GPIOA, GPIO_Pin_1); // RW=0(写模式)
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // RS=0(指令)
    
    // 发送高4位
    GPIO_Write(GPIOD, (cmd & 0xF0) | (GPIO_ReadOutputData(GPIOD) & 0x0F));
    DelayUs(100);
    GPIO_ResetBits(GPIOA, GPIO_Pin_2); // E=0
    
    // 发送低4位
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET); // RS=0
    GPIO_Write(GPIOD, (cmd << 4) | (GPIO_ReadOutputData(GPIOD) & 0xF0));
    DelayUs(100);
    GPIO_ResetBits(GPIOA, GPIO_Pin_2); // E=0
    
    DelayMs(2); // 指令执行时间
}

void LCD_WriteData(uint8_t data) {
    while(LCD_CheckBusy());
    GPIO_SetBits(GPIOA, GPIO_Pin_1); // RW=0(写模式)
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET); // RS=1(数据)
    
    // 发送高4位
    GPIO_Write(GPIOD, (data & 0xF0) | (GPIO_ReadOutputData(GPIOD) & 0x0F));
    DelayUs(100);
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);
    
    // 发送低4位
    GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
    GPIO_Write(GPIOD, (data << 4) | (GPIO_ReadOutputData(GPIOD) & 0xF0));
    DelayUs(100);
    GPIO_ResetBits(GPIOA, GPIO_Pin_2);
    
    DelayMs(1);
}
4. 初始化流程
void LCD_Init(void) {
    DelayMs(50); // 上电延时
    
    // 复位操作
    GPIO_ResetBits(GPIOA, GPIO_Pin_3); // RST=0
    DelayMs(10);
    GPIO_SetBits(GPIOA, GPIO_Pin_3);   // RST=1
    DelayMs(10);
    
    // 功能设置:8位数据接口,基本指令集
    LCD_WriteCmd(0x30); // 0011 N=1 F=0
    DelayMs(10);
    
    // 显示控制:开显示,关光标
    LCD_WriteCmd(0x0C); // 0000 1100
    DelayMs(10);
    
    // 清屏
    LCD_WriteCmd(0x01); // 0000 0001
    DelayMs(2);
    
    // 地址指针归零
    LCD_WriteCmd(0x06); // 0000 0110(自动增量)
}

三、关键功能实现

1. 显示字符串
void LCD_DisplayString(uint8_t x, uint8_t y, const char* str) {
    uint8_t addr;
    if(y == 0) addr = 0x80 + x;    // 第一行
    else if(y == 1) addr = 0x90 + x; // 第二行
    else if(y == 2) addr = 0x88 + x; // 第三行
    else addr = 0x98 + x;          // 第四行
    
    LCD_WriteCmd(addr);            // 设置显示位置
    while(*str) {
        LCD_WriteData(*str++);
    }
}
2. 自定义字符
void LCD_CreateChar(uint8_t location, uint8_t charmap[]) {
    uint8_t i;
    LCD_WriteCmd(0x40 + location * 8); // 设置CGRAM地址
    for(i=0; i<8; i++) {
        LCD_WriteData(charmap[i]);     // 写入字符点阵
    }
}

参考代码 CH12864B的STM32并行驱动程序 ST7920控制器 www.youwenfan.com/contentcsr/101815.html

四、调试与验证

  1. 逻辑分析仪抓取时序

    • 监控RS、RW、E信号与数据总线变化
    • 验证E信号上升沿是否与数据同步
  2. 常见问题处理

    现象 解决方案
    显示乱码 检查数据总线连接与电平匹配
    无法写入指令 确认忙信号检测逻辑正确
    背光不亮 检查GPIO配置与电源连接

通过上述方案,可实现STM32与CH12864B液晶屏的高效并行通信。建议首次开发时使用J-Link调试器进行单步验证,重点关注忙信号检测与数据同步机制。

专注于matlab/simulink,电子电路,编程