ST7789驱动

Posted on 2021-11-09 22:25  昨夜三更雨  阅读(4032)  评论(2编辑  收藏  举报

1. 信号线设置

主要有有6条线:

  • RESET:复位
  • CS:片选
  • DCX:数据/命令选择
  • SCK:SPI时钟线
  • SDA:数据线
  • PWR:LED背光
    这种配置下,MCU只向ST7789写数据而不读取数据。

2. SPI配置要求

  • 主模式,仅发送,8bit模式
  • 时钟极性为高,第二个边沿(上升沿)latch
  • 时钟周期不要低于16ns

3. 关键函数介绍

  • 需要根据硬件平台进行设置的函数,对应文件st7789_cfg.c/h;
void st7789_cfg_pwr_set(void);
void st7789_cfg_pwr_reset(void);
void st7789_cfg_rst_set(void);
void st7789_cfg_delay_ms(uint32_t _ms);
void st7789_cfg_rst_reset(void);
void st7789_cfg_cs_set(void);
void st7789_cfg_cs_reset(void);
void st7789_cfg_dcx_set(void);
void st7789_cfg_dcx_reset(void);
void st7789_cfg_spi_write(uint8_t *pbuf, uint16_t size);
  • 与硬件平台无关的函数(仅与上述函数相关),对应文件st7789.c/h;
void st7789_on(void);
void st7789_off(void);
void st7789_init(void);
void st7789_set_direction(uint8_t dir);
void st7789_fill
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t color
);
void st7789_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
void st7789_flush
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t *color
);

4. 代码文件

  • st7789_cfg.h
/**
 *******************************************************************************
 * @file    st7789_cfg.h
 * @author  xixizhk
 *******************************************************************************
 * @version V20211108 \n
 * Initial version.
 *******************************************************************************
 */


/* Define to prevent recursive inclusion **************************************/
#ifndef _ST7789_CFG_H
#define _ST7789_CFG_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "stm32g4xx_hal.h"
#include "main.h"
#include "spi.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

#define _ST7789_WIDTH   240
#define _ST7789_HEIGHT  240

#define _ST7789_BUFFER_SIZE  1024    /* 16-bit, less than 32768, even only */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

void st7789_cfg_pwr_set(void);
void st7789_cfg_pwr_reset(void);
void st7789_cfg_rst_set(void);
void st7789_cfg_delay_ms(uint32_t _ms);
void st7789_cfg_rst_reset(void);
void st7789_cfg_cs_set(void);
void st7789_cfg_cs_reset(void);
void st7789_cfg_dcx_set(void);
void st7789_cfg_dcx_reset(void);
void st7789_cfg_spi_write(uint8_t *pbuf, uint16_t size);

/**
 * @}
 */


#ifdef __cplusplus
}
#endif


#endif /* _ST7789_CFG_H */

/**************************** ALL RIGHTS RESERVED *****************************/
  • st7789_cfg.c
/**
 *******************************************************************************
 * @file    st7789_cfg.c
 * @author  xixizhk
 *******************************************************************************
 * @version V20211108 \n
 * Configure the low level interface for st7789.
 *******************************************************************************
 */


/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "st7789_cfg.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

/**
 * @brief   Set the PWR pin (back LED).
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_pwr_set(void)
{
    HAL_GPIO_WritePin(LCD_PWR_GPIO_Port, LCD_PWR_Pin, GPIO_PIN_SET);
}

/**
 * @brief   Reset the PWR pin (back LED).
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_pwr_reset(void)
{
    HAL_GPIO_WritePin(LCD_PWR_GPIO_Port, LCD_PWR_Pin, GPIO_PIN_RESET);
}

/**
 * @brief   Set the RESET pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_rst_set(void)
{
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET);
}

/**
 * @brief   Reset the RESET pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_rst_reset(void)
{
    HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET);
}

/**
 * @brief   Delay in ms.
 * @param   _ms [In]: number of microsecond.
 * @retval  None.
 */
void st7789_cfg_delay_ms(uint32_t _ms)
{
    /* Functions based on interrupt such as HAL_Delay() not recommended,
     * because it may result in blocking. Here, approximate delay is employed.
     */
    uint32_t i, j;
    for (i = 0; i < _ms; i++)
    {
        for (j = 0; j < 17000; j++)
        {
            ;
        }
    }
}

/**
 * @brief   Set the CS pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_cs_set(void)
{
    HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET);
}

/**
 * @brief   Reset the CS pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_cs_reset(void)
{
    HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET);
}

/**
 * @brief   Set the DCX pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_dcx_set(void)
{
    HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_SET);
}

/**
 * @brief   Reset the DCX pin.
 * @param   None.
 * @retval  None.
 */
void st7789_cfg_dcx_reset(void)
{
    HAL_GPIO_WritePin(LCD_DCX_GPIO_Port, LCD_DCX_Pin, GPIO_PIN_RESET);
}

/**
 * @brief   SPI write buffer.
 * @param   pbuf [In]: pointer to the buffer to be written.
 * @param   size [In]: size of the buffer to be written.
 * @retval  None.
 */
void st7789_cfg_spi_write(uint8_t *pbuf, uint16_t size)
{
    HAL_SPI_Transmit(&hspi1, pbuf, size, 1000);
}

/**
 * @}
 */


/**************************** ALL RIGHTS RESERVED *****************************/
  • st7789.h
/**
 *******************************************************************************
 * @file    st7789.h
 * @author  xixizhk
 *******************************************************************************
 * @version V20211108 \n
 * Initial version.
 * @version V20220406 \n
 * Direction setting function added, Read function added for snapshot required
 * by some GUI libraries (only 1-bit color supported, not verified).
 *******************************************************************************
 */


/* Define to prevent recursive inclusion **************************************/
#ifndef _ST7789_H
#define _ST7789_H

#ifdef __cplusplus
extern "C" {
#endif

/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "st7789_cfg.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

/**
 * @brief Display direction
 */
#define _ST7789_DIRECTION_NORMAL              0U
#define _ST7789_DIRECTION_XMIRROR_YMIRROR     1U
#define _ST7789_DIRECTION_XYEXCHANGE_YMIRROR  2U
#define _ST7789_DIRECTION_XYEXCHANGE_XMIRROR  3U

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

void st7789_on(void);
void st7789_off(void);
void st7789_init(void);
void st7789_set_direction(uint8_t dir);
void st7789_fill
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t color
);
void st7789_draw_pixel(uint16_t x, uint16_t y, uint16_t color);
void st7789_flush
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t *color
);

/**
 * @}
 */


#ifdef __cplusplus
}
#endif


#endif /* _ST7789_H */

/**************************** ALL RIGHTS RESERVED *****************************/
  • st7789.c
/**
 *******************************************************************************
 * @file    st7789.c
 * @author  xixizhk
 *******************************************************************************
 * @version V20211108 \n
 * Driver for st7789 (st7789v2), initial version.
 * @version V20220406 \n
 * Direction setting function added, Read function added for snapshot required
 * by some GUI libraries (only 1-bit color supported, not verified).
 *******************************************************************************
 */


/**
 *******************************************************************************
 * @addtogroup Includes
 * @{
 */

#include "st7789.h"

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Definitions
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Types
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Constants
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Variables
 * @{
 */

static uint8_t st7789_display_mode;

static uint8_t st7789_buffer[_ST7789_BUFFER_SIZE * 2];

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Macros
 * @{
 */

/**
 * @}
 */

/**
 *******************************************************************************
 * @addtogroup Functions
 * @{
 */

static void st7789_set_window
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2
);

/**
 * @brief   Write a command to st7789.
 * @param   cmd [In]: command to be sent.
 * @retval  None.
 */
static void st7789_write_cmd(uint8_t cmd)
{
    st7789_cfg_dcx_reset();
    st7789_cfg_spi_write(&cmd, 1);
}

/**
 * @brief   Write a data to st7789.
 * @param   data [In]: data to be sent.
 * @retval  None.
 */
static void st7789_write_data(uint8_t data)
{
    st7789_cfg_dcx_set();
    st7789_cfg_spi_write(&data, 1);
}

/**
 * @brief   Turn on LCD.
 * @param   None.
 * @retval  None.
 */
void st7789_on(void)
{
    st7789_cfg_pwr_set();
}

/**
 * @brief   Turn off LCD.
 * @param   None.
 * @retval  None.
 */
void st7789_off(void)
{
    st7789_cfg_pwr_reset();
}

/**
 * @brief   Initialize the LCD.
 * @param   None.
 * @retval  None.
 */
void st7789_init(void)
{
    /* Chip selection. */
    st7789_cfg_cs_reset();
    /* Reset. */
    st7789_cfg_rst_reset();
    st7789_cfg_delay_ms(200);
    st7789_cfg_rst_set();
    st7789_cfg_delay_ms(200);
    /* Sleep Out */
    st7789_write_cmd(0x11);
    /* Wait for power stability */
    st7789_cfg_delay_ms(200);

    /* RGB 5-6-5-bit  */
    st7789_write_cmd(0x3A);
    st7789_write_data(0x65);
    /* Porch Setting */
    st7789_write_cmd(0xB2);
    st7789_write_data(0x0C);
    st7789_write_data(0x0C);
    st7789_write_data(0x00);
    st7789_write_data(0x33);
    st7789_write_data(0x33);
    /* Gate Control */
    st7789_write_cmd(0xB7);
    st7789_write_data(0x35);
    /* VCOM Setting */
    st7789_write_cmd(0xBB);
    st7789_write_data(0x19);
    /* LCM Control */
    st7789_write_cmd(0xC0);
    st7789_write_data(0x2C);
    /* VDV and VRH Command Enable */
    st7789_write_cmd(0xC2);
    st7789_write_data(0x01);
    /* VRH Set */
    st7789_write_cmd(0xC3);
    st7789_write_data(0x12);
    /* VDV Set */
    st7789_write_cmd(0xC4);
    st7789_write_data(0x20);
    /* Frame Rate Control in Normal Mode */
    st7789_write_cmd(0xC6);
    st7789_write_data(0x0F);
    /* Power Control 1 */
    st7789_write_cmd(0xD0);
    st7789_write_data(0xA4);
    st7789_write_data(0xA1);
    /* Positive Voltage Gamma Control */
    st7789_write_cmd(0xE0);
    st7789_write_data(0xD0);
    st7789_write_data(0x04);
    st7789_write_data(0x0D);
    st7789_write_data(0x11);
    st7789_write_data(0x13);
    st7789_write_data(0x2B);
    st7789_write_data(0x3F);
    st7789_write_data(0x54);
    st7789_write_data(0x4C);
    st7789_write_data(0x18);
    st7789_write_data(0x0D);
    st7789_write_data(0x0B);
    st7789_write_data(0x1F);
    st7789_write_data(0x23);
    /* Negative Voltage Gamma Control */
    st7789_write_cmd(0xE1);
    st7789_write_data(0xD0);
    st7789_write_data(0x04);
    st7789_write_data(0x0C);
    st7789_write_data(0x11);
    st7789_write_data(0x13);
    st7789_write_data(0x2C);
    st7789_write_data(0x3F);
    st7789_write_data(0x44);
    st7789_write_data(0x51);
    st7789_write_data(0x2F);
    st7789_write_data(0x1F);
    st7789_write_data(0x1F);
    st7789_write_data(0x20);
    st7789_write_data(0x23);
    /* Display Inversion On */
    st7789_write_cmd(0x21);

    /* Display mode setting. */
    st7789_set_direction(_ST7789_DIRECTION_NORMAL);

    /* Display on */
    st7789_on();
    st7789_fill(0, 0, _ST7789_WIDTH - 1, _ST7789_HEIGHT - 1, 0x001F);
    st7789_write_cmd(0x29);
}

/**
 * @brief   Set display direction.
 * @param   dir [In]: Display direction, see _ST7789_DIRECTION_*.
 * @retval  None.
 */
void st7789_set_direction(uint8_t dir)
{
    switch (dir)
    {
        case _ST7789_DIRECTION_NORMAL:
            st7789_write_cmd(0x36);
            st7789_write_data(0x00);
            st7789_display_mode = _ST7789_DIRECTION_NORMAL;
            break;
        case _ST7789_DIRECTION_XMIRROR_YMIRROR:
            st7789_write_cmd(0x36);
            st7789_write_data(0xC0);
            st7789_display_mode = _ST7789_DIRECTION_XMIRROR_YMIRROR;
            break;
        case _ST7789_DIRECTION_XYEXCHANGE_YMIRROR:
            st7789_write_cmd(0x36);
            st7789_write_data(0xA0);
            st7789_display_mode = _ST7789_DIRECTION_XYEXCHANGE_YMIRROR;
            break;
        case _ST7789_DIRECTION_XYEXCHANGE_XMIRROR:
            st7789_write_cmd(0x36);
            st7789_write_data(0x60);
            st7789_display_mode = _ST7789_DIRECTION_XYEXCHANGE_XMIRROR;
            break;
        default:
            st7789_write_cmd(0x36);
            st7789_write_data(0x00);
            st7789_display_mode = _ST7789_DIRECTION_NORMAL;
            break;
    }
}

/**
 * @brief   Fill specified area with specified color (x1 <= x2, y1 <= y2).
 * @param   x1 [In]: start x.
 * @param   y1 [In]: start y.
 * @param   x2 [In]: end x.
 * @param   y2 [In]: end y.
 * @param   color [In]: color to be filled.
 * @retval  None.
 */
void st7789_fill
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t color)
{
    uint16_t size, r, i;

    size = (x2 - x1 + 1) * (y2 - y1 + 1);
    if (size > _ST7789_BUFFER_SIZE)
    {
        for (i = 0; i < _ST7789_BUFFER_SIZE; i++)
        {
            st7789_buffer[2 * i] = color >> 8;
            st7789_buffer[2 * i + 1] = color;
        }
    }
    else
    {
        for (i = 0; i < size; i++)
        {
            st7789_buffer[2 * i] = color >> 8;
            st7789_buffer[2 * i + 1] = color;
        }
    }
    
    r = size;
    st7789_set_window(x1, y1, x2, y2);
    st7789_cfg_dcx_set();
    while (1)
    {
        if (r > _ST7789_BUFFER_SIZE)
        {
            st7789_cfg_spi_write(st7789_buffer, _ST7789_BUFFER_SIZE * 2);
            r = r - _ST7789_BUFFER_SIZE;
        }
        else
        {
            st7789_cfg_spi_write(st7789_buffer, r * 2);
            break;
        }
    }
}

/**
 * @brief   Draw specified pixel with specified color.
 * @param   x [In]: x of specified pixel.
 * @param   y [In]: y of specified pixel.
 * @param   color [In]: color to be filled.
 * @retval  None.
 */
void st7789_draw_pixel(uint16_t x, uint16_t y, uint16_t color)
{
    uint8_t data[2];
    data[0] = color >> 8;
    data[1] = color;
    st7789_set_window(x, y, x, y);
    st7789_cfg_dcx_set();
    st7789_cfg_spi_write(data, 2);
}

/**
 * @brief   Flush color to specified area (x1 <= x2, y1 <= y2), for some GUI.
 * @param   x1 [In]: start x.
 * @param   y1 [In]: start y.
 * @param   x2 [In]: end x.
 * @param   y2 [In]: end y.
 * @param   color [In]: pointer to the color buffer to be flushed.
 * @retval  None.
 */
void st7789_flush
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2,
    uint16_t *color
)
{
    uint16_t size = (x2 - x1 + 1) * (y2 - y1 + 1);
    st7789_set_window(x1, y1, x2, y2);
    st7789_cfg_dcx_set();
    st7789_cfg_spi_write((uint8_t *)color, size * 2);
}

/**
 * @brief   Set window to be edited.
 *                y ^
 *                  |
 *                  |         x
 *          ------------------>
 *                  |
 *                  |
 * @param   x1 [In]: start x.
 * @param   y1 [In]: start y.
 * @param   x2 [In]: end x.
 * @param   y2 [In]: end y.
 * @retval  None.
 */
static void st7789_set_window
(
    uint16_t x1,
    uint16_t y1,
    uint16_t x2,
    uint16_t y2
)
{
    switch (st7789_display_mode)
    {
        case _ST7789_DIRECTION_NORMAL:
        case _ST7789_DIRECTION_XYEXCHANGE_XMIRROR:
            st7789_write_cmd(0x2A);
            st7789_write_data(x1 >> 8);
            st7789_write_data(x1);
            st7789_write_data(x2 >> 8);
            st7789_write_data(x2);
            st7789_write_cmd(0x2B);
            st7789_write_data(y1 >> 8);
            st7789_write_data(y1);
            st7789_write_data(y2 >> 8);
            st7789_write_data(y2);
            st7789_write_cmd(0x2C);
            break;
        case _ST7789_DIRECTION_XYEXCHANGE_YMIRROR:
            st7789_write_cmd(0x2A);
            st7789_write_data((x1 + 80) >> 8);
            st7789_write_data(x1 + 80);
            st7789_write_data((x2 + 80) >> 8);
            st7789_write_data(x2 + 80);
            st7789_write_cmd(0x2B);
            st7789_write_data(y1 >> 8);
            st7789_write_data(y1);
            st7789_write_data(y2 >> 8);
            st7789_write_data(y2);
            st7789_write_cmd(0x2C);
            break;
        case _ST7789_DIRECTION_XMIRROR_YMIRROR:
            st7789_write_cmd(0x2A);
            st7789_write_data(x1 >> 8);
            st7789_write_data(x1);
            st7789_write_data(x2 >> 8);
            st7789_write_data(x2);
            st7789_write_cmd(0x2B);
            st7789_write_data((y1 + 80) >> 8);
            st7789_write_data(y1 + 80);
            st7789_write_data((y2 + 80) >> 8);
            st7789_write_data(y2 + 80);
            st7789_write_cmd(0x2C);
            break;
        default:
            st7789_write_cmd(0x2A);
            st7789_write_data(x1 >> 8);
            st7789_write_data(x1);
            st7789_write_data(x2 >> 8);
            st7789_write_data(x2);
            st7789_write_cmd(0x2B);
            st7789_write_data(y1 >> 8);
            st7789_write_data(y1);
            st7789_write_data(y2 >> 8);
            st7789_write_data(y2);
            st7789_write_cmd(0x2C);
            break;
    }
}

/**
 * @}
 */


/**************************** ALL RIGHTS RESERVED *****************************/