Skip to content

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 0x04

2.初始化函数

显示屏在使用之前需要先进行初始化才行,这是必须的操作,基本上所有的显示屏都需要进行初始化.
初始化的目的是针对当前的显示屏,配置一下内部的芯片相关参数.

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);
}

这个函数说明,模拟了数据传输的过程:

  1. 设置DC引脚,决定是命令还是数据
  2. 拉低片选,选择LCD
  3. 发送数据(SPI模拟)
  4. 拉高片选,取消选择

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);
}

7. nokia5110的完整的源代码