前言
- 使用ST7735S屏幕驱动,方便学习LVGL
- 通过结构体的方式来管理相关函数和变量
- 通讯协议和硬件驱动层进行解耦
驱动
配置(用于对接硬件)
st7735s_conf.h
#ifndef STM32F407V4T6_RTOS_ST7735S_CONF_H
#define STM32F407V4T6_RTOS_ST7735S_CONF_H#include "stdint.h"
#include "stdio.h"#ifndef ST7735S_SCREEN_MODE
#define ST7735S_SCREEN_MODE VER_0_MODE
#endif
#ifndef ST7735S_SCREEN_WIDTH
#define ST7735S_SCREEN_WIDTH 128
#endif
#ifndef ST7735S_SCREEN_HIGH
#define ST7735S_SCREEN_HIGH 160
#endif
#ifndef ST7735S_BACK_COLOR
#define ST7735S_BACK_COLOR 0xFFFF
#endif
#ifndef ST7735S_POINT_COLOR
#define ST7735S_POINT_COLOR 0x0000
#endif
#define ST7735S_BUS_NAME "spi3"
#define ST7735S_SPI_DEVICE "spi30"
#define ST7735S_DC_PIN GET_PIN(B, 13)
#define ST7735S_RESET_PIN GET_PIN(B, 11)
#define ST7735S_CS_PIN GET_PIN(B, 14)
#define ST7735S_BLK_PIN GET_PIN(A,8) #define L2R_U2D 0
#define L2R_D2U 1
#define R2L_U2D 2
#define R2L_D2U 3 #define U2D_L2R 4
#define U2D_R2L 5
#define D2U_L2R 6
#define D2U_R2L 7
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0xF81F
#define GRED 0xFFE0
#define GBLUE 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF
#define YELLOW 0xFFE0
#define BROWN 0xBC40
#define BRRED 0xFC07
#define GRAY 0x8430
#define DARKBLUE 0x01CF
#define LIGHTBLUE 0x7D7C
#define GRAYBLUE 0x5458
#define LIGHTGREEN 0x841F
#define LGRAY 0xC618
#define GRAY0 0xEF7D
#define GRAY1 0x8410
#define GRAY2 0x4208
#define LGRAYBLUE 0xA651
#define LBBLUE 0x2B12 typedef enum {VER_0_MODE, VER_1_MODE, HOR_0_MODE, HOR_1_MODE
} ST7735S_DIR_MODE;
struct ST7735S { struct {ST7735S_DIR_MODE screen_mode;uint16_t width; uint16_t height; uint16_t back_color; uint16_t point_color; struct {uint16_t wramcmd; uint16_t setxcmd; uint16_t setycmd; } CMD;} CNF;struct {void (*_enter)(void); void (*_exit)(void); } CRIS;struct {void (*_select)(void);void (*_deselect)(void);} CS; struct {void (*_select_data)(void);void (*_select_reg)(void);} DC; struct {void (*_write_byte)(uint8_t dat); } SPI; };
extern struct ST7735S ST7735S_DEV;
void reg_st7735s_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void));void reg_st7735s_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void));void reg_st7735s_dc_cbfunc(void(*dc_dat)(void), void(*dc_reg)(void));void reg_st7735s_spi_cbfunc(void(*spi_write_byte)(uint8_t data));
void st7735s_init(void);#endif
st7735s_conf.c
#include "st7735s_conf.h"struct ST7735S ST7735S_DEV = {.CNF={.screen_mode =ST7735S_SCREEN_MODE,.width=ST7735S_SCREEN_WIDTH,.height = ST7735S_SCREEN_HIGH,.back_color = ST7735S_BACK_COLOR,.point_color = ST7735S_POINT_COLOR,},.SPI={NULL},.CS ={NULL, NULL},.DC={NULL, NULL},.CRIS={NULL, NULL}
};void reg_st7735s_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) {ST7735S_DEV.CRIS._enter = cris_en;ST7735S_DEV.CRIS._exit = cris_ex;
}void reg_st7735s_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) {ST7735S_DEV.CS._select = cs_sel;ST7735S_DEV.CS._deselect = cs_desel;
}void reg_st7735s_dc_cbfunc(void(*dc_dat)(void), void(*dc_reg)(void)) {ST7735S_DEV.DC._select_reg = dc_reg;ST7735S_DEV.DC._select_data = dc_dat;
}void reg_st7735s_spi_cbfunc(void(*spi_write_byte)(uint8_t data)) {ST7735S_DEV.SPI._write_byte = spi_write_byte;
}
通讯协议(数据手册)
st7735s.h
#ifndef STM32F407V4T6_RTOS_ST7735S_H
#define STM32F407V4T6_RTOS_ST7735S_H#include "st7735s_conf.h"
#include "st7735s_ex.h"void ST7735S_write_dat_u8(uint8_t dat);void ST7735S_write_dat_u16(uint16_t dat);void ST7735S_write_reg_val(uint16_t reg, uint16_t dat);void ST7735S_write_reg(uint8_t dat);void LCD_Init(void);
void LCD_SoftRest(void);
void LCD_DisplayOn(void);
void LCD_DisplayOff(void);
void LCD_Clear(uint16_t Color);
void LCD_Display_Dir(ST7735S_DIR_MODE dir);
void LCD_WriteRAM_Prepare(void);
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos);
void LCD_DrawPoint(uint16_t x, uint16_t y);
void LCD_Set_Window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height);
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);
void LCD_WriteRAM(uint16_t RGB_Code);
void LCD_Fast_DrawPoint(uint16_t x,uint16_t y,uint16_t color);
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color);
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color);
void LCD_Draw_Circle(uint16_t x0,uint16_t y0,uint8_t r, uint16_t Color);
#endif
st7735s.c
#include "st7735s.h"#define CRITICAL_ENTER() if(ST7735S_DEV.CRIS._enter)ST7735S_DEV.CRIS._enter()
#define CRITICAL_EXIT() if(ST7735S_DEV.CRIS._enter)ST7735S_DEV.CRIS._exit()
#define DC_DATA_SELECT() if(ST7735S_DEV.DC._select_data) ST7735S_DEV.DC._select_data()
#define DC_REG_SELECT() if(ST7735S_DEV.DC._select_reg) ST7735S_DEV.DC._select_reg()
#define CS_SELECT() if(ST7735S_DEV.CS._select) ST7735S_DEV.CS._select()
#define CS_DESELECT() if(ST7735S_DEV.CS._deselect) ST7735S_DEV.CS._deselect()void ST7735S_write_dat_u8(uint8_t dat) {CRITICAL_ENTER();DC_DATA_SELECT(); CS_SELECT();if (ST7735S_DEV.SPI._write_byte) {ST7735S_DEV.SPI._write_byte(dat);}CS_DESELECT();CRITICAL_EXIT();
}void ST7735S_write_dat_u16(uint16_t dat) {ST7735S_write_dat_u8(dat >> 8);ST7735S_write_dat_u8(dat);
}void ST7735S_write_reg_val(uint16_t reg, uint16_t dat) {ST7735S_write_reg(reg);ST7735S_write_dat_u8(dat);
}void ST7735S_write_reg(uint8_t dat) {CRITICAL_ENTER();DC_REG_SELECT();CS_SELECT();if (ST7735S_DEV.SPI._write_byte) {ST7735S_DEV.SPI._write_byte(dat);}CS_DESELECT();CRITICAL_EXIT();
}
void LCD_Init(void) {st7735s_init();LCD_SoftRest(); ST7735S_write_reg(0x11); HAL_Delay(120); ST7735S_write_reg(0xB1);ST7735S_write_dat_u8(0x01);ST7735S_write_dat_u8(0x2C);ST7735S_write_dat_u8(0x2D);ST7735S_write_reg(0xB2);ST7735S_write_dat_u8(0x01);ST7735S_write_dat_u8(0x2C);ST7735S_write_dat_u8(0x2D);ST7735S_write_reg(0xB3);ST7735S_write_dat_u8(0x01);ST7735S_write_dat_u8(0x2C);ST7735S_write_dat_u8(0x2D);ST7735S_write_dat_u8(0x01);ST7735S_write_dat_u8(0x2C);ST7735S_write_dat_u8(0x2D);ST7735S_write_reg(0xB4); ST7735S_write_dat_u8(0x07);ST7735S_write_reg(0xC0);ST7735S_write_dat_u8(0xA2);ST7735S_write_dat_u8(0x02);ST7735S_write_dat_u8(0x84);ST7735S_write_reg(0xC1);ST7735S_write_dat_u8(0xC5);ST7735S_write_reg(0xC2);ST7735S_write_dat_u8(0x0A);ST7735S_write_dat_u8(0x00);ST7735S_write_reg(0xC3);ST7735S_write_dat_u8(0x8A);ST7735S_write_dat_u8(0x2A);ST7735S_write_reg(0xC4);ST7735S_write_dat_u8(0x8A);ST7735S_write_dat_u8(0xEE);ST7735S_write_reg(0xC5); ST7735S_write_dat_u8(0x0E);ST7735S_write_reg(0x36); ST7735S_write_dat_u8(0xC0);ST7735S_write_reg(0xe0);ST7735S_write_dat_u8(0x0f);ST7735S_write_dat_u8(0x1a);ST7735S_write_dat_u8(0x0f);ST7735S_write_dat_u8(0x18);ST7735S_write_dat_u8(0x2f);ST7735S_write_dat_u8(0x28);ST7735S_write_dat_u8(0x20);ST7735S_write_dat_u8(0x22);ST7735S_write_dat_u8(0x1f);ST7735S_write_dat_u8(0x1b);ST7735S_write_dat_u8(0x23);ST7735S_write_dat_u8(0x37);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x07);ST7735S_write_dat_u8(0x02);ST7735S_write_dat_u8(0x10);ST7735S_write_reg(0xe1);ST7735S_write_dat_u8(0x0f);ST7735S_write_dat_u8(0x1b);ST7735S_write_dat_u8(0x0f);ST7735S_write_dat_u8(0x17);ST7735S_write_dat_u8(0x33);ST7735S_write_dat_u8(0x2c);ST7735S_write_dat_u8(0x29);ST7735S_write_dat_u8(0x2e);ST7735S_write_dat_u8(0x30);ST7735S_write_dat_u8(0x30);ST7735S_write_dat_u8(0x39);ST7735S_write_dat_u8(0x3f);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x07);ST7735S_write_dat_u8(0x03);ST7735S_write_dat_u8(0x10);ST7735S_write_reg(0x2a);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x7f);ST7735S_write_reg(0x2b);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x00);ST7735S_write_dat_u8(0x9f);ST7735S_write_reg(0xF0); ST7735S_write_dat_u8(0x01);ST7735S_write_reg(0xF6); ST7735S_write_dat_u8(0x00);ST7735S_write_reg(0x3A); ST7735S_write_dat_u8(0x05);ST7735S_write_reg(0x29);LCD_Display_Dir(ST7735S_DEV.CNF.screen_mode); LCD_Clear(ST7735S_DEV.CNF.back_color);
}
void LCD_DisplayOn(void) {ST7735S_write_reg(0X29);
}
void LCD_DisplayOff(void) {ST7735S_write_reg(0X28); }
void LCD_Display_Dir(ST7735S_DIR_MODE dir) {ST7735S_DEV.CNF.screen_mode = dir;uint16_t width, high;switch (ST7735S_DEV.CNF.screen_mode) {case VER_0_MODE: { width = ST7735S_SCREEN_WIDTH;high = ST7735S_SCREEN_HIGH;ST7735S_DEV.CNF.CMD.wramcmd = 0X2C;ST7735S_DEV.CNF.CMD.setxcmd = 0X2A;ST7735S_DEV.CNF.CMD.setycmd = 0X2B;ST7735S_write_reg_val(0x36, 0xC0);}break;case VER_1_MODE: {width = ST7735S_SCREEN_WIDTH;high = ST7735S_SCREEN_HIGH;ST7735S_DEV.CNF.CMD.wramcmd = 0X2C;ST7735S_DEV.CNF.CMD.setxcmd = 0X2A;ST7735S_DEV.CNF.CMD.setycmd = 0X2B;ST7735S_write_reg_val(0x36, 0x40);}break;case HOR_0_MODE: {width = ST7735S_SCREEN_HIGH;high = ST7735S_SCREEN_WIDTH;ST7735S_DEV.CNF.CMD.wramcmd = 0X2C;ST7735S_DEV.CNF.CMD.setxcmd = 0X2A;ST7735S_DEV.CNF.CMD.setycmd = 0X2B;ST7735S_write_reg_val(0x36, 0xA0);}break;case HOR_1_MODE: {width = ST7735S_SCREEN_HIGH;high = ST7735S_SCREEN_WIDTH;ST7735S_DEV.CNF.CMD.wramcmd = 0X2C;ST7735S_DEV.CNF.CMD.setxcmd = 0X2A;ST7735S_DEV.CNF.CMD.setycmd = 0X2B;ST7735S_write_reg_val(0x36, 0x60);}break;}ST7735S_DEV.CNF.width = width;ST7735S_DEV.CNF.height = high;LCD_Set_Window(0, 0, width, high);}
void LCD_Set_Window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height) {width = sx + width - 1;height = sy + height - 1;if (ST7735S_DEV.CNF.screen_mode == VER_0_MODE || ST7735S_DEV.CNF.screen_mode == VER_1_MODE) {ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setxcmd);ST7735S_write_dat_u16(sx + 2); ST7735S_write_dat_u16(width + 2); ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setycmd);ST7735S_write_dat_u16(sy + 1); ST7735S_write_dat_u16(height + 1); } else {ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setxcmd);ST7735S_write_dat_u16(sx + 1); ST7735S_write_dat_u16(width + 1); ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setycmd);ST7735S_write_dat_u16(sy + 2); ST7735S_write_dat_u16(height + 2); }
}
void LCD_Clear(uint16_t color) {uint32_t index = 0;uint32_t totalpoint;LCD_Set_Window(0, 0, ST7735S_DEV.CNF.width, ST7735S_DEV.CNF.height);totalpoint = ST7735S_DEV.CNF.width * ST7735S_DEV.CNF.height; LCD_SetCursor(0, 0); LCD_WriteRAM_Prepare(); for (index = 0; index < totalpoint; index++) {ST7735S_write_dat_u16(color);}
}
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos) {if (ST7735S_DEV.CNF.screen_mode == VER_0_MODE || ST7735S_DEV.CNF.screen_mode == VER_1_MODE) {ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setxcmd);ST7735S_write_dat_u16(Xpos);ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setycmd);ST7735S_write_dat_u16(Ypos);} else {ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setxcmd);ST7735S_write_dat_u16(Xpos);ST7735S_write_reg(ST7735S_DEV.CNF.CMD.setycmd);ST7735S_write_dat_u16(Ypos);}}
void LCD_WriteRAM_Prepare(void) {ST7735S_write_reg(ST7735S_DEV.CNF.CMD.wramcmd);
}
void LCD_DrawPoint(uint16_t x, uint16_t y) {LCD_SetCursor(x, y); LCD_WriteRAM_Prepare(); ST7735S_write_dat_u16(ST7735S_DEV.CNF.point_color);
}
void LCD_WriteRAM(uint16_t RGB_Code) {ST7735S_write_dat_u16(RGB_Code);
}
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color) {uint32_t i;uint16_t xlen = 0;LCD_Set_Window(sx, sy, ex - sx, ey - sy);ST7735S_write_reg(ST7735S_DEV.CNF.CMD.wramcmd);xlen = (ex - sx) * (ey - sy);LCD_WriteRAM_Prepare(); for (i = 0; i <= xlen; i++) {ST7735S_write_dat_u16(color); }LCD_Set_Window(0, 0, ST7735S_DEV.CNF.width, ST7735S_DEV.CNF.height);}
void LCD_Fast_DrawPoint(uint16_t x, uint16_t y, uint16_t color) {LCD_SetCursor(x, y); ST7735S_write_reg(ST7735S_DEV.CNF.CMD.wramcmd);ST7735S_write_dat_u16(color); }
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color) {LCD_DrawLine(x1, y1, x2, y1, Color);LCD_DrawLine(x1, y1, x1, y2, Color);LCD_DrawLine(x1, y2, x2, y2, Color);LCD_DrawLine(x2, y1, x2, y2, Color);
}
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t Color) {uint16_t t;int xerr = 0, yerr = 0, delta_x, delta_y, distance;int incx, incy, uRow, uCol;delta_x = x2 - x1; delta_y = y2 - y1;uRow = x1;uCol = y1;if (delta_x > 0)incx = 1; else if (delta_x == 0)incx = 0;else {incx = -1;delta_x = -delta_x;}if (delta_y > 0)incy = 1;else if (delta_y == 0)incy = 0;else {incy = -1;delta_y = -delta_y;}if (delta_x > delta_y)distance = delta_x; else distance = delta_y;for (t = 0; t <= distance + 1; t++){LCD_Fast_DrawPoint(uRow, uCol, Color);xerr += delta_x;yerr += delta_y;if (xerr > distance) {xerr -= distance;uRow += incx;}if (yerr > distance) {yerr -= distance;uCol += incy;}}
}
void LCD_Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t Color) {int a, b;int di;a = 0;b = r;di = 3 - (r << 1); while (a <= b) {LCD_Fast_DrawPoint(x0 + a, y0 - b, Color); LCD_Fast_DrawPoint(x0 + b, y0 - a, Color); LCD_Fast_DrawPoint(x0 + b, y0 + a, Color); LCD_Fast_DrawPoint(x0 + a, y0 + b, Color); LCD_Fast_DrawPoint(x0 - a, y0 + b, Color); LCD_Fast_DrawPoint(x0 - b, y0 + a, Color);LCD_Fast_DrawPoint(x0 - a, y0 - b, Color); LCD_Fast_DrawPoint(x0 - b, y0 - a, Color); a++;if (di < 0)di += 4 * a + 6;else {di += 10 + 4 * (a - b);b--;}}
}
硬件驱动(SPI3,这里使用的)
#include "st7735s.h"
#include "drv_common.h"
#include "drv_spi.h"#define DBG_ENABLE
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG#include <rtdbg.h>struct rt_spi_device *st7735s_device = RT_NULL;static void spi_cris_enter(void) { rt_spi_take_bus(st7735s_device); }static void spi_cris_exit(void) { rt_spi_release_bus(st7735s_device); }static void spi_cs_deselect(void) { rt_spi_release(st7735s_device); }static void spi_cs_select(void) { rt_spi_take(st7735s_device); }static void dc_dat_select(void) { rt_pin_write(ST7735S_DC_PIN, PIN_HIGH); }static void dc_reg_select(void) { rt_pin_write(ST7735S_DC_PIN, PIN_LOW); }static void spi_write_byte(uint8_t data) { rt_spi_send(st7735s_device, &data, 1); }rt_err_t st7735s_device_init(const char *spi_dev_name) {rt_hw_spi_device_attach(ST7735S_BUS_NAME, spi_dev_name, GPIOB, GPIO_PIN_14);st7735s_device = (struct rt_spi_device *) rt_device_find(spi_dev_name);if (st7735s_device == NULL) {LOG_W("未找到该设备");return -RT_ERROR;} else {LOG_W("找到该设备");struct rt_spi_configuration cfg;{cfg.data_width = 8;cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;cfg.max_hz = 40 * 1000 * 1000;}rt_spi_configure(st7735s_device, &cfg);}return RT_EOK;
}static void st7735s_callback_register() {reg_st7735s_cris_cbfunc(spi_cris_enter, spi_cris_exit);reg_st7735s_cs_cbfunc(spi_cs_select, spi_cs_deselect);reg_st7735s_dc_cbfunc(dc_dat_select, dc_reg_select);reg_st7735s_spi_cbfunc(spi_write_byte);
}
void LCD_SoftRest(void) {rt_pin_write(ST7735S_RESET_PIN, PIN_LOW);rt_thread_mdelay(100);rt_pin_write(ST7735S_RESET_PIN, PIN_HIGH);rt_thread_mdelay(1000);
}void st7735s_init(void) {rt_err_t result = RT_EOK;rt_pin_mode(ST7735S_DC_PIN, PIN_MODE_OUTPUT);rt_pin_mode(ST7735S_RESET_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(ST7735S_BLK_PIN, PIN_MODE_OUTPUT);result = st7735s_device_init(ST7735S_SPI_DEVICE);if (result != RT_EOK) goto __exit;st7735s_callback_register();__exit:if (result == RT_EOK) {LOG_I("st7735s_init initialize success.");} else {LOG_I("st7735s_init initialize err:%d.", result);}
}
测试调用
int main(void) {LCD_Init();for (int i = 0; i < 100; ++i) {LCD_Fast_DrawPoint(10,i,RED);}for (;;) {rt_thread_mdelay(1000);}
}