【兆易GD32H759I-EVAL】TLI与LCD显示实现(2)
[复制链接]
本帖最后由 尹小舟 于 2024-6-23 20:02 编辑
本实验移植正点原子LCD驱动
画点函数
void lcd_point_set(uint16_t xpos, uint16_t ypos, uint16_t color)
{
*(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*ypos) + xpos)) = color;
}
-
函数定义:
- 函数名:lcd_point_set
- 参数:
- xpos:一个无符号16位整数,表示点的x坐标。
- ypos:一个无符号16位整数,表示点的y坐标。
- color:一个无符号16位整数,表示要设置的颜色。
- 返回值:无(void)
-
函数功能:
- 根据给定的xpos和ypos,在LCD的当前帧缓冲区(current_framebuffer)中设置指定颜色的点。
-
参数详解:
- \param[in] xpos, ypos, color:这些是函数的输入参数,用于传递x位置、y位置和颜色值给函数。
- 该函数没有返回值(retval)。
-
函数体:
- *(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*ypos) + xpos)) = color;
- 这行代码执行了实际的点设置操作。
- __IO 是一个修饰符,通常用于指示编译器这个变量是“输入/输出”的
- current_framebuffer 是一个指向帧缓冲区的指针(这个指针可能在其他地方定义)。帧缓冲区通常用于存储要在LCD上显示的像素数据。
- LCD_PIXEL_WIDTH 是一个常量,表示LCD的像素宽度。
- 通过计算 (LCD_PIXEL_WIDTH*ypos) + xpos,我们可以找到特定点在帧缓冲区中的位置(索引)。但是,因为我们每个像素用2个字节(16位)来表示颜色,所以需要乘以2来获取字节地址。
- 然后,我们将计算出的地址强制转换为指向uint16_t的指针,并解引用它以写入颜色值。
代码的移植关键是实现LCD的初始化,和实现画点函数
#ifndef __LCD_H
#define __LCD_H
#include "stdlib.h"
#include "gd32h7xx.h"
#include "./BSP/LCD/tli.h"
/******************************************************************************************/
//设置RGB屏方向
//0为竖屏 1为横屏
#define RGB_DIR 1
/* 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 uint32_t g_point_color; /* 默认红色 */
extern uint32_t g_back_color; /* 背景颜色,默认为白色 */
/* LCD背光控制 */
#define LCD_BL(x) do{ x ? \
gpio_bit_write(GPIOJ, GPIO_PIN_10, SET) : \
gpio_bit_write(GPIOJ, GPIO_PIN_10, RESET); \
}while(0)
/* LCD复位引脚 */
#define LCD_RST(x) do{ x ? \
gpio_bit_write(GPIOJ, GPIO_PIN_11, SET) : \
gpio_bit_write(GPIOJ, GPIO_PIN_11, RESET); \
}while(0)
/* LCD地址结构体 */
typedef struct
{
volatile uint16_t LCD_REG;
volatile uint16_t LCD_RAM;
} LCD_TypeDef;
/******************************************************************************************/
/* EXMC相关参数 定义
* 注意: 我们默认是通过EXMC块0来连接LCD, 块0有4个片选: EXMC_NE0~3
*
*/
#define LCD_EXMC_NEX 3 /* 使用EXMC_NE3接LCD_CS,取值范围只能是: 0~3 */
#define LCD_EXMC_AX 10 /* 使用EXMC_A10接LCD_RS,取值范围是: 0 ~ 25 */
/* LCD_BASE的详细计算方法:
* 我们一般使用EXMC的块0(BANK0)来驱动TFTLCD液晶屏(MCU屏), 块0地址范围总大小为256MB,均分成4块:
* 存储块0(EXMC_NE0)地址范围: 0X6000 0000 ~ 0X63FF FFFF
* 存储块1(EXMC_NE1)地址范围: 0X6400 0000 ~ 0X67FF FFFF
* 存储块2(EXMC_NE2)地址范围: 0X6800 0000 ~ 0X6BFF FFFF
* 存储块3(EXMC_NE3)地址范围: 0X6C00 0000 ~ 0X6FFF FFFF
*
* 我们需要根据硬件连接方式选择合适的片选(连接LCD_CS)和地址线(连接LCD_RS)
* 开发板使用EXMC_NE3连接LCD_CS, EXMC_A10连接LCD_RS ,16位数据线,计算方法如下:
* 首先EXMC_NE3的基地址为: 0X6C00 0000; NEx的基址为(x=0/1/2/3): 0X6000 0000 + (0X400 0000 * x)
* EXMC_A10对应地址值: 2^10 * 2 = 0X800; EXMC_Ay对应的地址为(y = 0 ~ 25): 2^y * 2
*
* LCD->LCD_REG,对应LCD_RS = 0(LCD寄存器); LCD->LCD_RAM,对应LCD_RS = 1(LCD数据)
* 则 LCD->LCD_RAM的地址为: 0X6C00 0000 + 2^10 * 2 = 0X6C00 0800
* LCD->LCD_REG的地址可以为 LCD->LCD_RAM之外的任意地址.
* 由于我们使用结构体管理LCD_REG 和 LCD_RAM(REG在前,RAM在后,均为16位数据宽度)
* 因此 结构体的基地址(LCD_BASE) = LCD_RAM - 2 = 0X6C00 0800 -2
*
* 更加通用的计算公式为((片选脚EXMC_NEx)x=0/1/2/3, (RS接地址线EXMC_Ay)y=0~25):
* LCD_BASE = (0X6000 0000 + (0X400 0000 * x)) | (2^y * 2 -2)
* 等效于(使用移位操作)
* LCD_BASE = (0X6000 0000 + (0X400 0000 * x)) | ((1 << y) * 2 -2)
*/
#define LCD_BASE (uint32_t)((0X60000000 + (0X4000000 * LCD_EXMC_NEX)) | (((1 << LCD_EXMC_AX) * 2) -2))
#define LCD ((LCD_TypeDef *) LCD_BASE)
/******************************************************************************************/
/* LCD扫描方向和颜色 定义 */
/* 扫描方向定义 */
#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 DFT_SCAN_DIR L2R_U2D /* 默认的扫描方向 */
#if TLI_PIXFORMAT == TLI_PIXFORMAT_RGB565
/* 常用画笔颜色 */
#define WHITE 0xFFFF /* 白色 */
#define BLACK 0x0000 /* 黑色 */
#define RED 0xF800 /* 红色 */
#define GREEN 0x07E0 /* 绿色 */
#define BLUE 0x001F /* 蓝色 */
#define MAGENTA 0XF81F /* 品红色/紫红色 = BLUE + RED */
#define YELLOW 0XFFE0 /* 黄色 = GREEN + RED */
#define CYAN 0X07FF /* 青色 = GREEN + BLUE */
/* 非常用颜色 */
#define BROWN 0XBC40 /* 棕色 */
#define BRRED 0XFC07 /* 棕红色 */
#define GRAY 0X8430 /* 灰色 */
#define DARKBLUE 0X01CF /* 深蓝色 */
#define LIGHTBLUE 0X7D7C /* 浅蓝色 */
#define GRAYBLUE 0X5458 /* 灰蓝色 */
#define LIGHTGREEN 0X841F /* 浅绿色 */
#define LGRAY 0XC618 /* 浅灰色(PANNEL),窗体背景色 */
#define LGRAYBLUE 0XA651 /* 浅灰蓝色(中间层颜色) */
#define LBBLUE 0X2B12 /* 浅棕蓝色(选择条目的反色) */
#elif TLI_PIXFORMAT == TLI_PIXFORMAT_RGB888
/* 常用画笔颜色 */
#define WHITE 0xFFFFFF /* 白色 */
#define BLACK 0x000000 /* 黑色 */
#define RED 0xFF0000 /* 红色 */
#define GREEN 0x00FF00 /* 绿色 */
#define BLUE 0x0000FF /* 蓝色 */
#define MAGENTA 0XFF00FF /* 品红色/紫红色 = BLUE + RED */
#define YELLOW 0XFFFF00 /* 黄色 = GREEN + RED */
#define CYAN 0X00FFFF /* 青色 = GREEN + BLUE */
/* 非常用颜色 */
#define BROWN 0xB88800 /* 棕色 */
#define BRRED 0XFA8038 /* 棕红色 */
#define GRAY 0X808080 /* 灰色 */
#define DARKBLUE 0X00383C /* 深蓝色 */
#define LIGHTBLUE 0X3CACE0 /* 浅蓝色 */
#define GRAYBLUE 0X5088C0 /* 灰蓝色 */
#define LIGHTGREEN 0X8080FA /* 浅绿色 */
#define LGRAY 0XC0C0C0 /* 浅灰色(PANNEL),窗体背景色 */
#define LGRAYBLUE 0XA0C888 /* 浅灰蓝色(中间层颜色) */
#define LBBLUE 0x286090 /* 浅棕蓝色(选择条目的反色) */
//#define BROWN 0xA52A2A /* 棕色 */
//#define BRRED 0XFA8072 /* 棕红色 */
//#define GRAY 0X808080 /* 灰色 */
//#define DARKBLUE 0X003399 /* 深蓝色 */
//#define LIGHTBLUE 0XADD8E6 /* 浅蓝色 */
//#define GRAYBLUE 0X7AB8CC /* 灰蓝色 */
//#define LIGHTGREEN 0X90EE90 /* 浅绿色 */
//#define LGRAY 0XC0C0C0 /* 浅灰色(PANNEL),窗体背景色 */
//#define LGRAYBLUE 0X778899 /* 浅灰蓝色(中间层颜色) */
//#define LBBLUE 0x004D99 /* 浅棕蓝色(选择条目的反色) */
#else
#define WHITE 0xFFFFFFFF /* 白色 */
#define BLACK 0xFF000000 /* 黑色 */
#define RED 0xFFFF0000 /* 红色 */
#define GREEN 0xFF00FF00 /* 绿色 */
#define BLUE 0xFF0000FF /* 蓝色 */
#define MAGENTA 0XFFFF00FF /* 品红色/紫红色 = BLUE + RED */
#define YELLOW 0XFFFFFF00 /* 黄色 = GREEN + RED */
#define CYAN 0XFF00FFFF /* 青色 = GREEN + BLUE */
#define BROWN 0xFFB88800 /* 棕色 */
#define BRRED 0XFFFA8038 /* 棕红色 */
#define GRAY 0XFF808080 /* 灰色 */
#define DARKBLUE 0XFF00383C /* 深蓝色 */
#define LIGHTBLUE 0XFF3CACE0 /* 浅蓝色 */
#define GRAYBLUE 0XFF5088C0 /* 灰蓝色 */
#define LIGHTGREEN 0XFF8080FA /* 浅绿色 */
#define LGRAY 0XFFC0C0C0 /* 浅灰色(PANNEL),窗体背景色 */
#define LGRAYBLUE 0XFFA0C888 /* 浅灰蓝色(中间层颜色) */
#define LBBLUE 0xFF286090 /* 浅棕蓝色(选择条目的反色) */
#define color16M_black 0xFF000000
#define color16M_white 0xFFFFFFFF
#define color16M_red 0x00FF0000
#define color16M_green 0x0000FF00
#define color16M_blue 0x000000FF
#define color16M_blue2 0xFF00BFFF
#define color16M_yellow color16M_red|color16M_green
#define color16M_cyan color16M_green|color16M_blue
#define color16M_magenta color16M_red|color16M_blue
#endif
/******************************************************************************************/
/* 函数声明 */
void lcd_init(void); /* 初始化LCD */
void lcd_display_on(void); /* 开显示 */
void lcd_display_off(void); /* 关显示 */
void lcd_display_dir(uint8_t dir); /* 设置屏幕显示方向 */
uint16_t lcd_read_point(uint16_t x, uint16_t y); /* 读点(32位颜色,兼容TLI) */
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color); /* 画点(32位颜色,兼容TLI) */
void lcd_clear(uint16_t color); /* LCD清屏 */
void lcd_fill_circle(uint16_t x, uint16_t y, uint16_t r, uint32_t color); /* 填充实心圆 */
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint32_t color); /* 画圆 */
void lcd_draw_hline(uint16_t x, uint16_t y, uint16_t len, uint32_t color); /* 画水平线 */
void lcd_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color); /* 纯色填充矩形(32位颜色,兼容TLI) */
void lcd_color_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color); /* 彩色填充矩形 */
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color); /* 画直线 */
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color); /* 画矩形 */
void lcd_show_char(uint16_t x, uint16_t y, char chr, uint8_t size, uint8_t mode, uint32_t color); /* 显示一个字符 */
void lcd_show_num(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint32_t color); /* 显示数字 */
void lcd_show_xnum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode, uint32_t color); /* 扩展显示数字 */
void lcd_show_string(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, char *p, uint32_t color); /* 显示字符串 */
#endif
#include "stdlib.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/LCD/lcdfont.h"
#include "gd32h759i_lcd_eval.h"
#include "gd32h759i_eval_exmc_sdram.h"
/* LCD的画笔颜色和背景色 */
uint32_t g_point_color = RED; /* 画笔颜色 */
uint32_t g_back_color = 0XFFFFFFFF; /* 背景色 */
/* 管理LCD重要参数 */
_lcd_dev lcddev;
#define LCD_FRAME_BUFFER ((uint32_t)0xC0000000)
#define BUFFER_OFFSET ((uint32_t)0x7F800)
//static font_struct *current_font;
static uint16_t current_textcolor = 0x0000;
static uint16_t current_backcolor = 0xFFFF;
static uint32_t current_framebuffer = LCD_FRAME_BUFFER;
static uint32_t current_layer = LCD_LAYER_BACKGROUND;
static void lcd_char_draw(uint16_t xpos, uint16_t ypos, const uint16_t *c);
static void lcd_vertical_char_draw(uint16_t xpos, uint16_t ypos, const uint16_t *c);
static void pixel_set(int16_t x, int16_t y);
#define HORIZONTAL_SYNCHRONOUS_PULSE 41
#define HORIZONTAL_BACK_PORCH 2
#define ACTIVE_WIDTH 480
#define HORIZONTAL_FRONT_PORCH 2
#define VERTICAL_SYNCHRONOUS_PULSE 10
#define VERTICAL_BACK_PORCH 2
#define ACTIVE_HEIGHT 272
#define VERTICAL_FRONT_PORCH 2
/*!
\brief enable the LCD layer0 or layer1
\param[in] layer: LCD layer
\arg LCD_LAYER_BACKGROUND
\arg LCD_LAYER_FOREGROUND
\param[out] none
\retval none
*/
void lcd_layer_enable(uint32_t layer)
{
if(LCD_LAYER_BACKGROUND == layer){
tli_layer_enable(LAYER0);
}else if(LCD_LAYER_FOREGROUND == layer){
tli_layer_enable(LAYER1);
}
tli_enable();
}
/*!
\brief set the LCD layer
\param[in] layer: LCD layer
\arg LCD_LAYER_BACKGROUND
\arg LCD_LAYER_FOREGROUND
\param[out] none
\retval none
*/
void lcd_layer_set(uint32_t layer)
{
if(LCD_LAYER_BACKGROUND == layer){
current_framebuffer = LCD_FRAME_BUFFER;
current_layer = LCD_LAYER_BACKGROUND;
}else{
current_framebuffer = LCD_FRAME_BUFFER + BUFFER_OFFSET;
current_layer = LCD_LAYER_FOREGROUND;
}
}
/*!
\brief set the transparency of LCD
\param[in] trans: transparency of LCD, from 0 to 255
\param[out] none
\retval none
*/
void lcd_transparency_set(uint8_t trans)
{
if (LCD_LAYER_BACKGROUND == current_layer){
TLI_LXSA(LAYER0) &= ~(TLI_LXSA_SA);
TLI_LXSA(LAYER0) = trans;
}else{
TLI_LXSA(LAYER1) &= ~(TLI_LXSA_SA);
TLI_LXSA(LAYER1) = trans;
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
/*!
\brief initialize TLI layer0 or layer1
\param[in] layer: LCD layer
\arg LCD_LAYER_BACKGROUND
\arg LCD_LAYER_FOREGROUND
\param[in] width: width of the window
\param[in] height: height of the window
\param[out] none
\retval none
*/
void lcd_layer_init(uint32_t layer, uint32_t width, uint32_t height)
{
tli_layer_parameter_struct tli_layer_init_struct;
if(LCD_LAYER_BACKGROUND == layer){
/* TLI layer0 configuration */
tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
tli_layer_init_struct.layer_window_rightpos = (width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
tli_layer_init_struct.layer_window_bottompos = (height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
tli_layer_init_struct.layer_sa = 0xFF;
tli_layer_init_struct.layer_default_blue = 0xFF;
tli_layer_init_struct.layer_default_green = 0xFF;
tli_layer_init_struct.layer_default_red = 0xFF;
tli_layer_init_struct.layer_default_alpha = 0xFF;
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
tli_layer_init_struct.layer_frame_bufaddr = LCD_FRAME_BUFFER;
tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);
tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);
tli_layer_init_struct.layer_frame_total_line_number = height;
tli_layer_init(LAYER0, &tli_layer_init_struct);
}else if(LCD_LAYER_FOREGROUND == layer){
/* TLI layer1 configuration */
tli_layer_init_struct.layer_window_leftpos = (HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
tli_layer_init_struct.layer_window_rightpos = (width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_window_toppos = (VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
tli_layer_init_struct.layer_window_bottompos = (height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
tli_layer_init_struct.layer_sa = 0xFF;
tli_layer_init_struct.layer_default_blue = 0xFF;
tli_layer_init_struct.layer_default_green = 0xFF;
tli_layer_init_struct.layer_default_red = 0xFF;
tli_layer_init_struct.layer_default_alpha = 0x0;
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
tli_layer_init_struct.layer_frame_bufaddr = LCD_FRAME_BUFFER + BUFFER_OFFSET;
tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);
tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);
tli_layer_init_struct.layer_frame_total_line_number = height;
tli_layer_init(LAYER1, &tli_layer_init_struct);
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
// lcd_font_set(&LCD_DEFAULT_FONT);
}
/**
* @brief 初始化LCD
* @note 该初始化函数可以初始化各种型号的LCD(详见本.c文件最前面的描述)
*
* @param 无
* @retval 无
*/
void lcd_init(void)
{
tli_parameter_struct tli_init_struct;
lcddev.width = 480;
lcddev.height = 272;
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_GPIOH);
rcu_periph_clock_enable(RCU_GPIOG);
/* configure HSYNC(PE15), VSYNC(PA7), PCLK(PG7) */
gpio_af_set(GPIOE, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7);
gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
/* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PA5), LCD_R3(PH9),LCD_R2(PH8),
LCD_R1(PH3), LCD_R0(PH2) */
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_5);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_2);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_2);
/* configure LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PC1), LCD_G4(PH15), LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PB0), LCD_G0(PB1) */
gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_1);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_14);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_13);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_0);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_1);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_0);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_1);
/* configure LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PB5), LCD_B4(PC11), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PG14) */
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOB, GPIO_AF_3, GPIO_PIN_5);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_10);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_14);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_14);
/* configure LCD_DE(PF10) */
gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10);
/* LCD PWM BackLight(PG13) */
gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_13);
gpio_bit_set(GPIOG, GPIO_PIN_13);
rcu_periph_clock_enable(RCU_TLI);
/* configure PLL2 to generate TLI clock 25MHz/25*192/3 = 64MHz*/
rcu_pll_input_output_clock_range_config(IDX_PLL1,RCU_PLL1RNG_1M_2M,RCU_PLL1VCO_192M_836M);
if(ERROR == rcu_pll2_config(25,192,3,3,3)){
while(1){
}
}
rcu_pll_clock_output_enable(RCU_PLL2R);
rcu_tli_clock_div_config(RCU_PLL2R_DIV8);
rcu_osci_on(RCU_PLL2_CK);
if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)){
while(1){
}
}
/* configure the EXMC access mode */
exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);
/* TLI initialization */
tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_INVERTEDTLI;
/* LCD display timing configuration */
tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1;
tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1;
tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1;
tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1;
tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1;
tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1;
/* LCD background color configure*/
tli_init_struct.backcolor_red = 0xFF;
tli_init_struct.backcolor_green = 0xFF;
tli_init_struct.backcolor_blue = 0xFF;
tli_init(&tli_init_struct);
lcd_layer_init(LCD_LAYER_BACKGROUND, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
lcd_layer_init(LCD_LAYER_FOREGROUND, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
tli_layer_enable(LAYER0);
tli_layer_enable(LAYER1);
tli_enable();
lcd_layer_set(LCD_LAYER_BACKGROUND);
lcd_transparency_set(255);
lcd_clear(LCD_COLOR_WHITE);
lcd_layer_set(LCD_LAYER_FOREGROUND);
lcd_transparency_set(0);
lcd_clear(LCD_COLOR_WHITE);
lcd_layer_set(LCD_LAYER_BACKGROUND);
lcd_clear(WHITE); /* 清屏 */
}
/*!
\brief configure the packeted pixel format
\param[in] pixel_format: pixel format
\arg LAYER_PPF_ARGB8888
\arg LAYER_PPF_RGB888
\arg LAYER_PPF_RGB565
\arg LAYER_PPF_ARGB1555
\arg LAYER_PPF_ARGB4444
\arg LAYER_PPF_L8
\arg LAYER_PPF_AL44
\arg LAYER_PPF_AL88
\param[out] none
\retval none
*/
void lcd_pixel_format_config(uint32_t pixel_format)
{
if(LCD_LAYER_BACKGROUND == current_layer){
TLI_LXPPF(LAYER0) &= ~(TLI_LXPPF_PPF);
TLI_LXPPF(LAYER0) = pixel_format;
}else{
TLI_LXPPF(LAYER1) &= ~(TLI_LXPPF_PPF);
TLI_LXPPF(LAYER1) = pixel_format;
}
}
/*!
\brief configure the frame buffer base address
\param[in] address: frame buffer base address
\param[out] none
\retval none
*/
void lcd_address_config(uint32_t address)
{
if (LCD_LAYER_BACKGROUND == current_layer){
TLI_LXFBADDR(LAYER0) &= ~(TLI_LXFBADDR_FBADD);
TLI_LXFBADDR(LAYER0) = address;
}else{
TLI_LXFBADDR(LAYER1) &= ~(TLI_LXFBADDR_FBADD);
TLI_LXFBADDR(LAYER1) = address;
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
/**
* @brief 读取某个点的颜色值
* @param x,y:坐标
* @retval 此点的颜色(32位颜色,方便兼容TLI)
*/
uint16_t lcd_read_point(uint16_t x, uint16_t y)
{
return *(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*y) + x));
}
/**
* @brief LCD开启显示
* @param 无
* @retval 无
*/
void lcd_display_on(void)
{
tli_enable(); /* 使能TLI */
}
/**
* @brief LCD关闭显示
* @param 无
* @retval 无
*/
void lcd_display_off(void)
{
tli_disable(); /* 禁能TLI */
}
/**
* @brief 画点
* @param x,y: 坐标
* @param color: 点的颜色(32位颜色,方便兼容TLI)
* @retval 无
*/
void lcd_draw_point(uint16_t x, uint16_t y, uint32_t color)
{
*(__IO uint16_t*)(current_framebuffer + 2*((LCD_PIXEL_WIDTH*y) + x)) = color;
}
/**
* @brief 设置LCD显示方向
* @param dir:0,竖屏; 1,横屏
* @retval 无
*/
void lcd_display_dir(uint8_t dir)
{
}
/*!
\brief clear the LCD with specified color
\param[in] color: LCD color
\arg LCD_COLOR_WHITE
\arg LCD_COLOR_BLACK
\arg LCD_COLOR_GREY
\arg LCD_COLOR_BLUE
\arg LCD_COLOR_BLUE2
\arg LCD_COLOR_RED
\arg LCD_COLOR_MAGENTA
\arg LCD_COLOR_GREEN
\arg LCD_COLOR_CYAN
\arg LCD_COLOR_YELLOW
\param[out] none
\retval none
*/
void lcd_clear(uint16_t color)
{
uint32_t index = 0;
for (index = 0x00; index < BUFFER_OFFSET; index++){
*(__IO uint16_t*)(current_framebuffer + (2*index)) = color;
}
}
/**
* @brief 在指定区域内填充单个颜色
* @param (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex - sx + 1) * (ey - sy + 1)
* @param color: 要填充的颜色(32位颜色,方便兼容TLI)
* @retval 无
*/
void lcd_fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color)
{
uint16_t i, j;
uint16_t xlen = 0;
for (i = sy; i <= ey; i++)
{
for (j = sx; j < ex; j++)
{
lcd_draw_point(j, i, color);
}
}
}
/**
* @brief 在指定区域内填充指定颜色块
* @param (sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex - sx + 1) * (ey - sy + 1)
* @param color: 要填充的颜色数组首地址
* @retval 无
*/
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++)
{
for (j = 0; j < width; j++)
{
lcd_draw_point(sx+j, sy+i, color[i * width + j]);
}
}
}
/**
* @brief 画线
* @param x1,y1: 起点坐标
* @param x2,y2: 终点坐标
* @param color: 线的颜色
* @retval 无
*/
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color)
{
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, row, col;
delta_x = x2 - x1; /* 计算坐标增量 */
delta_y = y2 - y1;
row = x1;
col = 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_draw_point(row, col, color); /* 画点 */
xerr += delta_x ;
yerr += delta_y ;
if (xerr > distance)
{
xerr -= distance;
row += incx;
}
if (yerr > distance)
{
yerr -= distance;
col += incy;
}
}
}
/**
* @brief 画水平线
* @param x,y : 起点坐标
* @param len : 线长度
* @param color: 矩形的颜色
* @retval 无
*/
void lcd_draw_hline(uint16_t x, uint16_t y, uint16_t len, uint32_t color)
{
if ((len == 0) || (x > lcddev.width) || (y > lcddev.height)) return;
lcd_fill(x, y, x + len - 1, y, color);
}
/**
* @brief 画矩形
* @param x1,y1: 起点坐标
* @param x2,y2: 终点坐标
* @param color: 矩形的颜色
* @retval 无
*/
void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint32_t color)
{
lcd_draw_line(x1, y1, x2, y1, color);
lcd_draw_line(x1, y1, x1, y2, color);
lcd_draw_line(x1, y2, x2, y2, color);
lcd_draw_line(x2, y1, x2, y2, color);
}
/**
* @brief 画圆
* @param x0,y0: 圆中心坐标
* @param r : 半径
* @param color: 圆的颜色
* @retval 无
*/
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint8_t r, uint32_t color)
{
int a, b;
int di;
a = 0;
b = r;
di = 3 - (r << 1); /* 判断下个点位置的标志 */
while (a <= b)
{
lcd_draw_point(x0 + a, y0 - b, color); /* 5 */
lcd_draw_point(x0 + b, y0 - a, color); /* 0 */
lcd_draw_point(x0 + b, y0 + a, color); /* 4 */
lcd_draw_point(x0 + a, y0 + b, color); /* 6 */
lcd_draw_point(x0 - a, y0 + b, color); /* 1 */
lcd_draw_point(x0 - b, y0 + a, color);
lcd_draw_point(x0 - a, y0 - b, color); /* 2 */
lcd_draw_point(x0 - b, y0 - a, color); /* 7 */
a++;
/* 使用Bresenham算法画圆 */
if (di < 0)
{
di += 4 * a + 6;
}
else
{
di += 10 + 4 * (a - b);
b--;
}
}
}
/**
* @brief 填充实心圆
* @param x,y : 圆中心坐标
* @param r : 半径
* @param color: 圆的颜色
* @retval 无
*/
void lcd_fill_circle(uint16_t x, uint16_t y, uint16_t r, uint32_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 xr = r;
lcd_draw_hline(x - r, y, 2 * r, color);
for (i = 1; i <= imax; i++)
{
if ((i * i + xr * xr) > sqmax)
{
/* draw lines from outside */
if (xr > imax)
{
lcd_draw_hline (x - i + 1, y + xr, 2 * (i - 1), color);
lcd_draw_hline (x - i + 1, y - xr, 2 * (i - 1), color);
}
xr--;
}
/* draw lines from inside (center) */
lcd_draw_hline(x - xr, y + i, 2 * xr, color);
lcd_draw_hline(x - xr, y - i, 2 * xr, color);
}
}
/**
* @brief 在指定位置显示一个字符
* @param x,y : 坐标
* @param chr : 要显示的字符:' '--->'~'
* @param size : 字体大小 12/16/24/32
* @param mode : 叠加方式(1); 非叠加方式(0);
* @param color : 字符的颜色;
* @retval 无
*/
void lcd_show_char(uint16_t x, uint16_t y, char chr, uint8_t size, uint8_t mode, uint32_t color)
{
uint8_t temp, t1, t;
uint16_t y0 = y;
uint8_t csize = 0;
uint8_t *pfont = 0;
csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); /* 得到字体一个字符对应点阵集所占的字节数 */
chr = chr - ' '; /* 得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库) */
switch (size)
{
case 12:
pfont = (uint8_t *)asc2_1206[chr]; /* 调用1206字体 */
break;
case 16:
pfont = (uint8_t *)asc2_1608[chr]; /* 调用1608字体 */
break;
case 24:
pfont = (uint8_t *)asc2_2412[chr]; /* 调用2412字体 */
break;
case 32:
pfont = (uint8_t *)asc2_3216[chr]; /* 调用3216字体 */
break;
default:
return ;
}
for (t = 0; t < csize; t++)
{
temp = pfont[t]; /* 获取字符的点阵数据 */
for (t1 = 0; t1 < 8; t1++) /* 一个字节8个点 */
{
if (temp & 0x80) /* 有效点,需要显示 */
{
lcd_draw_point(x, y, color); /* 画点出来,要显示这个点 */
}
else if (mode == 0) /* 无效点并且选择非叠加方式 */
{
lcd_draw_point(x, y, g_back_color); /* 画背景色,相当于这个点不显示(注意背景色由全局变量控制) */
}
temp <<= 1; /* 移位, 以便获取下一个位的状态 */
y++;
if (y >= lcddev.height) return; /* 超区域了 */
if ((y - y0) == size) /* 显示完一列了? */
{
y = y0; /* y坐标复位 */
x++; /* x坐标递增 */
if (x >= lcddev.width) return; /* x坐标超区域了 */
break;
}
}
}
}
/**
* @brief 平方函数, m^n
* @param m: 底数
* @param n: 指数
* @retval m的n次方
*/
static uint32_t lcd_pow(uint8_t m, uint8_t n)
{
uint32_t result = 1;
while (n--) result *= m;
return result;
}
/**
* @brief 显示len个数字(高位为0则不显示)
* @param x,y : 起始坐标
* @param num : 数值(0 ~ 2^32)
* @param len : 显示数字的位数
* @param size : 选择字体 12/16/24/32
* @param color : 数字的颜色;
* @retval 无
*/
void lcd_show_num(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint32_t color)
{
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_show_char(x + (size / 2) * t, y, ' ', size, 0, color); /* 显示空格,占位 */
continue; /* 继续下个一位 */
}
else
{
enshow = 1; /* 使能显示 */
}
}
lcd_show_char(x + (size / 2) * t, y, temp + '0', size, 0, color); /* 显示字符 */
}
}
/**
* @brief 扩展显示len个数字(高位是0也显示)
* @param x,y : 起始坐标
* @param num : 数值(0 ~ 2^32)
* @param len : 显示数字的位数
* @param size : 选择字体 12/16/24/32
* @param mode : 显示模式
* [7]:0,不填充;1,填充0.
* [6:1]:保留
* [0]:0,非叠加显示;1,叠加显示.
* @param color : 数字的颜色;
* @retval 无
*/
void lcd_show_xnum(uint16_t x, uint16_t y, uint32_t num, uint8_t len, uint8_t size, uint8_t mode, uint32_t color)
{
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) /* 高位需要填充0 */
{
lcd_show_char(x + (size / 2) * t, y, '0', size, mode & 0X01, color); /* 用0占位 */
}
else
{
lcd_show_char(x + (size / 2) * t, y, ' ', size, mode & 0X01, color); /* 用空格占位 */
}
continue;
}
else
{
enshow = 1; /* 使能显示 */
}
}
lcd_show_char(x + (size / 2) * t, y, temp + '0', size, mode & 0X01, color);
}
}
/**
* @brief 显示字符串
* @param x,y : 起始坐标
* @param width,height: 区域大小
* @param size : 选择字体 12/16/24/32
* @param p : 字符串首地址
* @param color : 字符串的颜色;
* @retval 无
*/
void lcd_show_string(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t size, char *p, uint32_t color)
{
uint8_t x0 = x;
width += x;
height += y;
while ((*p <= '~') && (*p >= ' ')) /* 判断是不是非法字符! */
{
if (x >= width)
{
x = x0;
y += size;
}
if (y >= height) break; /* 退出 */
lcd_show_char(x, y, *p, size, 0, color);
x += size / 2;
p++;
}
}
#include "gd32h7xx.h"
#include "systick.h"
#include <stdio.h>
#include "gd32h759i_eval.h"
#include "gd32h759i_lcd_eval.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/TIMER/timer.h"
#include "./BSP/24CXX/24cxx.h"
#include "./BSP/LCD/lcd.h"
const uint8_t g_text_buf[] = {"gd32 IIC TEST"}; /* 要写入到 24c02 的字符串数组 */
#define TEXT_SIZE sizeof(g_text_buf) /* TEXT 字符串长度 */
/*!
\brief toggle the led every 500ms
\param[in] none
\param[out] none
\retval none
*/
void led_spark(void)
{
static __IO uint32_t timingdelaylocal = 0U;
if(timingdelaylocal) {
if(timingdelaylocal < 500U) {
gd_eval_led_on(LED1);
} else {
gd_eval_led_off(LED1);
}
timingdelaylocal--;
} else {
timingdelaylocal = 1000U;
}
}
/*!
\brief enable the CPU cache
\param[in] none
\param[out] none
\retval none
*/
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
uint8_t x = 0;
uint8_t datatemp[TEXT_SIZE];
/* enable the CPU cache */
cache_enable();
/* configure systick */
//systick_config();
delay_init(600);
/* initilize the LEDs, USART and key */
gd_eval_led_init(LED1);
gd_eval_led_init(LED2);
gd_eval_com_init(EVAL_COM);
gd_eval_key_init(KEY_WAKEUP, KEY_MODE_GPIO);
gd_eval_key_init(KEY_TAMPER, KEY_MODE_GPIO);
at24cxx_init();
timerx_int_init(10 - 1, 30000 - 1);
printf("\r\nCK_SYS is %d", rcu_clock_freq_get(CK_SYS));
lcd_init();
while (at24cxx_check())
{
gd_eval_led_on(LED1);
delay_ms(500);lcd_init();
gd_eval_led_off(LED1);
delay_ms(500);
}
while(1) {
if(RESET == gd_eval_key_scan(KEY_WAKEUP))
{
printf("\r\nCK_SYS is 1");
at24cxx_write(0, (uint8_t *)g_text_buf, TEXT_SIZE);
}
if(RESET == gd_eval_key_scan(KEY_TAMPER))
{
printf("\r\nCK_SYS is 2");
at24cxx_read(0, datatemp, TEXT_SIZE);
printf("The Data Readed Is: %s\r\n",datatemp);
}
switch (x)
{
case 0: lcd_clear(WHITE); break;
case 1: lcd_clear(BLACK); break;
case 2: lcd_clear(BLUE); break;
case 3: lcd_clear(RED); break;
case 4: lcd_clear(MAGENTA); break;
case 5: lcd_clear(GREEN); break;
case 6: lcd_clear(CYAN); break;
case 7: lcd_clear(YELLOW); break;
case 8: lcd_clear(BRRED); break;
case 9: lcd_clear(GRAY); break;
case 10: lcd_clear(LGRAY); break;
case 11: lcd_clear(BROWN); break;
}
lcd_show_string(10, 40, 240, 32, 32, "STM32", RED);
lcd_show_string(10, 80, 240, 24, 24, "TFTLCD TEST", RED);
lcd_show_string(10, 110, 240, 16, 16, "ATOM@ALIENTEK", RED);
x++;
if (x == 12)
x = 0;
delay_ms(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM, (uint8_t)ch);
while(RESET == usart_flag_get(EVAL_COM, USART_FLAG_TBE));
return ch;
}
实验现象
|