使用 STM32 控制 LCD12864 显示屏:驱动与文本显示
LCD12864 是一种字符型和图形型显示屏,支持 128x64 的显示分辨率。CS (Chip Select):选择 LCD 模块。SID (Serial Data):串行数据输入线,负责传送数据。CLK (Serial Clock):串行时钟线,用于同步数据传输。通过 STM32 微控制器控制 LCD12864 显示屏,可以实现多种图形和文字显示功能。本文详细介绍了从引脚配置、命令发送到显示文
STM32 LCD12864 AIP31020 基础指令集 调试显示字符
求点赞谢谢啦ovo 关注就太感激啦! 歇歇支持啦
下一章写关于LCD12864实现绘制图像功能。
引言
在嵌入式开发中,LCD 显示屏广泛用于图形界面和文字显示。今天,我们来介绍如何用 STM32 微控制器驱动一个常见的 128x64 分辨率的 LCD 显示屏(LCD12864)。LCD12864 采用串行接口,并使用基本的命令和数据通信方式。本文将详细解析如何在 STM32 环境中驱动 LCD12864,包括引脚配置、命令发送、以及显示数据的具体实现。
LCD12864 模块简介
LCD12864 是一种字符型和图形型显示屏,支持 128x64 的显示分辨率。它使用 3 根主要控制引脚:
- CS (Chip Select):选择 LCD 模块。
- SID (Serial Data):串行数据输入线,负责传送数据。
- CLK (Serial Clock):串行时钟线,用于同步数据传输。
1. LCD 显示模式
LCD12864 支持基本指令集和扩展指令集,可以进行文字显示,也可以通过扩展指令绘制图形。通过串行通信传送的每个字节需要分为 3 个数据包进行传输,且有特定的时序要求。
具体参考说明书,设置在h文件中有说明
2. STM32 GPIO 初始化
在 STM32 微控制器中,我们需要对控制 LCD 的 GPIO 引脚进行初始化。以 STM32F1xx 为例,本次我以
//PA5 CS
//PA6 SID
//PA7 SCLK
宏定义如下
#define LCD_CS_GPIO_PIN GPIO_PIN_5 // PA5 - Chip Select
#define LCD_SID_GPIO_PIN GPIO_PIN_6 // PA6 - Serial Data (MOSI)
#define LCD_CLK_GPIO_PIN GPIO_PIN_7 // PA7 - Serial Clock
#define LCD_GPIO_PORT GPIOA
/* 12864使用的引脚定义,CS:PB13 CLK:PB15, SID:PB14 */
#define LCD_CS(a) HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_CS_GPIO_PIN, (a) ? GPIO_PIN_SET : GPIO_PIN_RESET)
#define LCD_CLK(a) HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_CLK_GPIO_PIN, (a) ? GPIO_PIN_SET : GPIO_PIN_RESET)
#define LCD_SID(a) HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_SID_GPIO_PIN, (a) ? GPIO_PIN_SET : GPIO_PIN_RESET)
/* 功能设置指令 */
#define LCD_FUNCTION_SET_BASIC 0x30 // 8位接口,基本指令集 (DL=1, RE=0) 0011 0000
#define LCD_FUNCTION_SET_EXTEND 0x34 // 8位接口,扩展指令集 (DL=1, RE=1) 0011 0100
#define LCD_FUNCTION_SET_DRAWPIC 0x36 // 拓展指令集下打开绘画显示
/* 显示控制指令 */
#define LCD_DISPLAY_OFF 0x08 // 关闭整体显示 (D=0, C=0, B=0) 0000 1000
#define LCD_DISPLAY_ON 0x0C // 打开整体显示,不显示游标 (D=1, C=0, B=0) 0000 1100
#define LCD_DISPLAY_CURSOR_ON 0x0E // 显示游标 (D=1, C=1, B=0) 0000 1110
#define LCD_DISPLAY_CURSOR_BLINK 0x0F // 显示游标 + 反白闪烁 (D=1, C=1, B=1) 0000 1111
/* 清除显示 */
#define LCD_DISPLAY_CLEAR 0x01 // 清除显示 0000 0001
只有一块LCD ,故CS 我直接保持高,
我们需要启用 GPIOA 时钟,并配置适当的引脚模式为推挽输出模式。以下是相关的 GPIO 初始化代码:
void LCD_GPIO_Init(void) {
// 启用 GPIO 端口时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 配置 CS、SID(MOSI)、SCLK 为推挽输出模式
GPIO_InitStruct.Pin = LCD_CS_GPIO_PIN | LCD_SID_GPIO_PIN | LCD_CLK_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; // 高速输出
HAL_GPIO_Init(LCD_GPIO_PORT, &GPIO_InitStruct);
// 默认拉高 CS,使 LCD 处于选中状态
HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_CS_GPIO_PIN, GPIO_PIN_SET);
// 默认 SCLK 置低,SID 数据线默认置低
HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_SID_GPIO_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_GPIO_PORT, LCD_CLK_GPIO_PIN, GPIO_PIN_RESET);
}
3.延迟函数说明
LCD 通信要求精确的时序,因此需要延时函数来控制时钟和数据传输的速度。但是延迟函数有很多种不同的显示形式,根据不同的显示形式,会有不同的设定,故最后留一个函数指针结构,需要在LCD 初始化时候对他进行指向。
typedef void(*delayus)(uint32_t us); //在h文件
extern delayus Sys_Delayus; //在h文件
//以下为c文件
delayus Sys_Delayus =NULL;
void LCD_DelayUs(uint32_t us)
{
if (Sys_Delayus != NULL) {
Sys_Delayus(us); // 调用外部的延时函数
}
}
void LCD_DelayMs(uint32_t ms)
{
while (ms--) {
LCD_DelayUs(1000); // 1 毫秒 = 1000 微秒
}
}
void LCD_Init(delayus sys_delay){
LCD_GPIO_Init();
// 确保 Sys_Delayus 指向外部的延迟函数
Sys_Delayus = sys_delay; // 将 Sys_Delayus 指向 }
}
//在main中实现
LCD_Init(My_DelayUs);
//需要根据自己的delay设定,注意是uint32 ,
//因为uint8 只支持到256,而uint16 66535 us级如果直接1ms的话直接超过了 我就用uint32 了
4. LCD 命令和数据发送
发送字节
LCD12864 通过串行接口接收命令和数据。每次传输需要 3 个字节的传输,其中包含命令的高 4 位和低 4 位。为了发送这些字节,我们需要定义一个函数来串行地将字节通过 SID 和 CLK 引脚发送出去。以下是发送字节的代码:
简单的通信 SCLK为低时变化SID,SID变化好了 将SCLK拉高
LCD_SID() 是宏定义,也可以用HAL 函数实现一样。
static void lcd_send_byte(uint8_t byte)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
LCD_CLK(0); // 拉低时钟
uint8_t bit = (byte >> (7 - i)) & 0x01; // 获取每一位数据
LCD_SID(bit); // 按位发送数据
LCD_DelayUs(5); // 延迟
LCD_CLK(1); // 拉高时钟
}
}
发送命令
LCD12864 有两类基本命令:功能设置和显示控制。我们通过串行接口发送命令来进行功能的切换和控制显示状态。
参考说明书中时序实现
以下是设置和发送命令的几个常见函数:
/**
* @brief 发送 LCD12864 指令(带 RS 和 R/W 控制)
*
* @param RS 寄存器选择位 (0 = 命令, 1 = 数据)
* @param R_W 读写控制位 (0 = 写, 1 = 读)
* @param data 要发送的指令数据(8位)
*
* @note LCD 采用 3 字节格式进行串行通信:
* - 第一个字节: 11111 R/W RS 0
* - 第二个字节: D7 D6 D5 D4 0 0 0 0
* - 第三个字节: D3 D2 D1 D0 0 0 0 0
*
* @note LCD12864 需要连续发送三个字节完成一次指令传输。
*/
void LCD_SendCommand(uint8_t RS, uint8_t R_W, uint8_t data)
{
uint8_t byte1, byte2, byte3;
// 第一个字节: 11111 R/W RS 0
byte1 = (0xf8) | (R_W << 2) | (RS << 1); // 设置 RS 和 R/W 位
// 第二个字节: D7 D6 D5 D4 0 0 0 0
byte2 = (data & 0xF0); // 提取 data 的高 4 位,低 4 位自动填 0
// 第三个字节: D3 D2 D1 D0 0 0 0 0
byte3 = (data << 4) & 0xF0; // 提取 data 的低 4 位,并左移 4 位放入高 4 位
// 发送三个字节
lcd_send_byte(byte1); // 发送第一个字节
lcd_send_byte(byte2); // 发送第二个字节
lcd_send_byte(byte3); // 发送第三个字节
}
发送指令与发送数据
/**
* @brief 发送 LCD12864 指令(固定为写入命令)
*
* @param cmd 要发送的命令(8位)
*
* @note 由于 R/W=0 RS=0,代表写入命令,此函数专门用于发送 LCD 命令。
*/
void LCD_WriteCommand(uint8_t cmd)
{
LCD_SendCommand(0, 0, cmd); // RS=0 (命令), RW=0 (写)
}
void LCD_WriteDisplayData(uint8_t data)
{
LCD_SendCommand(1, 0, data);
}
显示字符串函数说明
在 LCD12864 中显示文本是通过设置显示位置后逐个写入字符的方式实现的。每个字符占用 16x16 像素,显示的文本通常是从特定的地址(行列)开始。
/* LCD12864内部字库显示的DDRAM地址,每个地址占16*16个像素点 */
static unsigned char lcd_str_addr[4][8] = {
{0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87},
{0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97},
{0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F},
{0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F}
};
void LCD_Draw_Str(uint8_t column, uint8_t row, uint8_t *str)
{
// 设置起始位置
LCD_WriteCommand(lcd_str_addr[column][row]);
while (*str)
{
LCD_WriteDisplayData(*str++); // 逐个字符显示
}
}
LCD初始化
初始化 LCD12864 涉及多个步骤:首先配置引脚,然后初始化显示模式,最后执行一些基本的 LCD 设置。例如,选择功能集、开启显示、清屏等
void LCD_Init(delayus sys_delay)
{
LCD_GPIO_Init();
Sys_Delayus = sys_delay; // 将延迟函数传入
LCD_DelayMs(50); // 延时 50ms 等待 LCD 准备
LCD_WriteCommand(LCD_FUNCTION_SET_BASIC); // 选择基本指令集
LCD_WriteCommand(LCD_DISPLAY_ON); // 打开显示
LCD_WriteCommand(LCD_DISPLAY_CLEAR); // 清除屏幕
LCD_DelayMs(2); // 延时,确保屏幕清除完成
}
文本显示
初始化完成后,我们可以通过 LCD_Draw_Str 函数在屏幕上显示文本。例如:
LCD_Draw_Str(0, 0, "Hello, World!"); // 在第一行显示 "Hello, World!"
LCD_Draw_Str(1, 0, "STM32 LCD Test"); // 在第二行显示 "STM32 LCD Test"
总结
通过 STM32 微控制器控制 LCD12864 显示屏,可以实现多种图形和文字显示功能。本文详细介绍了从引脚配置、命令发送到显示文本的完整实现流程。通过了解 LCD12864 的工作原理和 STM32 的控制方法,开发者可以根据项目需求灵活配置显示效果,满足不同应用的需求。
希望本文能够帮助大家快速上手 STM32 控制 LCD12864 显示屏的开发。如果有任何问题或建议,欢迎留言交流!
求点赞求关注谢谢啦ovo
下一章写关于LCD12864实现绘制图像功能。
更多推荐



所有评论(0)