1、简介
初学者在学习使用TouchGFX工具设计GUI应用时,一般常用ST官方带有屏幕的评估板,因为TouchGFX的原生工程均支持这些评估板,不需要做额外的屏幕驱动、GUI刷新等事项。如果将TouchGFX应用移植到自定义屏幕就得做相应修改,如TouchGFX模版工程需要由CubeMX创建等
2、先决条件
ST开发板已经实现RGB屏幕的驱动显示,对外提供图像数据写入函数、窗体位置及大小设置函数
示例屏幕:
2.4寸屏幕 320*240像素
屏幕驱动IC ST7789
3、CubeMX工程设置
使能定时器7,用于touchgfx屏幕刷新的tick心跳
定时间隔为10ms,使能定时器中断
勾选CRC
勾选touchgfx组件库
水平像素为320,垂直像素240,颜色制式RGB565
目标IDE选为Keil,此时生成的keil工程编译会有报错
因为需要使用touchgfx创建一个屏幕并编译生成完整的gfx工程
使用touchgfx打开以下gfx工程
添加BOX控件,并填充任意颜色
点击右下红框编译,此后keil工程编译便不会报错了
4、GUI设计
屏幕添加两个图片控件,图一为背景静态图,图2为动态图,随着时间会不断从边缘移动到屏幕中间
添加交互事件,触发方式为每经过N个tick心跳就移动图2所在的窗体
gfx仿真效果
实际显示效果
附st7789屏幕驱动+touchgfx屏幕刷新内容修改
st7789.h
#ifndef __ST7789_H #define __ST7789_H #include "fonts.h" #include "main.h" extern SPI_HandleTypeDef hspi3; #define ST7789_SPI_PORT hspi3 /* Pin connection*/ #define ST7789_RST_PORT GPIOD #define ST7789_RST_PIN GPIO_PIN_3 #define ST7789_DC_PORT GPIOD #define ST7789_DC_PIN GPIO_PIN_6 #ifndef CFG_NO_CS #define ST7789_CS_PORT GPIOD #define ST7789_CS_PIN GPIO_PIN_2 #endif #define USING_240X320 /* Choose a display rotation you want to use: (0-3) */ #define ST7789_ROTATION 3 // use Normally on 240x240 #define USE_HORIZONTAL 0 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏 #ifdef USING_240X320 #define ST7789_WIDTH 320 #define ST7789_HEIGHT 240 #if ST7789_ROTATION == 0 #define X_SHIFT 0 #define Y_SHIFT 80 #elif ST7789_ROTATION == 1 #define X_SHIFT 80 #define Y_SHIFT 0 #elif ST7789_ROTATION == 2 #define X_SHIFT 0 #define Y_SHIFT 0 #elif ST7789_ROTATION == 3 #define X_SHIFT 0 #define Y_SHIFT 0 #endif #endif #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define GRAY 0X8430 #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define BROWN 0XBC40 #define BRRED 0XFC07 #define DARKBLUE 0X01CF #define LIGHTBLUE 0X7D7C #define GRAYBLUE 0X5458 #define LIGHTGREEN 0X841F #define LGRAY 0XC618 #define LGRAYBLUE 0XA651 #define LBBLUE 0X2B12 /* Control Registers and constant codes */ #define ST7789_NOP 0x00 #define ST7789_SWRESET 0x01 #define ST7789_RDDID 0x04 #define ST7789_RDDST 0x09 #define ST7789_SLPIN 0x10 #define ST7789_SLPOUT 0x11 #define ST7789_PTLON 0x12 #define ST7789_NORON 0x13 #define ST7789_INVOFF 0x20 #define ST7789_INVON 0x21 #define ST7789_DISPOFF 0x28 #define ST7789_DISPON 0x29 #define ST7789_CASET 0x2A #define ST7789_RASET 0x2B #define ST7789_RAMWR 0x2C #define ST7789_RAMRD 0x2E #define ST7789_PTLAR 0x30 #define ST7789_COLMOD 0x3A #define ST7789_MADCTL 0x36 /** * Memory Data Access Control Register (0x36H) * MAP: D7 D6 D5 D4 D3 D2 D1 D0 * param: MY MX MV ML RGB MH - - * */ /* Page Address Order ('0': Top to Bottom, '1': the opposite) */ #define ST7789_MADCTL_MY 0x80 /* Column Address Order ('0': Left to Right, '1': the opposite) */ #define ST7789_MADCTL_MX 0x40 /* Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) */ #define ST7789_MADCTL_MV 0x20 /* Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) */ #define ST7789_MADCTL_ML 0x10 /* RGB/BGR Order ('0' = RGB, '1' = BGR) */ #define ST7789_MADCTL_RGB 0x00 #define ST7789_RDID1 0xDA #define ST7789_RDID2 0xDB #define ST7789_RDID3 0xDC #define ST7789_RDID4 0xDD /* Advanced options */ #define ST7789_COLOR_MODE_16bit 0x55 // RGB565 (16bit) #define ST7789_COLOR_MODE_18bit 0x66 // RGB666 (18bit) /* Basic operations */ #define ST7789_RST_Clr() HAL_GPIO_WritePin(ST7789_RST_PORT, ST7789_RST_PIN, GPIO_PIN_RESET) #define ST7789_RST_Set() HAL_GPIO_WritePin(ST7789_RST_PORT, ST7789_RST_PIN, GPIO_PIN_SET) #define ST7789_DC_Clr() HAL_GPIO_WritePin(ST7789_DC_PORT, ST7789_DC_PIN, GPIO_PIN_RESET) #define ST7789_DC_Set() HAL_GPIO_WritePin(ST7789_DC_PORT, ST7789_DC_PIN, GPIO_PIN_SET) #ifndef CFG_NO_CS #define ST7789_Select() HAL_GPIO_WritePin(ST7789_CS_PORT, ST7789_CS_PIN, GPIO_PIN_RESET) #define ST7789_UnSelect() HAL_GPIO_WritePin(ST7789_CS_PORT, ST7789_CS_PIN, GPIO_PIN_SET) #else #define ST7789_Select() asm("nop") #define ST7789_UnSelect() asm("nop") #endif #define ABS(x) ((x) > 0 ? (x) : -(x)) void ST7789_WriteData(uint8_t *buff, size_t buff_size); void ST7789_WriteCommand(uint8_t cmd); void ST7789_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); /* Basic functions. */ void ST7789_Init(void); void ST7789_SetRotation(uint8_t m); void ST7789_Fill_Color(uint16_t color); void ST7789_DrawPixel(uint16_t x, uint16_t y, uint16_t color); void ST7789_Fill(uint16_t xSta, uint16_t ySta, uint16_t xEnd, uint16_t yEnd, uint16_t color); void ST7789_DrawPixel_4px(uint16_t x, uint16_t y, uint16_t color); /* Graphical functions. */ void ST7789_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); void ST7789_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); void ST7789_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color); void ST7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *data); void ST7789_InvertColors(uint8_t invert); /* Text functions. */ void ST7789_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor); void ST7789_WriteString(uint16_t x, uint16_t y, const char *str, FontDef font, uint16_t color, uint16_t bgcolor); /* Extented Graphical functions. */ void ST7789_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); void ST7789_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color); void ST7789_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color); void ST7789_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color); /* Command functions */ void ST7789_TearEffect(uint8_t tear); /* Simple test function. */ void ST7789_Test(void); #ifndef ST7789_ROTATION #error You should at least choose a display rotation! #endif #endif
st7789.c
#include "st7789.h" void ST7789_WriteCommand(uint8_t cmd) { ST7789_Select(); ST7789_DC_Clr(); HAL_SPI_Transmit(&ST7789_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY); ST7789_UnSelect(); } /** * @brief Write data to ST7789 controller * @param buff -> pointer of data buffer * @param buff_size -> size of the data buffer * @return none */ void ST7789_WriteData(uint8_t *buff, size_t buff_size) { ST7789_Select(); ST7789_DC_Set(); // split data in small chunks because HAL can't send more than 64K at once while (buff_size > 0) { uint16_t chunk_size = buff_size > 65535 ? 65535 : buff_size; #ifdef USE_DMA if (DMA_MIN_SIZE <= buff_size) { HAL_SPI_Transmit_DMA(&ST7789_SPI_PORT, buff, chunk_size); while (ST7789_SPI_PORT.hdmatx->State != HAL_DMA_STATE_READY) {} } else HAL_SPI_Transmit(&ST7789_SPI_PORT, buff, chunk_size, HAL_MAX_DELAY); #else HAL_SPI_Transmit(&ST7789_SPI_PORT, buff, chunk_size, HAL_MAX_DELAY); #endif buff += chunk_size; buff_size -= chunk_size; } ST7789_UnSelect(); } /** * @brief Write data to ST7789 controller, simplify for 8bit data. * data -> data to write * @return none */ void ST7789_WriteSmallData(uint8_t data) { ST7789_Select(); ST7789_DC_Set(); HAL_SPI_Transmit(&ST7789_SPI_PORT, &data, sizeof(data), HAL_MAX_DELAY); ST7789_UnSelect(); } /** * @brief Set the rotation direction of the display * @param m -> rotation parameter(please refer it in st7789.h) * @return none */ void ST7789_SetRotation(uint8_t m) { ST7789_WriteCommand(ST7789_MADCTL); // MADCTL switch (m) { case 0: ST7789_WriteSmallData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB); break; case 1: ST7789_WriteSmallData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); break; case 2: ST7789_WriteSmallData(ST7789_MADCTL_RGB); break; case 3: ST7789_WriteSmallData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB); break; default: break; } } /** * @brief Set address of DisplayWindow * @param xi&yi -> coordinates of window * @return none */ void ST7789_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { ST7789_Select(); uint16_t x_start = x0 + X_SHIFT, x_end = x1 + X_SHIFT; uint16_t y_start = y0 + Y_SHIFT, y_end = y1 + Y_SHIFT; /* Column Address set */ ST7789_WriteCommand(ST7789_CASET); { uint8_t data[] = {x_start >> 8, x_start & 0xFF, x_end >> 8, x_end & 0xFF}; ST7789_WriteData(data, sizeof(data)); } /* Row Address set */ ST7789_WriteCommand(ST7789_RASET); { uint8_t data[] = {y_start >> 8, y_start & 0xFF, y_end >> 8, y_end & 0xFF}; ST7789_WriteData(data, sizeof(data)); } /* Write to RAM */ ST7789_WriteCommand(ST7789_RAMWR); ST7789_UnSelect(); } /** * @brief Initialize ST7789 controller * @param none * @return none */ void ST7789_Init(void) { #ifdef USE_DMA memset(disp_buf, 0, sizeof(disp_buf)); #endif HAL_Delay(10); ST7789_RST_Clr(); HAL_Delay(10); ST7789_RST_Set(); HAL_Delay(20); ST7789_WriteCommand(ST7789_COLMOD); // Set color mode ST7789_WriteSmallData(ST7789_COLOR_MODE_16bit); ST7789_WriteCommand(0xB2); // Porch control { uint8_t data[] = {0x0C, 0x0C, 0x00, 0x33, 0x33}; ST7789_WriteData(data, sizeof(data)); } ST7789_SetRotation(ST7789_ROTATION); // MADCTL (Display Rotation) /* Internal LCD Voltage generator settings */ ST7789_WriteCommand(0XB7); // Gate Control ST7789_WriteSmallData(0x35); // Default value ST7789_WriteCommand(0xBB); // VCOM setting ST7789_WriteSmallData(0x19); // 0.725v (default 0.75v for 0x20) ST7789_WriteCommand(0xC0); // LCMCTRL ST7789_WriteSmallData (0x2C); // Default value ST7789_WriteCommand (0xC2); // VDV and VRH command Enable ST7789_WriteSmallData (0x01); // Default value ST7789_WriteCommand (0xC3); // VRH set ST7789_WriteSmallData (0x12); // +-4.45v (defalut +-4.1v for 0x0B) ST7789_WriteCommand (0xC4); // VDV set ST7789_WriteSmallData (0x20); // Default value ST7789_WriteCommand (0xC6); // Frame rate control in normal mode ST7789_WriteSmallData (0x0F); // Default value (60HZ) ST7789_WriteCommand (0xD0); // Power control ST7789_WriteSmallData (0xA4); // Default value ST7789_WriteSmallData (0xA1); // Default value /**************** Division line ****************/ ST7789_WriteCommand(0xE0); { uint8_t data[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}; ST7789_WriteData(data, sizeof(data)); } ST7789_WriteCommand(0xE1); { uint8_t data[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}; ST7789_WriteData(data, sizeof(data)); } ST7789_WriteCommand (ST7789_INVOFF); // Inversion ON ST7789_WriteCommand (ST7789_SLPOUT); // Out of sleep mode ST7789_WriteCommand (ST7789_NORON); // Normal Display on ST7789_WriteCommand (ST7789_DISPON); // Main screen turned on HAL_Delay(50); ST7789_Fill_Color(BLACK); // Fill with Black. } /** * @brief Fill the DisplayWindow with single color * @param color -> color to Fill with * @return none */ void ST7789_Fill_Color(uint16_t color) { uint16_t i; ST7789_SetAddressWindow(0, 0, ST7789_WIDTH - 1, ST7789_HEIGHT - 1); ST7789_Select(); #ifdef USE_DMA for (i = 0; i < ST7789_HEIGHT / HOR_LEN; i++) { //memset((uint16_t*)disp_buf, (uint16_t)0xAC3F, sizeof(disp_buf)); for(uint32_t j=0;j<sizeof(disp_buf)/sizeof(uint16_t);j++){ disp_buf[j]=(color&0xFF)<<8|color>>8; } ST7789_WriteData((uint8_t *)disp_buf, sizeof(disp_buf)); } #else uint16_t j; for (i = 0; i < ST7789_WIDTH; i++) for (j = 0; j < ST7789_HEIGHT; j++) { uint8_t data[] = {color >> 8, color & 0xFF}; ST7789_WriteData(data, sizeof(data)); } #endif ST7789_UnSelect(); } /** * @brief Draw a Pixel * @param x&y -> coordinate to Draw * @param color -> color of the Pixel * @return none */ void ST7789_DrawPixel(uint16_t x, uint16_t y, uint16_t color) { if ((x < 0) || (x >= ST7789_WIDTH) || (y < 0) || (y >= ST7789_HEIGHT)) return; ST7789_SetAddressWindow(x, y, x, y); uint8_t data[] = {color >> 8, color & 0xFF}; ST7789_Select(); ST7789_WriteData(data, sizeof(data)); ST7789_UnSelect(); } /** * @brief Fill an Area with single color * @param xSta&ySta -> coordinate of the start point * @param xEnd&yEnd -> coordinate of the end point * @param color -> color to Fill with * @return none */ void ST7789_Fill(uint16_t xSta, uint16_t ySta, uint16_t xEnd, uint16_t yEnd, uint16_t color) { if ((xEnd < 0) || (xEnd >= ST7789_WIDTH) || (yEnd < 0) || (yEnd >= ST7789_HEIGHT)) return; ST7789_Select(); uint16_t i, j; ST7789_SetAddressWindow(xSta, ySta, xEnd, yEnd); for (i = ySta; i <= yEnd; i++) for (j = xSta; j <= xEnd; j++) { uint8_t data[] = {color >> 8, color & 0xFF}; ST7789_WriteData(data, sizeof(data)); } ST7789_UnSelect(); } /** * @brief Draw a big Pixel at a point * @param x&y -> coordinate of the point * @param color -> color of the Pixel * @return none */ void ST7789_DrawPixel_4px(uint16_t x, uint16_t y, uint16_t color) { if ((x <= 0) || (x > ST7789_WIDTH) || (y <= 0) || (y > ST7789_HEIGHT)) return; ST7789_Select(); ST7789_Fill(x - 1, y - 1, x + 1, y + 1, color); ST7789_UnSelect(); } /** * @brief Draw a line with single color * @param x1&y1 -> coordinate of the start point * @param x2&y2 -> coordinate of the end point * @param color -> color of the line to Draw * @return none */ void ST7789_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t color) { uint16_t swap; uint16_t steep = ABS(y1 - y0) > ABS(x1 - x0); if (steep) { swap = x0; x0 = y0; y0 = swap; swap = x1; x1 = y1; y1 = swap; //_swap_int16_t(x0, y0); //_swap_int16_t(x1, y1); } if (x0 > x1) { swap = x0; x0 = x1; x1 = swap; swap = y0; y0 = y1; y1 = swap; //_swap_int16_t(x0, x1); //_swap_int16_t(y0, y1); } int16_t dx, dy; dx = x1 - x0; dy = ABS(y1 - y0); int16_t err = dx / 2; int16_t ystep; if (y0 < y1) { ystep = 1; } else { ystep = -1; } for (; x0<=x1; x0++) { if (steep) { ST7789_DrawPixel(y0, x0, color); } else { ST7789_DrawPixel(x0, y0, color); } err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } /** * @brief Draw a Rectangle with single color * @param xi&yi -> 2 coordinates of 2 top points. * @param color -> color of the Rectangle line * @return none */ void ST7789_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { ST7789_Select(); ST7789_DrawLine(x1, y1, x2, y1, color); ST7789_DrawLine(x1, y1, x1, y2, color); ST7789_DrawLine(x1, y2, x2, y2, color); ST7789_DrawLine(x2, y1, x2, y2, color); ST7789_UnSelect(); } /** * @brief Draw a circle with single color * @param x0&y0 -> coordinate of circle center * @param r -> radius of circle * @param color -> color of circle line * @return none */ void ST7789_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color) { int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r; ST7789_Select(); ST7789_DrawPixel(x0, y0 + r, color); ST7789_DrawPixel(x0, y0 - r, color); ST7789_DrawPixel(x0 + r, y0, color); ST7789_DrawPixel(x0 - r, y0, color); while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; ST7789_DrawPixel(x0 + x, y0 + y, color); ST7789_DrawPixel(x0 - x, y0 + y, color); ST7789_DrawPixel(x0 + x, y0 - y, color); ST7789_DrawPixel(x0 - x, y0 - y, color); ST7789_DrawPixel(x0 + y, y0 + x, color); ST7789_DrawPixel(x0 - y, y0 + x, color); ST7789_DrawPixel(x0 + y, y0 - x, color); ST7789_DrawPixel(x0 - y, y0 - x, color); } ST7789_UnSelect(); } /** * @brief Draw an Image on the screen * @param x&y -> start point of the Image * @param w&h -> width & height of the Image to Draw * @param data -> pointer of the Image array * @return none */ void ST7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *data) { if ((x >= ST7789_WIDTH) || (y >= ST7789_HEIGHT)) return; if ((x + w - 1) >= ST7789_WIDTH) return; if ((y + h - 1) >= ST7789_HEIGHT) return; ST7789_Select(); ST7789_SetAddressWindow(x, y, x + w - 1, y + h - 1); ST7789_WriteData((uint8_t *)data, sizeof(uint16_t) * w * h); ST7789_UnSelect(); } /** * @brief Invert Fullscreen color * @param invert -> Whether to invert * @return none */ void ST7789_InvertColors(uint8_t invert) { ST7789_Select(); ST7789_WriteCommand(invert ? 0x21 /* INVON */ : 0x20 /* INVOFF */); ST7789_UnSelect(); } /** * @brief Write a char * @param x&y -> cursor of the start point. * @param ch -> char to write * @param font -> fontstyle of the string * @param color -> color of the char * @param bgcolor -> background color of the char * @return none */ void ST7789_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor) { uint32_t i, b, j; ST7789_Select(); ST7789_SetAddressWindow(x, y, x + font.width - 1, y + font.height - 1); for (i = 0; i < font.height; i++) { b = font.data[(ch - 32) * font.height + i]; for (j = 0; j < font.width; j++) { if ((b << j) & 0x8000) { uint8_t data[] = {color >> 8, color & 0xFF}; ST7789_WriteData(data, sizeof(data)); } else { uint8_t data[] = {bgcolor >> 8, bgcolor & 0xFF}; ST7789_WriteData(data, sizeof(data)); } } } ST7789_UnSelect(); } /** * @brief Write a string * @param x&y -> cursor of the start point. * @param str -> string to write * @param font -> fontstyle of the string * @param color -> color of the string * @param bgcolor -> background color of the string * @return none */ void ST7789_WriteString(uint16_t x, uint16_t y, const char *str, FontDef font, uint16_t color, uint16_t bgcolor) { ST7789_Select(); while (*str) { if (x + font.width >= ST7789_WIDTH) { x = 0; y += font.height; if (y + font.height >= ST7789_HEIGHT) { break; } if (*str == ' ') { // skip spaces in the beginning of the new line str++; continue; } } ST7789_WriteChar(x, y, *str, font, color, bgcolor); x += font.width; str++; } ST7789_UnSelect(); } /** * @brief Draw a filled Rectangle with single color * @param x&y -> coordinates of the starting point * @param w&h -> width & height of the Rectangle * @param color -> color of the Rectangle * @return none */ void ST7789_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { ST7789_Select(); uint8_t i; /* Check input parameters */ if (x >= ST7789_WIDTH || y >= ST7789_HEIGHT) { /* Return error */ return; } /* Check width and height */ if ((x + w) >= ST7789_WIDTH) { w = ST7789_WIDTH - x; } if ((y + h) >= ST7789_HEIGHT) { h = ST7789_HEIGHT - y; } /* Draw lines */ for (i = 0; i <= h; i++) { /* Draw lines */ ST7789_DrawLine(x, y + i, x + w, y + i, color); } ST7789_UnSelect(); } /** * @brief Draw a Triangle with single color * @param xi&yi -> 3 coordinates of 3 top points. * @param color ->color of the lines * @return none */ void ST7789_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color) { ST7789_Select(); /* Draw lines */ ST7789_DrawLine(x1, y1, x2, y2, color); ST7789_DrawLine(x2, y2, x3, y3, color); ST7789_DrawLine(x3, y3, x1, y1, color); ST7789_UnSelect(); } /** * @brief Draw a filled Triangle with single color * @param xi&yi -> 3 coordinates of 3 top points. * @param color ->color of the triangle * @return none */ void ST7789_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color) { ST7789_Select(); int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0, yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0, curpixel = 0; deltax = ABS(x2 - x1); deltay = ABS(y2 - y1); x = x1; y = y1; if (x2 >= x1) { xinc1 = 1; xinc2 = 1; } else { xinc1 = -1; xinc2 = -1; } if (y2 >= y1) { yinc1 = 1; yinc2 = 1; } else { yinc1 = -1; yinc2 = -1; } if (deltax >= deltay) { xinc1 = 0; yinc2 = 0; den = deltax; num = deltax / 2; numadd = deltay; numpixels = deltax; } else { xinc2 = 0; yinc1 = 0; den = deltay; num = deltay / 2; numadd = deltax; numpixels = deltay; } for (curpixel = 0; curpixel <= numpixels; curpixel++) { ST7789_DrawLine(x, y, x3, y3, color); num += numadd; if (num >= den) { num -= den; x += xinc1; y += yinc1; } x += xinc2; y += yinc2; } ST7789_UnSelect(); } /** * @brief Draw a Filled circle with single color * @param x0&y0 -> coordinate of circle center * @param r -> radius of circle * @param color -> color of circle * @return none */ void ST7789_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) { ST7789_Select(); int16_t f = 1 - r; int16_t ddF_x = 1; int16_t ddF_y = -2 * r; int16_t x = 0; int16_t y = r; ST7789_DrawPixel(x0, y0 + r, color); ST7789_DrawPixel(x0, y0 - r, color); ST7789_DrawPixel(x0 + r, y0, color); ST7789_DrawPixel(x0 - r, y0, color); ST7789_DrawLine(x0 - r, y0, x0 + r, y0, color); while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; ST7789_DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, color); ST7789_DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, color); ST7789_DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, color); ST7789_DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, color); } ST7789_UnSelect(); } /** * @brief Open/Close tearing effect line * @param tear -> Whether to tear * @return none */ void ST7789_TearEffect(uint8_t tear) { ST7789_Select(); ST7789_WriteCommand(tear ? 0x35 /* TEON */ : 0x34 /* TEOFF */); ST7789_UnSelect(); } /** * @brief A Simple test function for ST7789 * @param none * @return none */ void ST7789_Test(void) { ST7789_Fill_Color(WHITE); HAL_Delay(1000); ST7789_WriteString(10, 20, "Speed Test", Font_11x18, RED, WHITE); HAL_Delay(1000); ST7789_Fill_Color(CYAN); HAL_Delay(500); ST7789_Fill_Color(RED); HAL_Delay(500); ST7789_Fill_Color(BLUE); HAL_Delay(500); ST7789_Fill_Color(GREEN); HAL_Delay(500); ST7789_Fill_Color(YELLOW); HAL_Delay(500); ST7789_Fill_Color(BROWN); HAL_Delay(500); ST7789_Fill_Color(DARKBLUE); HAL_Delay(500); ST7789_Fill_Color(MAGENTA); HAL_Delay(500); ST7789_Fill_Color(LIGHTGREEN); HAL_Delay(500); ST7789_Fill_Color(LGRAY); HAL_Delay(500); ST7789_Fill_Color(LBBLUE); HAL_Delay(500); ST7789_Fill_Color(WHITE); HAL_Delay(500); ST7789_WriteString(10, 10, "Font test.", Font_16x26, GBLUE, WHITE); ST7789_WriteString(10, 50, "Hello Steve!", Font_7x10, RED, WHITE); ST7789_WriteString(10, 75, "Hello Steve!", Font_11x18, YELLOW, WHITE); ST7789_WriteString(10, 100, "Hello Steve!", Font_16x26, MAGENTA, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Rect./Line.", Font_11x18, YELLOW, BLACK); ST7789_DrawRectangle(30, 30, 100, 100, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Filled Rect.", Font_11x18, YELLOW, BLACK); ST7789_DrawFilledRectangle(30, 30, 50, 50, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Circle.", Font_11x18, YELLOW, BLACK); ST7789_DrawCircle(60, 60, 25, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Filled Cir.", Font_11x18, YELLOW, BLACK); ST7789_DrawFilledCircle(60, 60, 25, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Triangle", Font_11x18, YELLOW, BLACK); ST7789_DrawTriangle(30, 30, 30, 70, 60, 40, WHITE); HAL_Delay(1000); ST7789_Fill_Color(RED); ST7789_WriteString(10, 10, "Filled Tri", Font_11x18, YELLOW, BLACK); ST7789_DrawFilledTriangle(30, 30, 30, 70, 60, 40, WHITE); HAL_Delay(1000); // If FLASH cannot storage anymore datas, please delete codes below. ST7789_Fill_Color(WHITE); ST7789_DrawImage(0, 0, 128, 128, (uint16_t *)saber); HAL_Delay(3000); }
找到工程文件TouchGFXHAL.cpp,添加如下代码,主要是使用位图绘制函数来完成touchgfx画面内容的显示更新
#ifdef __cplusplus extern "C"{ #include "st7789.h" } #endif #include <touchgfx/hal/OSWrappers.hpp>
添加自定义屏幕的绘制代码,完成指定屏幕区域的图像绘制
void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect) { volatile uint16_t* buffer = getClientFrameBuffer()+(rect.y*ST7789_WIDTH)+rect.x;//获取图像数据 uint16_t height,i; ST7789_SetAddressWindow(rect.x,rect.y,rect.x+rect.width-1,rect.y+rect.height-1);//设定绘制区域 for(height=0;height<rect.height;height++) //开始绘制 { for(i=0;i<rect.width;i++) { uint8_t dat[2]; dat[0]=buffer[i]>>8; dat[1]=buffer[i]; ST7789_WriteData(dat,sizeof(dat)); } buffer += ST7789_WIDTH; } }
添加定时刷新当前屏幕显示
extern "C" void touchgfxSignalVSync(void) { HAL::getInstance()->vSync(); OSWrappers::signalVSync(); HAL::getInstance()->swapFrameBuffers(); }
前面使用cubemx配置了定时器7,以下在main.c文件重新定义定时器的回调函数
extern void touchgfxSignalVSync(void); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM7) { touchgfxSignalVSync(); } }
最后是启用定时器7,初始化touchgfx应用
HAL_TIM_Base_Start_IT(&htim7); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ MX_TouchGFX_Process(); /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }