目录
概述
1 硬件介绍
1.1 ST7796-LCD
1.2 MCU IO与LCD PIN对应关系
1.3 MCU IO与Touch PIN对应关系
2 N32G45x移植 LVGL
2.1 移植步骤
2.2 注意点
2.2.1 UI刷新函数
2.2.2 主函数中调用
3 LVGL的应用Demo
3.1 功能描述
3.2 代码实现
3.3 测试
N32G45XVL-STB之lvgl的应用实例
概述
本文主要介绍在N32G45XVL上移植lvgl应该注意的问题,其主要包括驱动程序接口的实现,UI刷新速度的优化。还编写一个简单的案例用以测试LVGL的UI显示和触摸功能的响应速度。相比与Contex-M3内核来说,基于Contex-M4内核的N32G45XVL在UI刷新速度上当然快了好多,当在用户体验上,任有值得优化的地方。
1 硬件介绍
1.1 ST7796-LCD
LCD的PIN引脚功能介绍
序号 | 模块引脚 | 引脚说明 |
1 | VCC | 屏电源正 |
2 | GND | 屏电源地 |
3 | LCD_CS | 液晶屏片选控制信号,低电平有效 |
4 | LCD_RST | 液晶屏复位控制信号,低电平复位 |
5 | LCD_RS | 液晶屏命令/数据选择控制信号 高电平:数据,低电平:命令 |
6 | SDI(MOSI) | SPI总线写数据信号(SD卡和液晶屏共用) |
7 | SCK | SPI总线时钟信号(SD卡和液晶屏共用) |
8 | LED | 液晶屏背光控制信号(如需要控制,请接引脚,如不需要控制,可以不接) |
9 | SDO(MISO) | SPI总线读数据信号(SD卡和液晶屏共用) |
10 | CTP_SCL | 电容触摸屏IIC总线时钟信号(无触摸屏的模块不需连接) |
11 | CTP_RST | 电容触摸屏复位控制信号,低电平复位(无触摸屏的模块不需连接) |
12 | CTP_SDA | 电容触摸屏IIC总线数据信号(无触摸屏的模块不需连接) |
13 | CTP_INT | 电容触摸屏IIC总线触摸中断信号,产生触摸时,输入低电平到主控(无触摸屏的模块不需连接) |
14 | SD_CS | SD卡片选控制信号,低电平有效(不使用SD卡功能,可不接) |
实体LCD Port对应关系如下图所示
1.2 MCU IO与LCD PIN对应关系
N32G45X PIN引脚 | LCD PIN引脚 |
---|---|
PA7-MOSI | MOSI |
PA6-MISO | MISO |
PA5-SCK | SCK |
PD4 | CS |
PD5 | RST |
PD6 | RS |
1.3 MCU IO与Touch PIN对应关系
N32G45X PIN引脚 | touch PIN引脚 |
---|---|
PB6 | I2C-SCK |
PB7 | I2C-SDA |
PB10 | INIT |
PB9 | RST |
2 N32G45x移植 LVGL
2.1 移植步骤
关于LVGL的移植参考如下文档:
N32G45XVL-STB之移植LVGL(lvgl-8.2.0)-CSDN博客
2.2 注意点
2.2.1 UI刷新函数
笔者使用SPI接口类型的LCD,相比较有图形接口的LCD来说,其速度刷新速度函数比较慢的。为了尽可能加快UI的刷新速度,笔者做了如下优化:
1)重新写数据函数
代码26行: 计算刷新点个数
代码30行:设置窗口
代码31行:设置传递数据模式
代码34~39行:SPI模式写数据
源代码
static void lcd_draw_fast_rgb_color(int16_t sx, int16_t sy,int16_t ex, int16_t ey, uint16_t *color)
{uint16_t w = ex-sx+1;uint16_t h = ey-sy+1;uint32_t draw_size = w * h;uint32_t i;uint16_t tempcolor;LCD_SetWindows(sx, sy, ex, ey);LCD_RS_SET;LCD_CS_CLR;// set point value for( i = 0; i < draw_size; i++){tempcolor = color[i];SPI_WriteByte(tempcolor>>8);SPI_WriteByte(tempcolor);}LCD_CS_SET;
}
2.2.2 主函数中调用
在main函数中需要调用两个函数:
1)刷新UI函数: lv_task_handler()
2)触摸监测tick函数: lv_tick_inc(1)
源代码:
/*** @brief Main program*/
int main(void)
{uint32_t time_count;Board_Init();ui_init();usr_touchInit();LCD_DrvInit();lvgl_test();while (1){// refresh tje UI interval: 300 ms time_count = get_timer1_countMs();if( (time_count % 50) == 0){}if( (time_count % 5) == 0){lv_tick_inc(1);}lv_task_handler();}
}
3 LVGL的应用Demo
3.1 功能描述
1)实现3个Button
2)通过Button改变数值
3.2 代码实现
#include "lv_mainstart.h"
#include "lvgl.h"
#include <stdio.h>static const lv_font_t* font; /* 定义字体 */static lv_obj_t *label_speed; /* 速度提示文本 */
static lv_obj_t *btn_speed_up; /* 加速按钮 */
static lv_obj_t *btn_speed_down; /* 减速按钮 */
static lv_obj_t *btn_stop; /* 急停按钮 */static int32_t speed_val = 0; /* 速度值 *//* 获取当前活动屏幕的宽高 */
#define scr_act_width() lv_obj_get_width(lv_scr_act())
#define scr_act_height() lv_obj_get_height(lv_scr_act())/*** @brief 按钮回调* @param *e :事件相关参数的集合,它包含了该事件的所有数据* @return 无*/
static void btn_event_cb(lv_event_t * e)
{lv_obj_t *target = lv_event_get_target(e); /* 获取触发源 */if(target == btn_speed_up) /* 加速按钮 */{speed_val += 30;}else if(target == btn_speed_down) /* 减速按钮 */{speed_val -= 30;}else if(target == btn_stop) /* 急停按钮 */{speed_val = 0;}lv_label_set_text_fmt(label_speed, "Speed : %d RPM", speed_val); /* 更新速度值 */
}/*** @brief 速度值提示标签* @param 无* @return 无*/
static void lv_example_label(void)
{/* 根据活动屏幕宽度选择字体 */if (scr_act_width() <= 320){font = &lv_font_montserrat_20;}else if (scr_act_width() <= 480){font = &lv_font_montserrat_20;}else{font = &lv_font_montserrat_20;}label_speed = lv_label_create(lv_scr_act()); /* 创建速度显示标签 */lv_obj_set_style_text_font(label_speed, font, LV_PART_MAIN); /* 设置字体 */lv_label_set_text(label_speed, "Speed : 0 RPM"); /* 设置文本 */lv_obj_align(label_speed, LV_ALIGN_CENTER, 0, -scr_act_height() / 3); /* 设置标签位置 */
}
/*** @brief 加速按钮* @param 无* @return 无*/
static void lv_example_btn_up(void)
{font = &lv_font_montserrat_18;btn_speed_up = lv_btn_create(lv_scr_act()); /* 创建加速按钮 */lv_obj_set_size(btn_speed_up, scr_act_width() / 4, scr_act_height() / 6); /* 设置按钮大小 */lv_obj_align(btn_speed_up, LV_ALIGN_CENTER, -scr_act_width() / 3, 0); /* 设置按钮位置 */lv_obj_add_event_cb(btn_speed_up, btn_event_cb, LV_EVENT_CLICKED, NULL); /* 设置按钮事件 */lv_obj_t* label = lv_label_create(btn_speed_up); /* 创建加速按钮标签 */lv_obj_set_style_text_font(label, font, LV_PART_MAIN); /* 设置字体 */lv_label_set_text(label, "Speed +"); /* 设置标签文本 */lv_obj_set_align(label,LV_ALIGN_CENTER); /* 设置标签位置 */
}/*** @brief 减速按钮* @param 无* @return 无*/
static void lv_example_btn_down(void)
{font = &lv_font_montserrat_18;btn_speed_down = lv_btn_create(lv_scr_act()); /* 创建加速按钮 */lv_obj_set_size(btn_speed_down, scr_act_width() / 4, scr_act_height() / 6); /* 设置按钮大小 */lv_obj_align(btn_speed_down, LV_ALIGN_CENTER, 0, 0); /* 设置按钮位置 */lv_obj_add_event_cb(btn_speed_down, btn_event_cb, LV_EVENT_CLICKED, NULL); /* 设置按钮事件 */lv_obj_t* label = lv_label_create(btn_speed_down); /* 创建减速按钮标签 */lv_obj_set_style_text_font(label, font, LV_PART_MAIN); /* 设置字体 */lv_label_set_text(label, "Speed -"); /* 设置标签文本 */lv_obj_set_align(label,LV_ALIGN_CENTER); /* 设置标签位置 */
}/*** @brief 急停按钮* @param 无* @return 无*/
static void lv_example_btn_stop(void)
{font = &lv_font_montserrat_18;btn_stop = lv_btn_create(lv_scr_act()); /* 创建急停按钮 */lv_obj_set_size(btn_stop, scr_act_width() / 4, scr_act_height() / 6); /* 设置按钮大小 */lv_obj_align(btn_stop, LV_ALIGN_CENTER, scr_act_width() / 3, 0); /* 设置按钮位置 */lv_obj_set_style_bg_color(btn_stop, lv_color_hex(0xef5f60), LV_STATE_DEFAULT); /* 设置按钮背景颜色(默认) */lv_obj_set_style_bg_color(btn_stop, lv_color_hex(0xff0000), LV_STATE_PRESSED); /* 设置按钮背景颜色(按下) */lv_obj_add_event_cb(btn_stop, btn_event_cb, LV_EVENT_CLICKED, NULL); /* 设置按钮事件 */lv_obj_t* label = lv_label_create(btn_stop); /* 创建急停按钮标签 */lv_obj_set_style_text_font(label, font, LV_PART_MAIN); /* 设置字体 */lv_label_set_text(label, "Stop"); /* 设置标签文本 */lv_obj_set_align(label,LV_ALIGN_CENTER); /* 设置标签位置 */
}/*** @brief LVGL演示* @param 无* @return 无*/
void lv_mainstart(void)
{lv_example_label(); /* 速度提示标签 */lv_example_btn_up(); /* 加速按钮 */lv_example_btn_down(); /* 减速按钮 */lv_example_btn_stop(); /* 急停按钮 */
}/* End of this file */
3.3 测试
点击按键改变数据