NOKIA 5110 显示屏驱动
1.引脚配置

c
#define LCD_SCLK_Pin GPIO_PIN_3 //时钟引脚
#define LCD_SCLK_GPIO_Port GPIOA
#define LCD_DI_Pin GPIO_PIN_4 //数据引脚
#define LCD_DI_GPIO_Port GPIOA
#define LCD_DC_Pin GPIO_PIN_5 //命令与数据引脚
#define LCD_DC_GPIO_Port GPIOA
#define LCD_RST_Pin GPIO_PIN_6 //复位引脚
#define LCD_RST_GPIO_Port GPIOA
#define LCD_SCE_Pin GPIO_PIN_7 //片选引脚
#define LCD_SCE_GPIO_Port GPIOA
/*Configure GPIO pins : LCD_SCLK_Pin LCD_DI_Pin LCD_DC_Pin LCD_RST_Pin
LCD_SCE_Pin */
GPIO_InitStruct.Pin = LCD_SCLK_Pin|LCD_DI_Pin|LCD_DC_Pin|LCD_RST_Pin
|LCD_SCE_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);2. 芯片的一些预定义
c
// LCD Commands
#define LCD_CLEARDISPLAY 0x0E
#define LCD_DISPLAYALLON 0x09
#define LCD_DISPLAYALLON_RESUME 0x0C
#define LCD_DISPLAYALLON_NORMAL 0x0A
#define LCD_DISPLAYCONTROL_NORMAL 0x0C
#define LCD_DISPLAYCONTROL_BLANK 0x08
#define LCD_DISPLAYCONTROL_INVERSE 0x0D
#define LCD_FUNCTIONSET_BASIC 0x20
#define LCD_FUNCTIONSET_EXTENDED 0x21
#define LCD_DISPLAYCONTROL 0x08
#define LCD_DISPLAYBLANK 0x08
#define LCD_DISPLAYNORMAL 0x0C
#define LCD_DISPLAYINVERTED 0x0D
#define LCD_SETYADDR 0x40
#define LCD_SETXADDR 0x80
#define LCD_TEMP_COEF 0x04
#define LCD_BIAS_MODE 0x10
#define LCD_VOP 0x80
#define LCD_POWERDOWN 0x042.初始化函数
显示屏在使用之前需要先进行初始化才行,这是必须的操作,基本上所有的显示屏都需要进行初始化.
初始化的目的是针对当前的显示屏,配置一下内部的芯片相关参数.
c
void LCD_Init(void)
{
// 硬件复位
LCD_Reset();
// 进入扩展命令模式
LCD_WriteCommand(LCD_FUNCTIONSET_EXTENDED);
// 设置LCD偏置电压
LCD_WriteCommand(LCD_BIAS_MODE | 0x02);
// 设置温度系数
LCD_WriteCommand(LCD_TEMP_COEF | 0x01);
// 设置对比度 (VOP)
LCD_WriteCommand(LCD_VOP | 0x40);
// 进入基本命令模式
LCD_WriteCommand(LCD_FUNCTIONSET_BASIC);
// 设置显示模式
LCD_WriteCommand(LCD_DISPLAYCONTROL_NORMAL);
// 清空显示
LCD_Clear();
}3. 硬件复位
c
void LCD_Reset(void)
{
HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
HAL_Delay(100);
}4. 写入数据至芯片
c
static void LCD_Write(uint8_t data, LcdCmdDataType type)
{
// 设置DC引脚,决定是命令还是数据
if (type == LCD_CMD) {
HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET); // 命令模式
} else {
HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET); // 数据模式
}
// 拉低片选,选择LCD
HAL_GPIO_WritePin(LCD_SCE_GPIO_Port, LCD_SCE_Pin, GPIO_PIN_RESET);
// 发送数据(SPI模拟)
for (uint8_t i = 0; i < 8; i++) {
// 准备数据位
if (data & 0x80) {
HAL_GPIO_WritePin(LCD_DI_GPIO_Port, LCD_DI_Pin, GPIO_PIN_SET); // 数据位为1
} else {
HAL_GPIO_WritePin(LCD_DI_GPIO_Port, LCD_DI_Pin, GPIO_PIN_RESET); // 数据位为0
}
// 时钟上升沿
HAL_GPIO_WritePin(LCD_SCLK_GPIO_Port, LCD_SCLK_Pin, GPIO_PIN_SET);
// 时钟下降沿,数据被采样
HAL_GPIO_WritePin(LCD_SCLK_GPIO_Port, LCD_SCLK_Pin, GPIO_PIN_RESET);
// 移动到下一位
data <<= 1;
}
// 拉高片选,取消选择
HAL_GPIO_WritePin(LCD_SCE_GPIO_Port, LCD_SCE_Pin, GPIO_PIN_SET);
}这个函数说明,模拟了数据传输的过程:
- 设置DC引脚,决定是命令还是数据
- 拉低片选,选择LCD
- 发送数据(SPI模拟)
- 拉高片选,取消选择
5. 写命令和写数据
c
static void LCD_WriteCommand(uint8_t cmd)
{
LCD_Write(cmd, LCD_CMD);
}
static void LCD_WriteData(uint8_t data)
{
LCD_Write(data, LCD_DATA);
}6. 清空屏幕
c
void LCD_Clear(void)
{
LCD_WriteCommand(LCD_CLEARDISPLAY);
HAL_Delay(2);
}