基于STM32的ST7789屏幕驱动


前言

在这篇文章中,我们将示范如何使用 STM32 微控制器驱动ST7789 显示器。我们会逐步介绍如何初始化 GPIO 和 SPI 接口,发送命令和数据,并完成显示器的基本操作,如清屏和窗口设置。


提示:以下是本篇文章正文内容,下面案例可供参考

一、ST7789是什么?

ST7789 是一种常用的图形 LCD 驱动芯片,广泛用于嵌入式系统中的显示器。

二、使用步骤

1.GPIO 初始化

首先,我们需要初始化 GPIO 引脚,以便与 ST7789 显示器进行通信。

// GPIO 初始化函数
void ST7789_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能 GPIOA 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // 配置 SPI 引脚
    GPIO_InitStructure.GPIO_Pin = SPI1_SCK_PIN | SPI1_MOSI_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置控制引脚
    GPIO_InitStructure.GPIO_Pin = SPI1_CS_PIN | SPI1_RES_PIN | SPI1_DC_PIN | SPI1_BLK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 置位引脚
    GPIO_SetBits(GPIOA, SPI1_CS_PIN | SPI1_RES_PIN | SPI1_DC_PIN | SPI1_BLK_PIN);
}

2. SPI 初始化

接下来,配置 SPI 接口以便数据传输。

// SPI 初始化函数
void ST7789_SPI_Init(void) {
    SPI_InitTypeDef SPI_InitStructure;

    // 使能 SPI1 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    // 配置 SPI 参数
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 10;
    SPI_Init(SPI1, &SPI_InitStructure);

    // 使能 SPI
    SPI_Cmd(SPI1, ENABLE);
}

3. 写入 SPI 数据

我们需要函数来通过 SPI 发送数据。

// 写入 SPI 数据函数
void SPI_Write(uint8_t data) {
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, data);
    while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    (void)SPI_I2S_ReceiveData(SPI1);
}

4. 写入 SPI 数据

// ST7789 写入命令函数
void ST7789_WriteCommand(uint8_t cmd) {
    GPIO_ResetBits(GPIOA, SPI1_DC_PIN); // 选择命令模式
    GPIO_ResetBits(GPIOA, SPI1_CS_PIN); // 选择显示器
    SPI_Write(cmd); // 发送命令
    GPIO_SetBits(GPIOA, SPI1_CS_PIN); // 取消选择显示器
}

// ST7789 写入数据函数
void ST7789_WriteData(uint8_t data) {
    GPIO_SetBits(GPIOA, SPI1_DC_PIN); // 选择数据模式
    GPIO_ResetBits(GPIOA, SPI1_CS_PIN); // 选择显示器
    SPI_Write(data); // 发送数据
    GPIO_SetBits(GPIOA, SPI1_CS_PIN); // 取消选择显示器
}

5. 初始化 ST7789 显示器

// ST7789 初始化函数
void ST7789_Init(void) {
    // 复位显示器
    GPIO_ResetBits(GPIOA, SPI1_RES_PIN);
    Delay(100); // 延时100ms
    GPIO_SetBits(GPIOA, SPI1_RES_PIN);
    Delay(100); // 延时100ms

    // 发送初始化命令
    ST7789_WriteCommand(0x01); // 软件复位
    Delay(150); // 延时150ms
    ST7789_WriteCommand(0x11); // 退出睡眠模式
    Delay(255); // 延时255ms

    ST7789_WriteCommand(0x36); // 内存数据访问控制
    ST7789_WriteData(0x00);    // 设置显示方向为0度(横屏)

    ST7789_WriteCommand(0x3A); // 设置颜色格式
    ST7789_WriteData(0x05);    // 8位颜色格式

    ST7789_WriteCommand(0xB2); // 设置帧率控制
    ST7789_WriteData(0x0C);
    ST7789_WriteData(0x0C);
    ST7789_WriteData(0x00);
    ST7789_WriteData(0x33);
    ST7789_WriteData(0x33);

    ST7789_WriteCommand(0xB7); // 设置电源控制
    ST7789_WriteData(0x35);

    ST7789_WriteCommand(0xBB); // 电量控制
    ST7789_WriteData(0x1A);

    ST7789_WriteCommand(0xC0); // 电源控制
    ST7789_WriteData(0x2C);

    ST7789_WriteCommand(0xC2); // VDV 和 VRH 设置
    ST7789_WriteData(0x01);

    ST7789_WriteCommand(0xC3); // VRH 设置
    ST7789_WriteData(0x12);    // 设置VRH

    ST7789_WriteCommand(0xC4); // VDV 设置
    ST7789_WriteData(0x20);

    ST7789_WriteCommand(0xC6); // 帧率控制
    ST7789_WriteData(0x0F);

    ST7789_WriteCommand(0xD0); // 电源控制
    ST7789_WriteData(0xA4);
    ST7789_WriteData(0xA1);

    ST7789_WriteCommand(0xE0); // 正极伽玛校正
    ST7789_WriteData(0xD0);
    ST7789_WriteData(0x04);
    ST7789_WriteData(0x0D);
    ST7789_WriteData(0x11);
    ST7789_WriteData(0x13);
    ST7789_WriteData(0x2B);
    ST7789_WriteData(0x3F);
    ST7789_WriteData(0x54);
    ST7789_WriteData(0x4C);
    ST7789_WriteData(0x18);
    ST7789_WriteData(0x0D);
    ST7789_WriteData(0x0B);
    ST7789_WriteData(0x1F);
    ST7789_WriteData(0x23);

    ST7789_WriteCommand(0xE1); // 负极伽玛校正
    ST7789_WriteData(0xD0);
    ST7789_WriteData(0x04);
    ST7789_WriteData(0x0C);
    ST7789_WriteData(0x11);
    ST7789_WriteData(0x13);
    ST7789_WriteData(0x2C);
    ST7789_WriteData(0x3F);
    ST7789_WriteData(0x44);
    ST7789_WriteData(0x51);
    ST7789_WriteData(0x2F);
    ST7789_WriteData(0x1F);
    ST7789_WriteData(0x1F);
    ST7789_WriteData(0x20);
    ST7789_WriteData(0x23);

    ST7789_WriteCommand(0x21); // 打开反显

    ST7789_WriteCommand(0x29); // 打开显示
    Delay(100);

    // 设置列地址
    ST7789_WriteCommand(0x2A); // 列地址设置
    ST7789_WriteData(0x00); // 起始列地址高位
    ST7789_WriteData(0x00); // 起始列地址低位
    ST7789_WriteData(0x00); // 结束列地址高位
    ST7789_WriteData(0xEF); // 结束列地址低位(240 列)

    // 设置行地址
    ST7789_WriteCommand(0x2B); // 行地址设置
    ST7789_WriteData(0x00); // 起始行地址高位
    ST7789_WriteData(0x00); // 起始行地址低位
    ST7789_WriteData(0x00); // 结束行地址高位
    ST7789_WriteData(0xC5); // 结束行地址低位(198 行)

    ST7789_WriteCommand(0x2C); // 内存写入
}

6. 设置显示窗口

// 设置显示窗口函数
void ST7789_SetWindows(uint16_t xStar, uint16_t yStar, uint16_t xEnd, uint16_t yEnd) {
    ST7789_WriteCommand(0x2A); // 列地址设置
    ST7789_WriteData(xStar >> 8); // 起始列地址高位
    ST7789_WriteData(xStar & 0xFF); // 起始列地址低位
    ST7789_WriteData(xEnd >> 8); // 结束列地址高位
    ST7789_WriteData(xEnd & 0xFF); // 结束列地址低位

    ST7789_WriteCommand(0x2B); // 行地址设置
    ST7789_WriteData(yStar >> 8); // 起始行地址高位
    ST7789_WriteData(yStar & 0xFF); // 起始行地址低位
    ST7789_WriteData(yEnd >> 8); // 结束行地址高位
    ST7789_WriteData(yEnd & 0xFF); // 结束行地址低位

    ST7789_WriteCommand(0x2C); // 内存写入
}

7. 清除屏幕

// 清除屏幕函数
void ST7789_Clear(uint16_t color) {
    uint32_t i;
    ST7789_SetWindows(0, 0, 239, 197); // 设置窗口为整个屏幕

    GPIO_SetBits(GPIOA, SPI1_DC_PIN); // 选择数据模式
    GPIO_ResetBits(GPIOA, SPI1_CS_PIN); // 选择显示器

    // 使用块写入的方法来提高效率
    for (i = 0; i < 240 * 198; i++) {
        SPI_Write(color >> 8); // 写入高字节
        SPI_Write(color & 0xFF); // 写入低字节
    }

    GPIO_SetBits(GPIOA, SPI1_CS_PIN); // 取消选择显示器
}

总结

通过上述步骤,我们实现了 STM32 对 ST7789 显示屏的初始化与基本控制。掌握这些基本操作后,可以进一步实现更复杂的图形显示功能,如绘制图像、文字显示等。在实际开发中,还需要根据具体应用调整显示参数和优化代码性能。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于STM32ST7789驱动代码示例(使用SPI通信): 首先,需要在代码中包含SPI和GPIO库的头文件: ```c #include "stm32f4xx_spi.h" #include "stm32f4xx_gpio.h" ``` 然后定义SPI接口和GPIO引脚,这里以SPI1和GPIOB为例: ```c #define LCD_SPI SPI1 #define LCD_GPIO GPIOB #define LCD_DC_PIN GPIO_Pin_0 #define LCD_CS_PIN GPIO_Pin_1 #define LCD_RST_PIN GPIO_Pin_2 ``` 接着,初始化SPI和GPIO: ```c void LCD_SPI_Init(void) { SPI_InitTypeDef SPI_InitStruct; GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // 配置SPI1的SCK、MISO、MOSI引脚 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStruct); // 将SCK、MISO、MOSI引脚映射到SPI1 GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1); GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1); // 配置片选、复位、数据/命令引脚 GPIO_InitStruct.GPIO_Pin = LCD_DC_PIN | LCD_CS_PIN | LCD_RST_PIN; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(LCD_GPIO, &GPIO_InitStruct); // 初始化SPI1 SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStruct.SPI_Mode = SPI_Mode_Master; SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStruct.SPI_CRCPolynomial = 7; // CRC校验多项式,不使用CRC校验时可以不设置 SPI_Init(LCD_SPI, &SPI_InitStruct); // 使能SPI1 SPI_Cmd(LCD_SPI, ENABLE); // 初始化LCD复位引脚 GPIO_SetBits(LCD_GPIO, LCD_RST_PIN); DelayMs(5); GPIO_ResetBits(LCD_GPIO, LCD_RST_PIN); DelayMs(20); GPIO_SetBits(LCD_GPIO, LCD_RST_PIN); DelayMs(150); } ``` 其中,`DelayMs`是一个自定义的函数,用于延迟一定的时间,可以根据实际情况自行实现。 接下来,定义发送数据和发送命令的函数: ```c void LCD_SPI_SendData(uint8_t data) { while (SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(LCD_SPI, data); while (SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_RXNE) == RESET); SPI_I2S_ReceiveData(LCD_SPI); } void LCD_SendCommand(uint8_t cmd) { GPIO_ResetBits(LCD_GPIO, LCD_DC_PIN); GPIO_ResetBits(LCD_GPIO, LCD_CS_PIN); LCD_SPI_SendData(cmd); GPIO_SetBits(LCD_GPIO, LCD_CS_PIN); } void LCD_SendData(uint8_t data) { GPIO_SetBits(LCD_GPIO, LCD_DC_PIN); GPIO_ResetBits(LCD_GPIO, LCD_CS_PIN); LCD_SPI_SendData(data); GPIO_SetBits(LCD_GPIO, LCD_CS_PIN); } ``` 这里的`LCD_SendCommand`和`LCD_SendData`函数分别用于发送命令和数据,通过设置和清除`DC`引脚的电平来区分。 最后,就可以通过这些函数来操作ST7789液晶屏了,例如初始化屏幕: ```c void LCD_Init(void) { LCD_SPI_Init(); LCD_SendCommand(0x11); // sleep out DelayMs(120); LCD_SendCommand(0x36); // MADCTL (Memory Access Control) LCD_SendData(0x00); // row address order: top to bottom LCD_SendData(0x00); // column address order: left to right LCD_SendData(0xC0); // RGB color filter panel, vertical refresh order: top to bottom LCD_SendCommand(0x3A); // COLMOD (Interface Pixel Format) LCD_SendData(0x05); // 16-bit RGB, 65K colors LCD_SendCommand(0xB2); // PORCTRL (PORch control) LCD_SendData(0x0C); // VREG1OUT voltage = 4.1V LCD_SendData(0x0C); // VDV (VCOM Dynamic Driving Voltage) = VREG1OUT x 0.75 LCD_SendData(0x00); // VCM (VCOM voltage) = VREG1OUT x 0.75 LCD_SendData(0x33); // VDVAC (VDVAC amplitude) = VREG1OUT x 1.6 LCD_SendCommand(0xB7); // GCTRL (Gate Control) LCD_SendData(0x35); // VGH (Gate High voltage) = VREG1OUT x 3.0 LCD_SendData(0x35); // VGL (Gate Low voltage) = -VREG1OUT x 3.0 LCD_SendCommand(0xBB); // VCOMS (VCOM setting) LCD_SendData(0x1E); // VCOMS = -1.025V LCD_SendCommand(0xC0); // LCMCTRL (LCM Control) LCD_SendData(0x2C); // LCD Driving waveform control: no inversion LCD_SendData(0x2D); // Source output level: VCOMH - 1.05V LCD_SendData(0x07); // LCD display line number: 320 LCD_SendCommand(0xC2); // VDVVRHEN (VDV and VRH Command Enable) LCD_SendData(0x01); // enable VDV and VRH registers LCD_SendCommand(0xC3); // VRHS (VRH Set) LCD_SendData(0x11); // VAP (VCOM alternating amplitude) = VREG1OUT x 0.9 LCD_SendData(0x02); // VDV (VCOM Dynamic Driving Voltage) = VREG1OUT x 0.75 LCD_SendCommand(0xC4); // VDVS (VDV Set) LCD_SendData(0x20); // VDV (VCOM Dynamic Driving Voltage) LCD_SendCommand(0xC6); // FRCTRL2 (Frame Rate control in normal mode) LCD_SendData(0x0F); // 60Hz, inversion off LCD_SendCommand(0xD0); // PWCTRL1 (Power Control 1) LCD_SendData(0xA4); // AVDD = VREG1OUT x 2.4 LCD_SendData(0xA1); // AVEE = -VREG1OUT x 2.4 LCD_SendData(0x00); // VCL = VREG1OUT x 1.8 LCD_SendCommand(0xE0); // PGAMCTRL (Positive Gamma Control) LCD_SendData(0xD0); LCD_SendData(0x08); LCD_SendData(0x11); LCD_SendData(0x08); LCD_SendData(0x0C); LCD_SendData(0x15); LCD_SendData(0x39); LCD_SendData(0x33); LCD_SendData(0x50); LCD_SendData(0x36); LCD_SendData(0x13); LCD_SendData(0x14); LCD_SendData(0x29); LCD_SendData(0x2d); LCD_SendData(0x2A); LCD_SendCommand(0xE1); // NGAMCTRL (Negative Gamma Control) LCD_SendData(0xD0); LCD_SendData(0x08); LCD_SendData(0x10); LCD_SendData(0x08); LCD_SendData(0x06); LCD_SendData(0x06); LCD_SendData(0x39); LCD_SendData(0x44); LCD_SendData(0x51); LCD_SendData(0x0B); LCD_SendData(0x16); LCD_SendData(0x14); LCD_SendData(0x2F); LCD_SendData(0x31); LCD_SendData(0x2A); LCD_SendCommand(0x29); // display on } ``` 这里的初始化代码可以根据实际情况进行修改,具体的命令和参数可以参考ST7789的数据手册。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值