本帖最后由 sujingliang 于 2024-12-18 19:50 编辑
记录一下用G32A1465移植LVGL的过程。
G32A1465的SRAM为128KB,地址被分成了2部分:
每部分大约60多kb,从资源上看可以运行下LVGL。注意要勾选IRAM2。
1、复制LVGL必要文件到Middlewares中
从硬盘找到不知道从什么地方下载的LVGL,将下面几个文件和目录拷贝到SDK下的Middlewares中。
2、将原文件和头文件加入工程
按照目录名建立如下工程文件夹,将对应目录及子目录下的*.c文件全部都加进来,
这一步工作量很大。
头文件也加上
3、lv_port_disp_templ.c
位于:Middlewares/lvgl/examples/porting
加入LCD初始化函数:
static void disp_init(void)
{
/*You code here*/
LCD_Init();
}
配置2个缓存:
void lv_port_disp_init(void)
{
static lv_disp_draw_buf_t draw_buf_dsc_2;
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 32]; /*A buffer for 10 rows*/
static lv_color_t buf_2_2[MY_DISP_HOR_RES * 32]; /*An other buffer for 10 rows*/
lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 32); /*Initialize the display buffer*/
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_2;
disp_flush调用区域填充函数:
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
uint16_t *p=(uint16_t*)color_p;
uint16_t c=*p;
if(disp_flush_enabled) {
LCD_Fill1(area->x1,area->y1,area->x2,area->y2,(uint16_t*)color_p);
}
lv_disp_flush_ready(disp_drv);
}
区域填充函数
void LCD_Fill1(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t* color)
{
uint32_t i,j;
uint16_t width=ex-sx+1; //得到填充的宽度
uint16_t height=ey-sy+1; //高度
int32_t num= (width) * (height) * 2;
LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口
LCD_CS_CLR;
LCD_RS_SET;
SPI_WriteByte((uint8_t*)color,num);
}
SPI连续写数据函数:void SPI_WriteByte(uint8_t *spiTxBuf,uint16_t len)
{
LPSPI_MasterTransferBlocking(LPSPI_1, spiTxBuf, NULL, len, SPI_TIMEOUT);
}
4、配置一个定时器
timer config:
LPITMR_USER_CHANNEL_CONFIG_T g_lpitmrChannelConfig =
{
.timerMode = LPITMR_PERIODIC_COUNTER,
.periodUnits = LPIT_PERIOD_UNITS_MICROSECONDS,
.period = 799U,
.triggerSrc = LPITMR_TRIG_SRC_INTERNAL,
.triggerSelect = 0U,
.reloadOnTriggerEn = true,
.stopOnInterruptEn = true,
.startOnTriggerEn = true,
.channelChainEn = false,
初始化定时器,
void LPITMR_Initialize(void)
{
LPITMR_DeInit(LPITMR_INSTANCE);
LPITMR_Init(LPITMR_INSTANCE, &g_lpitmrConfig);
LPITMR_ChannelInit(LPITMR_INSTANCE, LPITMR_CHANNEL1, &g_lpitmrChannelConfig);
LPITMR_StartTimerChannels(LPITMR_INSTANCE, LPITMR_CHANNEL1);
INT_SYS_InstallHandler(LPITMR_Ch1_IRQn, LPITMR_Irq, NULL);
INT_SYS_EnableIRQ(LPITMR_Ch1_IRQn);
}
定时器中断处理,调用lv_tick_inc(1);
void LPITMR_Irq(void)
{
if(LPITMR_ReadInterruptFlagTimerChannels(LPITMR_INSTANCE, LPITMR_CHANNEL1_MASK))
{
/* Clear LPITMR channel1 interrupt flagure */
LPITMR_ClearInterruptFlagTimerChannels(LPITMR_INSTANCE, LPITMR_CHANNEL1_MASK);
lv_tick_inc(1);
}
}
5、main文件
#include "lv_conf.h"
#include "lvgl.h"
#include "lv_port_disp_template.h"
lv_init();
lv_port_disp_init();
LPITMR_Initialize(); //定时器初始化
lv_demo_widgets(); //调用demo
6、lv_conf.h
#define LV_COLOR_16_SWAP 1
为了适应LCD的配置,使能颜色交换
#define LV_MEM_SIZE (40U * 1024U)
LV_MEM_SIZE 配置大一点,widgets DEMO至少需要38KB
#define LV_MEM_ADR 0x1FFF1000
配置lv_mem地址从0x1FFF1000,这是LV管理内存的起始地址。
选这个地址是因为IRAM2起始0x1FFF0000,空出前面一部分给系统,所以选了0x1FFF1000,这样后面大约还有50多KB。
内存分配可以参见sct文件:
#define LV_BUILD_EXAMPLES 1
使能DEMO
#define LV_USE_DEMO_WIDGETS 1
运行WIDGETS demo
7、实验效果
|