一、简介:
MCU:GD32F303
显示驱动:ST7735S
LCD硬件接口:8080(8位数据线)
引脚:
数据:D7~D0
片选:CS
数据/命令:RS
写控制:WR
读控制:RD
复位:RST
背光:EN
二、代码:
1、头文件:
#ifndef __ST7735S_LCD_H
#define __ST7735S_LCD_H
#include "main.h"
#include "font.h"
#define USE_DMA
/*
* 说明:
* 这是一个1.8寸的TFT_LCD屏幕,显示驱动IC是:ST7735S
* 分辨率:128*160
*
*
*/
#define LCD_WIDTH 128
#define LCD_HEIGHT 160
/用户配置区///
// 支持横竖屏快速定义切换
#define USE_LCM_DIR 2 // 定义液晶屏顺时针旋转方向 0-0度旋转,1-180度旋转,2-270度旋转,3-90度旋转
// LCD重要参数集
typedef struct
{
uint16_t width; // LCD 宽度
uint16_t height; // LCD 高度
uint16_t id; // LCD ID
uint8_t dir; // 横屏还是竖屏控制:0,竖屏;1,横屏。
uint16_t wramcmd; // 开始写gram指令
uint16_t setxcmd; // 设置x坐标指令
uint16_t setycmd; // 设置y坐标指令
} _lcd_dev;
// LCD参数
extern _lcd_dev lcddev; // 管理LCD重要参数
// LCD的画笔颜色和背景色
extern uint16_t POINT_COLOR; // 默认红色
extern uint16_t BACK_COLOR; // 背景颜色.默认为白色
//-----------------LCD端口定义----------------//
#define LCD_RESET_Port GPIOC // 复位引脚:PC15
#define LCD_RESET_Pin GPIO_PIN_15
#define LCD_RD_Port LCD_RESET_Port // 读数据引脚:PC14
#define LCD_RD_Pin GPIO_PIN_14
#define LCD_WR_Port LCD_RESET_Port // 写数据引脚:PC13
#define LCD_WR_Pin GPIO_PIN_13
#define LCD_CS_Port LCD_RESET_Port // 片选引脚:PC11
#define LCD_CS_Pin GPIO_PIN_11
#define LCD_RS_Port LCD_RESET_Port // 数据/命令选择引脚:PC10
#define LCD_RS_Pin GPIO_PIN_10
#define LCD_EN_Port LCD_RESET_Port // LCD背光引脚:PC0
#define LCD_EN_Pin GPIO_PIN_0
// 数据线:DB0~DB7
#define LCD_DB_Port GPIOB
#define LCD_DB0_Pin GPIO_PIN_0
#define LCD_DB1_Pin GPIO_PIN_1
#define LCD_DB2_Pin GPIO_PIN_2
#define LCD_DB3_Pin GPIO_PIN_3
#define LCD_DB4_Pin GPIO_PIN_4
#define LCD_DB5_Pin GPIO_PIN_5
#define LCD_DB6_Pin GPIO_PIN_6
#define LCD_DB7_Pin GPIO_PIN_7
// 数据线输出输入
#define DB_PORT_OUTPUT 1
#define DB_PORT_INPUT 0
// 拉高
// #define LCD_RST_SET gpio_bit_set(LCD_RESET_Port, LCD_RESET_Pin) // 复位 PC15
// #define LCD_CS_SET gpio_bit_set(LCD_CS_Port, LCD_CS_Pin) // 片选端口 PC11
// #define LCD_RS_SET gpio_bit_set(LCD_RS_Port, LCD_RS_Pin) // 数据/命令 PC10
// #define LCD_WR_SET gpio_bit_set(LCD_WR_Port, LCD_WR_Pin) // 写数据 PC13
// #define LCD_RD_SET gpio_bit_set(LCD_RD_Port, LCD_RD_Pin) // 读数据 PC14
// 拉低
// #define LCD_RST_CLR gpio_bit_reset(LCD_RESET_Port, LCD_RESET_Pin)
// #define LCD_CS_CLR gpio_bit_reset(LCD_CS_Port, LCD_CS_Pin)
// #define LCD_RS_CLR gpio_bit_reset(LCD_RS_Port, LCD_RS_Pin)
// #define LCD_WR_CLR gpio_bit_reset(LCD_WR_Port, LCD_WR_Pin)
// #define LCD_RD_CLR gpio_bit_reset(LCD_RD_Port, LCD_RD_Pin)
// #define LCD_LED(x) (x ? gpio_bit_set(LCD_EN_Port, LCD_EN_Pin) : gpio_bit_reset(LCD_EN_Port, LCD_EN_Pin))
#define LCD_RST_SET GPIO_BOP(LCD_RESET_Port) = (uint32_t)LCD_RESET_Pin
#define LCD_CS_SET GPIO_BOP(LCD_CS_Port) = (uint32_t)LCD_CS_Pin
#define LCD_RS_SET GPIO_BOP(LCD_RS_Port) = (uint32_t)LCD_RS_Pin
#define LCD_WR_SET GPIO_BOP(LCD_WR_Port) = (uint32_t)LCD_WR_Pin
#define LCD_RD_SET GPIO_BOP(LCD_RD_Port) = (uint32_t)LCD_RD_Pin
// 拉低
#define LCD_RST_CLR GPIO_BC(LCD_RESET_Port) = (uint32_t)LCD_RESET_Pin
#define LCD_CS_CLR GPIO_BC(LCD_CS_Port) = (uint32_t)LCD_CS_Pin
#define LCD_RS_CLR GPIO_BC(LCD_RS_Port) = (uint32_t)LCD_RS_Pin
#define LCD_WR_CLR GPIO_BC(LCD_WR_Port) = (uint32_t)LCD_WR_Pin
#define LCD_RD_CLR GPIO_BC(LCD_RD_Port) = (uint32_t)LCD_RD_Pin
#define LCD_LED(x) (x ? (GPIO_BOP(LCD_EN_Port) = (uint32_t)LCD_EN_Pin) : (GPIO_BC(LCD_EN_Port) = (uint32_t)LCD_EN_Pin))
// PB3~10,作为数据线
// 数据输出
#define DATAOUT(x) DataOut(x)
#define DATAIN DataIn(void) // 数据输入
// 画笔颜色
#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 // 灰色
// GUI颜色
#define DARKBLUE 0X01CF // 深蓝色
#define LIGHTBLUE 0X7D7C // 浅蓝色
#define GRAYBLUE 0X5458 // 灰蓝色
// 以上三色为PANEL的颜色
#define LIGHTGREEN 0X841F // 浅绿色
#define LGRAY 0XC618 // 浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 // 浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 // 浅棕蓝色(选择条目的反色)
#define DISP_ON 0x29
#define DISP_OFF 0x28
#define LCD_MADCTL 0x36 // Memory Data Access Control
#define LCD_SLPOUT 0x11 // turns off sleep mode
#define LCD_FRMCTR1 0xB1 // Set the frame frequency of the full colors normal mode
#define LCD_FRMCTR2 0xB2 // Set the frame frequency of the idle mode
#define LCD_FRMCTR3 0xB3 // Set the frame frequency of the Partial mode/full colors
#define LCD_INVCTR 0xB4 // Display inversion mode control
#define LCD_PWCTR1 0xC0 //
#define LCD_READ_ID 0x04 // read lcd id
void DataOut(uint8_t data);
uint8_t DataIn(void);
void LCD_WR_REG(uint8_t data);
void LCD_WR_DATA(uint8_t data);
void LCD_WriteRAM(uint16_t RGB_Code);
void LCD_WriteReg(uint16_t LCD_Reg, uint16_t LCD_RegValue);
void LCD_WriteRAM_Prepare(void);
void opt_delay(uint8_t i);
void LCD_DisplayOn(void);
void LCD_DisplayOff(void); // 关显示
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos); // 设置光标
void LCD_DrawPoint(uint16_t x, uint16_t y); // 画点
void LCD_Fast_DrawPoint(uint16_t x, uint16_t y, uint16_t color); // 快速画点
void LCD_Display_Dir(uint8_t dir);
void LCD_Set_Window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height); // 设置窗口
void LCD_GPIO_Init(void);
void LCD_Init(void); // 初始化
void LCD_DB_Mode(uint8_t mode, uint8_t status);
uint16_t LCD_Read_ID(uint8_t reg);
uint16_t LCD_ReadPoint(uint16_t x, uint16_t y);
void LCD_Clear(uint16_t color);
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color);
void LCD_Color_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color);
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void LCD_Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r);
void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint8_t size, uint8_t mode);
uint32_t LCD_Pow(uint8_t m, uint8_t n);
void LCD_ShowNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size);
void LCD_ShowxNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode);
void LCD_ShowString(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, uint8_t *p);
void GUI_DrawFont16(uint16_t x, uint16_t y, uint8_t *s, uint8_t mode);
void GUI_DrawFont24(uint16_t x, uint16_t y, uint8_t *s, uint8_t mode);
void GUI_DrawFont32(uint16_t x, uint16_t y, uint8_t *s, uint8_t mode);
void Show_Str(uint16_t x, uint16_t y, uint8_t *str, uint8_t size, uint8_t mode);
void Gui_Drawbmp16(uint16_t x, uint16_t y, const unsigned char *p); // 显示40*40图片
void Gui_StrCenter(uint16_t x, uint16_t y, uint8_t *str, uint8_t size, uint8_t mode);
void Load_Drow_Dialog(void);
void gui_draw_hline(uint16_t x0, uint16_t y0, uint16_t len, uint16_t color);
void gui_fill_circle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color);
void lcd_draw_bline(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t size, uint16_t color);
void tft_lcd_draw_pic(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t *color_buf);
void LCD_Fill_lvgl(uint8_t sx, uint8_t sy, uint8_t ex, uint8_t ey, uint16_t *color);
void logo_disp();
#endif
2、源文件:
#include "st7735s_lcd.h"
//=======================================液晶屏接线===========================================//
// 数据总线类型为8位并口
// DB0~DB7 = GPIOB:0~7 8位数据线
// CS = PC11 片选信号
// RS = PC10 数据/命令选择控制信号
// WR = PC13 写控制信号
// RD = PC14 读控制信号
// RST = PC15 复位信号
// LED = PC0 背光开关控制
// LCD的画笔颜色和背景色
uint16_t POINT_COLOR = RED; // 画笔颜色
uint16_t BACK_COLOR = BLACK; // 背景色
// 管理LCD重要参数
// 默认为竖屏
_lcd_dev lcddev;
/// @brief 将数据依次写入D0~D7
/// @param data:输入的八位数据
/// eg: 0x11 —— 0001 0001:DB7 ~ DB0
void DataOut(uint8_t data)
{
#if 0
uint8_t data_buff[8] = {0};
for(uint8_t i = 0; i < 8; i++)
{
data_buff[i] = (data >> (7 - i)) & 0x01;
}
gpio_bit_write(LCD_DB_Port, LCD_DB0_Pin,data_buff[7]); // LCD_DB0
gpio_bit_write(LCD_DB_Port, LCD_DB1_Pin,data_buff[6]);
gpio_bit_write(LCD_DB_Port, LCD_DB2_Pin,data_buff[5]);
gpio_bit_write(LCD_DB_Port, LCD_DB3_Pin,data_buff[4]);
gpio_bit_write(LCD_DB_Port, LCD_DB4_Pin,data_buff[3]);
gpio_bit_write(LCD_DB_Port, LCD_DB5_Pin,data_buff[2]);
gpio_bit_write(LCD_DB_Port, LCD_DB6_Pin,data_buff[1]);
gpio_bit_write(LCD_DB_Port, LCD_DB7_Pin,data_buff[0]); // LCD_DB7
#endif
GPIO_BOP(GPIOB) = (data & 0x00FF) // 置位有效位
| ((~data & 0x00FF) << 16); // 仅复位PB0~PB7
}
uint8_t DataIn(void)
{
uint8_t data = 0;
uint8_t data_buff[8] = {0};
data_buff[0] = gpio_input_bit_get(LCD_DB_Port, LCD_DB0_Pin);
data_buff[1] = gpio_input_bit_get(LCD_DB_Port, LCD_DB1_Pin);
data_buff[2] = gpio_input_bit_get(LCD_DB_Port, LCD_DB2_Pin);
data_buff[3] = gpio_input_bit_get(LCD_DB_Port, LCD_DB3_Pin);
data_buff[4] = gpio_input_bit_get(LCD_DB_Port, LCD_DB4_Pin);
data_buff[5] = gpio_input_bit_get(LCD_DB_Port, LCD_DB5_Pin);
data_buff[6] = gpio_input_bit_get(LCD_DB_Port, LCD_DB6_Pin);
data_buff[7] = gpio_input_bit_get(LCD_DB_Port, LCD_DB7_Pin);
// Combine bits from data_buff into data
for (uint8_t i = 0; i < 8; i++)
{
data |= (data_buff[i] << i);
}
return data;
}
// 写寄存器函数
// data:寄存器值
// eg:0xB1 :1011 0001 -- D7~D0
// D/CX WRX RDX D17-8 D7 D6 D5 D4 D3 D2 D1 D0
// 0 ↑ 1 - 1 0 1 1 0 0 0 1
//
void LCD_WR_REG(uint8_t data)
{
LCD_RS_CLR; // 数据/命令:0——命令、1——数据
LCD_CS_CLR; // 片选拉低(开始传输)
DATAOUT(data); // 写入命令
LCD_WR_CLR; // Wr下降沿(开始写入)
LCD_WR_SET; // Wr上升沿(数据锁存)
LCD_CS_SET; // CS拉高(结束传输)
}
// 写数据函数
// data:寄存器值
void LCD_WR_DATA(uint8_t data)
{
LCD_RS_SET; // 设置DCX信号,1:数据
LCD_CS_CLR; // CS拉低
DATAOUT(data); // 写入数据
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
// LCD写GRAM
// RGB_Code:颜色值
void LCD_WriteRAM(uint16_t RGB_Code)
{
// 写十六位GRAM
LCD_WR_DATA(RGB_Code >> 8); // 先送高8为
LCD_WR_DATA(RGB_Code); // 后送低8为
}
// 写寄存器
// LCD_Reg:寄存器编号
// LCD_RegValue:要写入的值
void LCD_WriteReg(uint16_t LCD_Reg, uint16_t LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WriteRAM(LCD_RegValue);
}
// 开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(lcddev.wramcmd); // 0x2C
}
// 当mdk -O1时间优化时需要设置,(没用到)
// 延时i
void opt_delay(uint8_t i)
{
while (i--)
;
}
// LCD开启显示
void LCD_DisplayOn(void)
{
LCD_WR_REG(DISP_ON); // 开启显示
}
// LCD关闭显示
void LCD_DisplayOff(void)
{
LCD_WR_REG(DISP_OFF); // 关闭显示
}
// 设置光标位置
// Xpos:横坐标
// Ypos:纵坐标
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos >> 8);
LCD_WR_DATA(Xpos & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos >> 8);
LCD_WR_DATA(Ypos & 0XFF);
}
// 画点
// x,y:坐标
// POINT_COLOR:此点的颜色
void LCD_DrawPoint(uint16_t x, uint16_t y)
{
LCD_SetCursor(x, y); // 设置光标位置
LCD_WriteRAM_Prepare(); // 开始写入GRAM
LCD_WriteRAM(POINT_COLOR);
}
// 快速画点
// x,y:坐标
// color:颜色
void LCD_Fast_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
{
// 设置光标位置
LCD_SetCursor(x, y);
// 写入颜色
LCD_WriteReg(lcddev.wramcmd, color);
}
// dir:方向选择 0-0度旋转,1-180度旋转,2-270度旋转,3-90度旋转
void LCD_Display_Dir(uint8_t dir)
{
if (dir == 0 || dir == 1) // 竖屏
{
lcddev.dir = 0; // 竖屏
lcddev.width = 128;
lcddev.height = 160;
lcddev.wramcmd = 0X2C;
lcddev.setxcmd = 0X2A;
lcddev.setycmd = 0X2B;
if (dir == 0) // 0-0度旋转
{
LCD_WR_REG(0x36); // 设置屏幕扫描方向命令
LCD_WR_DATA((0 << 3) | (1 << 7) | (1 << 6) | (0 << 5)); // 0xC0
}
else // 1-180度旋转
{
LCD_WR_REG(0x36);
LCD_WR_DATA((0 << 3) | (0 << 7) | (0 << 6) | (0 << 5)); // 0x00
}
}
else if (dir == 2 || dir == 3)
{
lcddev.dir = 1; // 横屏模式
lcddev.width = 160; // 实际物理宽度(旋转后的逻辑宽度) 宽160
lcddev.height = 128; // 实际物理高度(旋转后的逻辑高度) 高128
// 设置GRAM相关指令(ST7735S芯片固定值)
lcddev.wramcmd = 0X2C; // 写GRAM指令
lcddev.setxcmd = 0X2A; // 设置X/列坐标指令
lcddev.setycmd = 0X2B; // 设置Y/行坐标指令
if (dir == 2) // 2-270度旋转
{
LCD_WR_REG(0x36); // 发送屏幕方向控制命令
LCD_WR_DATA((0 << 3) | (0 << 7) | (1 << 6) | (1 << 5)); // 参数组合:0<<3 | 0<<7 | 1<<6 | 1<<5 → 二进制01100000 (0x60)
}
else // 3-90度旋转
{
LCD_WR_REG(0x36);
LCD_WR_DATA((0 << 3) | (1 << 7) | (0 << 6) | (1 << 5)); // (0xA0)
}
}
// 设置有效显示区域
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(0); LCD_WR_DATA(0); // X起始地址 0
LCD_WR_DATA((lcddev.width - 1) >> 8); // X结束地址高字节:0x00 (159>>8=0)
LCD_WR_DATA((lcddev.width - 1) & 0XFF); // X结束地址低字节:0x9F (159)
LCD_WR_REG(lcddev.setycmd); // 设置Y轴坐标
LCD_WR_DATA(0); LCD_WR_DATA(0);
LCD_WR_DATA((lcddev.height - 1) >> 8);
LCD_WR_DATA((lcddev.height - 1) & 0XFF);
}
// 设置窗口,并自动设置画点坐标到窗口左上角(sx,sy).
// sx,sy:窗口起始坐标(左上角)
// width,height:窗口宽度和高度,必须大于0!!
// 窗体大小:width*height.
void LCD_Set_Window(uint16_t sx, uint16_t sy, uint16_t width, uint16_t height)
{
uint16_t twidth, theight; // 160
twidth = sx + width - 1; // 减1是因为计算机图形学中从0开始计数的特性,以及硬件寄存器对结束地址的定义,确保窗口范围准确无误。
theight = sy + height - 1; // 0+128-1 计算窗口下边界
// 设置X坐标
LCD_WR_REG(lcddev.setxcmd); // 发送设置X坐标命令
LCD_WR_DATA(sx >> 8); // 取x坐标高8位,高位先发送
LCD_WR_DATA(sx & 0XFF); // 取x坐标低8位
LCD_WR_DATA(twidth >> 8); // 取x坐标高8位,高位先发送
LCD_WR_DATA(twidth & 0XFF); // 取x坐标低8位
// 设置Y坐标
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(sy >> 8);
LCD_WR_DATA(sy & 0XFF);
LCD_WR_DATA(theight >> 8);
LCD_WR_DATA(theight & 0XFF);
}
void LCD_GPIO_Init(void)
{
// 开启时钟GPIOB|C
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
// 配置引脚
gpio_init(LCD_EN_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, LCD_EN_Pin);
gpio_init(LCD_CS_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX,
LCD_CS_Pin | LCD_RS_Pin | LCD_WR_Pin | LCD_RD_Pin | LCD_RESET_Pin);
gpio_bit_set(LCD_CS_Port, LCD_CS_Pin);
gpio_bit_set(LCD_RS_Port, LCD_RS_Pin);
gpio_bit_set(LCD_WR_Port, LCD_WR_Pin | LCD_RD_Pin | LCD_RESET_Pin);
gpio_init(LCD_DB_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, LCD_DB0_Pin | LCD_DB3_Pin | LCD_DB4_Pin | LCD_DB5_Pin | LCD_DB6_Pin | LCD_DB7_Pin);
dbg_trace_pin_disable(); // 禁用跟踪引脚分配, 跟踪引脚分配使能由DBG_CTL控制寄存器控制
rcu_periph_clock_enable(RCU_AF); // 使能映射功能的时钟
/* PB3、PB4默认为JTAG引脚,需要重新映射;不要将JTAG-DP与SW-DP同时关闭,否侧将无法烧录程序 */
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
gpio_init(LCD_DB_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_MAX, LCD_DB1_Pin | LCD_DB2_Pin);
gpio_bit_set(LCD_DB_Port, LCD_DB0_Pin | LCD_DB1_Pin | LCD_DB2_Pin | LCD_DB3_Pin |
LCD_DB4_Pin | LCD_DB5_Pin | LCD_DB6_Pin | LCD_DB7_Pin);
}
// 初始化lcd
void LCD_Init(void)
{
LCD_GPIO_Init();
// RCC->APB2ENR|=1<<0; //开启辅助时钟
// JTAG_Set(SWD_ENABLE); //开启SWD
/* 复位 */
LCD_RST_SET;
delay_1ms(1);
LCD_RST_CLR;
delay_1ms(10);
LCD_RST_SET;
delay_1ms(120);
//************* Start Initial Sequence **********//
delay_1ms(120); // ms
LCD_WR_REG(0x11); // 退出睡眠
delay_1ms(120); // delay_1ms 120ms
LCD_WR_REG(LCD_FRMCTR1); // 帧速率控制(处于正常模式/全色模式)
LCD_WR_DATA(0x00); // frame rate=85.3Hz
LCD_WR_DATA(0x2C); //
LCD_WR_DATA(0x2B);
LCD_WR_REG(LCD_FRMCTR2); // 设置空闲模式的帧频率。
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x01);
LCD_WR_REG(LCD_FRMCTR3); // In partial mode
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x01);
LCD_WR_REG(LCD_INVCTR); DOT反转显示反转控制
LCD_WR_DATA(0x03);
LCD_WR_REG(0xB9); // In normal mode
LCD_WR_DATA(0xFF);
LCD_WR_DATA(0x83);
LCD_WR_DATA(0x47);
LCD_WR_REG(0xC0); // VRH: Set the GVDD
LCD_WR_DATA(0xA2);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x84);
LCD_WR_REG(0xC1); // set VGH/ VGL
LCD_WR_DATA(0x02); //??02 VGH=16.6 VGL=-7.5 00 VGH=11.6 VGL=-7.5 06 VGH=16.6 VGL=-10
LCD_WR_REG(0xC2); // APA: adjust the operational amplifier DCA: adjust the booster Voltage
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC3); // In Idle mode (8-colors)
LCD_WR_DATA(0x8A);
LCD_WR_DATA(0x2A);
LCD_WR_REG(0xC4); // In partial mode + Full color
LCD_WR_DATA(0x8A);
LCD_WR_DATA(0xEE);
LCD_WR_REG(0xC5); // VCOM
LCD_WR_DATA(0x09);
LCD_WR_REG(0x20); // Display inversion
LCD_WR_REG(0xC7);
LCD_WR_DATA(0x10);
LCD_WR_REG(0x36); // MX, MY, RGB mode
LCD_WR_DATA(0xC0); // 08
LCD_WR_REG(0xE0);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x1C);
LCD_WR_DATA(0x1B);
LCD_WR_DATA(0x1A);
LCD_WR_DATA(0x2F);
LCD_WR_DATA(0x28);
LCD_WR_DATA(0x20);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x23);
LCD_WR_DATA(0x22);
LCD_WR_DATA(0x2A);
LCD_WR_DATA(0x36);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x10);
LCD_WR_REG(0xE1);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x1A);
LCD_WR_DATA(0x1A);
LCD_WR_DATA(0x1A);
LCD_WR_DATA(0x2E);
LCD_WR_DATA(0x27);
LCD_WR_DATA(0x21);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x22);
LCD_WR_DATA(0x2A);
LCD_WR_DATA(0x35);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x05);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x10);
LCD_WR_REG(0x35); // 65k mode
LCD_WR_DATA(0x00);
LCD_WR_REG(0x3A); // 65k mode
LCD_WR_DATA(0x05);
LCD_WR_REG(0x29); // Display on
// LCD_DisplayOff();
LCD_Display_Dir(USE_LCM_DIR); // 屏幕方向
LCD_LED(0);
// LCD_Clear(BLACK);
}
// brief:设置数据线模式
// para:mode,0--输入、1--输出
void LCD_DB_Mode(uint8_t mode, uint8_t status)
{
if (mode)
{
// DB0~7:通用推挽输出模式
gpio_init(LCD_DB_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, LCD_DB0_Pin | LCD_DB1_Pin | LCD_DB2_Pin | LCD_DB3_Pin | LCD_DB4_Pin | LCD_DB5_Pin | LCD_DB6_Pin | LCD_DB7_Pin);
}
else
{
// DB0~7: 上拉输入模式
gpio_init(LCD_DB_Port, GPIO_MODE_IPU, GPIO_OSPEED_10MHZ, LCD_DB0_Pin | LCD_DB1_Pin | LCD_DB2_Pin | LCD_DB3_Pin | LCD_DB4_Pin | LCD_DB5_Pin | LCD_DB6_Pin | LCD_DB7_Pin);
}
// 全部输出
gpio_bit_write(LCD_DB_Port, LCD_DB0_Pin | LCD_DB1_Pin | LCD_DB2_Pin | LCD_DB3_Pin | LCD_DB4_Pin | LCD_DB5_Pin | LCD_DB6_Pin | LCD_DB7_Pin, status);
}
// 读LCD数据
// 返回值:读到的值
uint16_t LCD_RD_DATA(void)
{
uint16_t t;
// 数据线输入,全部输出0
LCD_DB_Mode(DB_PORT_INPUT, 0);
LCD_RS_SET;
LCD_CS_CLR;
// 读取数据(读寄存器时,并不需要读2次)
LCD_RD_CLR;
t = DataIn();
LCD_RD_SET;
LCD_CS_SET;
// 数据线输出,全部输出高
LCD_DB_Mode(DB_PORT_OUTPUT, 1);
return t = t >> 8;
}
// 读显示屏 ID 指令:0X04
uint16_t LCD_Read_ID(uint8_t reg)
{
LCD_WR_REG(reg);
LCD_RD_DATA(); // dummy read
LCD_RD_DATA();
lcddev.id = LCD_RD_DATA();
lcddev.id <<= 8;
lcddev.id |= LCD_RD_DATA();
return lcddev.id;
}
// 读取个某点的颜色值
// x,y:坐标
// 返回值:此点的颜色
uint16_t LCD_ReadPoint(uint16_t x, uint16_t y)
{
uint16_t r, g, b;
if (x >= lcddev.width || y >= lcddev.height)
return 0; // 超过了范围,直接返回
LCD_SetCursor(x, y);
// LCD_SetCursor(28,28);
LCD_WR_REG(0X2E); // 9341/6804/3510/1963 发送读GRAM指令
// GPIOB->CRL=0X88888888; //PB0-7 上拉输入
// GPIOB->CRH=0X88888888; //PB8-15 上拉输入
// GPIOB->ODR=0XFFFF; //全部输出高
LCD_DB_Mode(DB_PORT_INPUT, 1);
LCD_RS_SET;
LCD_CS_CLR;
// 读取数据(假读)
LCD_RD_CLR;
opt_delay(2); // 延时
// r=DATAIN; //dummy READ
LCD_RD_SET;
// 读取数据(假读)
LCD_RD_CLR;
opt_delay(2); // 延时
// r=DATAIN; //dummy READ
LCD_RD_SET;
// 读取数据(假读)
LCD_RD_CLR;
opt_delay(2); // 延时
// r=DATAIN; //dummy READ
LCD_RD_SET;
// 读取数据(读GRAM时,前四次为假读)
LCD_RD_CLR;
opt_delay(2); // 延时
// r=DATAIN; //dummy READ
LCD_RD_SET;
LCD_RD_CLR;
opt_delay(2); // 延时
r = DataIn(); // 读取红色值
r = r >> 8;
LCD_RD_SET;
LCD_RD_CLR;
opt_delay(2); // 延时
g = DataIn(); // 读取绿色值
g = g >> 8;
LCD_RD_SET;
LCD_RD_CLR;
opt_delay(2); // 延时
b = DataIn(); // 读取蓝色值
b = b >> 8;
LCD_RD_SET;
LCD_CS_SET;
r = r & 0xFF;
g = g & 0xFF;
b = b & 0xFF;
// GPIOB->CRL=0X33333333; //PB0-7 上拉输出
// GPIOB->CRH=0X33333333; //PB8-15 上拉输出
// GPIOB->ODR=0XFFFF; //全部输出高
LCD_DB_Mode(DB_PORT_OUTPUT, 1);
return (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3));
// return r;
}
// 清屏函数
// color:要清屏的填充色
void LCD_Clear(uint16_t color)
{
uint32_t index = 0;
uint32_t totalpoint = lcddev.width;
totalpoint *= lcddev.height; // 得到总点数
LCD_SetCursor(0x00, 0x0000); // 设置光标位置
LCD_WriteRAM_Prepare(); // 开始写入GRAM
for (index = 0; index < totalpoint; index++)
{
LCD_WriteRAM(color);
}
}
// 在指定区域内填充指定颜色
// 区域大小:(xend-xsta+1)*(yend-ysta+1)
// xsta
// color:要填充的颜色
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t color)
{
uint16_t i, j;
uint16_t xlen = 0;
uint16_t temp;
if ((lcddev.id == 0X6804) && (lcddev.dir == 1)) // 6804横屏的时候特殊处理
{
temp = sx;
sx = sy;
sy = lcddev.width - ex - 1;
ex = ey;
ey = lcddev.width - temp - 1;
lcddev.dir = 0;
lcddev.setxcmd = 0X2A;
lcddev.setycmd = 0X2B;
LCD_Fill(sx, sy, ex, ey, color);
lcddev.dir = 1;
lcddev.setxcmd = 0X2B;
lcddev.setycmd = 0X2A;
}
else
{
xlen = ex - sx + 1;
for (i = sy; i <= ey; i++)
{
LCD_SetCursor(sx, i); // 设置光标位置
LCD_WriteRAM_Prepare(); // 开始写入GRAM
for (j = 0; j < xlen; j++)
LCD_WriteRAM(color); // 设置光标位置
}
}
}
// 在指定区域内填充指定颜色块
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
// color:要填充的颜色
void LCD_Color_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)
{
uint16_t height, width;
uint16_t i, j;
width = ex - sx + 1; // 得到填充的宽度
height = ey - sy + 1; // 高度
for (i = 0; i < height; i++)
{
LCD_SetCursor(sx, sy + i); // 设置光标位置
LCD_WriteRAM_Prepare(); // 开始写入GRAM
for (j = 0; j < width; j++)
LCD_WriteRAM(color[i * width + j]); // 写入数据
}
}
// 画线
// x1,y1:起点坐标
// x2,y2:终点坐标
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
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_DrawPoint(uRow, uCol); // 画点
xerr += delta_x;
yerr += delta_y;
if (xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
}
// 画矩形
//(x1,y1),(x2,y2):矩形的对角坐标
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
LCD_DrawLine(x1, y1, x2, y1);
LCD_DrawLine(x1, y1, x1, y2);
LCD_DrawLine(x1, y2, x2, y2);
LCD_DrawLine(x2, y1, x2, y2);
}
// 在指定位置画一个指定大小的圆
//(x,y):中心点
// r :半径
void LCD_Draw_Circle(uint16_t x0, uint16_t y0, uint8_t r)
{
int a, b;
int di;
a = 0;
b = r;
di = 3 - (r << 1); // 判断下个点位置的标志
while (a <= b)
{
LCD_DrawPoint(x0 + a, y0 - b); // 5
LCD_DrawPoint(x0 + b, y0 - a); // 0
LCD_DrawPoint(x0 + b, y0 + a); // 4
LCD_DrawPoint(x0 + a, y0 + b); // 6
LCD_DrawPoint(x0 - a, y0 + b); // 1
LCD_DrawPoint(x0 - b, y0 + a);
LCD_DrawPoint(x0 - a, y0 - b); // 2
LCD_DrawPoint(x0 - b, y0 - a); // 7
a++;
// 使用Bresenham算法画圆
if (di < 0)
di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b--;
}
}
}
// 在指定位置显示一个字符
// x,y:起始坐标
// num:要显示的字符:" "--->"~"
// size:字体大小 12/16/24
// mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(uint16_t x, uint16_t y, uint8_t num, uint8_t size, uint8_t mode)
{
uint8_t temp, t1, t;
uint16_t y0 = y;
uint8_t csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); // 得到字体一个字符对应点阵集所占的字节数
num = num - ' '; // 得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
for (t = 0; t < csize; t++)
{
if (size == 12)
temp = asc2_1206[num][t]; // 调用1206字体
else if (size == 16)
temp = asc2_1608[num][t]; // 调用1608字体
else if (size == 24)
temp = asc2_2412[num][t]; // 调用2412字体
else
return; // 没有的字库
for (t1 = 0; t1 < 8; t1++)
{
if (temp & 0x80)
LCD_Fast_DrawPoint(x, y, POINT_COLOR);
else if (mode == 0)
LCD_Fast_DrawPoint(x, y, BACK_COLOR);
temp <<= 1;
y++;
if (y >= lcddev.height)
return; // 超区域了
if ((y - y0) == size)
{
y = y0;
x++;
if (x >= lcddev.width)
return; // 超区域了
break;
}
}
}
}
// m^n函数
// 返回值:m^n次方.
uint32_t LCD_Pow(uint8_t m, uint8_t n)
{
uint32_t result = 1;
while (n--)
result *= m;
return result;
}
// 显示数字,高位为0,则不显示
// x,y :起点坐标
// len :数字的位数
// size:字体大小
// color:颜色
// num:数值(0~4294967295);
void LCD_ShowNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size)
{
uint8_t t, temp;
uint8_t enshow = 0;
for (t = 0; t < len; t++)
{
temp = (num / LCD_Pow(10, len - t - 1)) % 10;
if (enshow == 0 && t < (len - 1))
{
if (temp == 0)
{
LCD_ShowChar(x + (size / 2) * t, y, ' ', size, 0);
continue;
}
else
enshow = 1;
}
LCD_ShowChar(x + (size / 2) * t, y, temp + '0', size, 0);
}
}
// 显示数字,高位为0,还是显示
// x,y:起点坐标
// num:数值(0~999999999);
// len:长度(即要显示的位数)
// size:字体大小
// mode:
//[7]:0,不填充;1,填充0.
//[6:1]:保留
//[0]:0,非叠加显示;1,叠加显示.
void LCD_ShowxNum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode)
{
uint8_t t, temp;
uint8_t enshow = 0;
for (t = 0; t < len; t++)
{
temp = (num / LCD_Pow(10, len - t - 1)) % 10;
if (enshow == 0 && t < (len - 1))
{
if (temp == 0)
{
if (mode & 0X80)
LCD_ShowChar(x + (size / 2) * t, y, '0', size, mode & 0X01);
else
LCD_ShowChar(x + (size / 2) * t, y, ' ', size, mode & 0X01);
continue;
}
else
enshow = 1;
}
LCD_ShowChar(x + (size / 2) * t, y, temp + '0', size, mode & 0X01);
}
}
// 显示字符串
// x,y:起点坐标
// width,height:区域大小
// size:字体大小
//*p:字符串起始地址
void LCD_ShowString(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, uint8_t *p)
{
uint8_t x0 = x;
width += x;
height += y;
while ((*p <= '~') && (*p >= ' ')) // 判断是不是非法字符!
{
if (x >= width)
{
x = x0;
y += size;
}
if (y >= height)
break; // 退出
LCD_ShowChar(x, y, *p, size, 0);
x += size / 2;
p++;
}
}
#if 0
//汉字 16*16
void GUI_DrawFont16(uint16_t x, uint16_t y, uint8_t *s, uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
{ LCD_Set_Window(x,y,16,16);
LCD_WriteRAM_Prepare();
for(i=0;i<16*2;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont16[k].Msk[i]&(0x80>>j)) LCD_WriteRAM(POINT_COLOR);
else LCD_WriteRAM(BACK_COLOR);
}
else
{
//POINT_COLOR=fc;
if(tfont16[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==16)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢复窗口为全屏
}
//汉字 24*24
void GUI_DrawFont24(uint16_t x, uint16_t y, uint8_t *s,uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
{ LCD_Set_Window(x,y,24,24);
LCD_WriteRAM_Prepare();
for(i=0;i<24*3;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont24[k].Msk[i]&(0x80>>j)) LCD_WriteRAM(POINT_COLOR);
else LCD_WriteRAM(BACK_COLOR);
}
else
{
//POINT_COLOR=fc;
if(tfont24[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==24)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢复窗口为全屏
}
//汉字 32*32
void GUI_DrawFont32(uint16_t x, uint16_t y, uint8_t *s,uint8_t mode)
{
uint8_t i,j;
uint16_t k;
uint16_t HZnum;
uint16_t x0=x;
HZnum=sizeof(tfont32) / sizeof(typFNT_GB32); //自动统计汉字数目
for (k=0;k<HZnum;k++)
{
if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
{ LCD_Set_Window(x,y,32,32);
LCD_WriteRAM_Prepare();
for(i=0;i<32*4;i++)
{
for(j=0;j<8;j++)
{
if(!mode) //非叠加方式
{
if(tfont32[k].Msk[i]&(0x80>>j)) LCD_WriteRAM(POINT_COLOR);
else LCD_WriteRAM(BACK_COLOR);
}
else
{
//POINT_COLOR=fc;
if(tfont32[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点
x++;
if((x-x0)==32)
{
x=x0;
y++;
break;
}
}
}
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//恢复窗口为全屏
}
#endif
// 显示汉字或者字符串
void Show_Str(uint16_t x, uint16_t y, uint8_t *str, uint8_t size, uint8_t mode)
{
uint16_t x0 = x;
uint8_t bHz = 0; // 字符或者中文 默认为英文
while (*str != 0) // 数据未结束
{
if (!bHz)
{
if (x > (lcddev.width - size / 2) || y > (lcddev.height - size))
return;
if (*str > 0x80)
bHz = 1; // 中文
else // 字符
{
if (*str == 0x0D) // 换行符号
{
y += size;
x = x0;
str++;
}
else
{
if (size >= 24) // 字库中没有集成12X24 16X32的英文字体,用8X16代替
{
LCD_ShowChar(x, y, *str, 24, mode);
x += 12; // 字符,为全字的一半
}
else
{
LCD_ShowChar(x, y, *str, size, mode);
x += size / 2; // 字符,为全字的一半
}
}
str++;
}
}
else // 中文
{
if (x > (lcddev.width - size) || y > (lcddev.height - size))
return;
bHz = 0; // 有汉字库
/* 屏蔽掉中文显示 */
// if(size==32)
// GUI_DrawFont32(x,y,str,mode);
// else if(size==24)
// GUI_DrawFont24(x,y,str,mode);
// else
// GUI_DrawFont16(x,y,str,mode);
str += 2;
x += size; // 下一个汉字偏移
}
}
}
// 显示40*40图片
void Gui_Drawbmp16(uint16_t x, uint16_t y, const unsigned char *p) // 显示40*40图片
{
uint16_t i;
uint8_t picH, picL;
LCD_Set_Window(x, y, 40, 40);
LCD_WriteRAM_Prepare();
for (i = 0; i < 40 * 40; i++)
{
picL = *(p + i * 2); // 数据低位在前
picH = *(p + i * 2 + 1);
LCD_WriteRAM(picH << 8 | picL);
}
LCD_Set_Window(0, 0, lcddev.width, lcddev.height); // 恢复显示窗口为全屏
}
// 居中显示
void Gui_StrCenter(uint16_t x, uint16_t y, uint8_t *str, uint8_t size, uint8_t mode)
{
uint16_t x1;
uint16_t len = strlen((const char *)str);
if (size > 16)
{
x1 = (lcddev.width - len * (size / 2)) / 2;
}
else
{
x1 = (lcddev.width - len * 8) / 2;
}
Show_Str(x + x1, y, str, size, mode);
}
void Load_Drow_Dialog(void)
{
LCD_Clear(WHITE); // 清屏
POINT_COLOR = BLUE; // 设置字体为蓝色
BACK_COLOR = WHITE;
LCD_ShowString(lcddev.width - 24, 0, 200, 16, 16, "RST"); // 显示清屏区域
POINT_COLOR = RED; // 设置画笔蓝色
}
// 电容触摸屏专有部分
// 画水平线
// x0,y0:坐标
// len:线长度
// color:颜色
void gui_draw_hline(uint16_t x0, uint16_t y0, uint16_t len, uint16_t color)
{
if (len == 0)
return;
LCD_Fill(x0, y0, x0 + len - 1, y0, color);
}
// 画实心圆
// x0,y0:坐标
// r:半径
// color:颜色
void gui_fill_circle(uint16_t x0, uint16_t y0, uint16_t r, uint16_t color)
{
uint32_t i;
uint32_t imax = ((uint32_t)r * 707) / 1000 + 1;
uint32_t sqmax = (uint32_t)r * (uint32_t)r + (uint32_t)r / 2;
uint32_t x = r;
gui_draw_hline(x0 - r, y0, 2 * r, color);
for (i = 1; i <= imax; i++)
{
if ((i * i + x * x) > sqmax) // draw lines from outside
{
if (x > imax)
{
gui_draw_hline(x0 - i + 1, y0 + x, 2 * (i - 1), color);
gui_draw_hline(x0 - i + 1, y0 - x, 2 * (i - 1), color);
}
x--;
}
// draw lines from inside (center)
gui_draw_hline(x0 - x, y0 + i, 2 * x, color);
gui_draw_hline(x0 - x, y0 - i, 2 * x, color);
}
}
// 画一条粗线
//(x1,y1),(x2,y2):线条的起始坐标
// size:线条的粗细程度
// color:线条的颜色
void lcd_draw_bline(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t size, uint16_t color)
{
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
if (x1 < size || x2 < size || y1 < size || y2 < size)
return;
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++) // 画线输出
{
gui_fill_circle(uRow, uCol, size, color); // 画点
xerr += delta_x;
yerr += delta_y;
if (xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
}
void tft_lcd_draw_pic(uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint16_t *color_buf)
{
uint16_t i;
uint32_t total_point = (x_end - x_start) * (y_end - y_start);
LCD_Set_Window(x_start, y_start, x_end, y_end);
LCD_WriteRAM_Prepare();
for (i = 0; i < total_point; i++)
{
LCD_WriteRAM(*color_buf);
color_buf++;
}
LCD_Set_Window(0, 0, lcddev.width, lcddev.height); // 恢复显示窗口为全屏
}
void LCD_Fill_lvgl(uint8_t sx, uint8_t sy, uint8_t ex, uint8_t ey, uint16_t *color)
{
uint8_t i, j;
uint8_t width = ex - sx; // 得到填充的宽度
uint8_t height = ey - sy; // 高度
LCD_Set_Window(sx, sy, ex, ey); // 设置显示窗口
LCD_WriteRAM_Prepare();
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
LCD_WriteRAM(*color); // 写入数据
color++;
}
}
}
void logo_disp()
{
tft_lcd_draw_pic(0, 0, LCD_HEIGHT, LCD_WIDTH, (uint16_t *)gImage_start);
LCD_LED(1); // 点亮背光
}
三、部分代码解析
/// @brief 将数据依次写入D0~D7
/// @param data:输入的八位数据
/// eg: 0x11 —— 0001 0001:DB7 ~ DB0
void DataOut(uint8_t data)
{
GPIO_BOP(GPIOB) = (data & 0x00FF) // 置位有效位
| ((~data & 0x00FF) << 16); // 仅复位PB0~PB7
}
GPIO_BOP寄存器:端口位操作寄存器 (GPIOx_BOP, x=A..G)
分步解析:
假设输入data = 0xA5(二进制10100101)
1、置位操作部分:
data & 0x00FF → 0xA5(保留低8位)
对应二进制:10100101
置位GPIOB的PB0~7
2、复位操作部分:
~data → 0x5A(01011010)
(~data & 0x00FF) << 16 → 0x5A0000
高16位的第16-23位有效(对应复位PB0-PB7)
复位GPIOB的PB0~7