前言
- 使用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);
}
}