STM32移植LVGL:一路踩坑之旅

这篇文章我主要讲解一下我在移植LVGL时所遇到的一些坑以及解决方法。LVGL的移植过程可以参考我前面的文章,http://t.csdn.cn/QSVOO。

第一个

问题:
在lvgl8.1以前的版本可能会出现MY_DISP_HOR_RES 和 MY_DISP_VER_RES 未定义的报错。
解决方法:
lvgl.conf.h 头文件里定义即可
lvgl8.1以后的版本不需要我们自己添加了,它已经在lv_port.disp.c定义好了我们只需要修改成我们自己的屏幕参数。

第二个

问题:
报错提示内存不足
解决方法:
1、修改lvgl可用内存的大小,在lv_conf.h中修改LV_MEM_SIZE的值,修改后的样子(原来是128U*1024U)
2、增大STM32的空间,在stm32f407xx.s(我这里用的是STM32F407的板子)文件中修改,修改后的样子:

第三个

问题:
移植好后编译下载发现屏幕显示是乱的,这是lv_port_disp.c里的disp_flush函数修改错误导致的。
我原来用正点原子的F103的精英板移植用这个方法显示是正常的,我现在换了其他板子和屏幕也用同样的方法结果就显示不正常了。

这里在disp_flush函数里添加的函数是填充指定颜色函数LCD_Draw_Picture,函数原型如下:

/****************************************************************************
* 名    称: void LCD_Draw_Picture(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
* 功    能:在指定区域内画入图片
* 入口参数:(sx,sy),(ex,ey):填充矩形对角坐标
            color:要填充的图片像素颜色数组
* 返回参数:无
* 说    明:区域大小为:(ex-sx+1)*(ey-sy+1)  
****************************************************************************/
void LCD_Draw_Picture(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
{  
	u16 height,width;
	u16 i,j;
	width=ex-sx+1; 			    //得到图片的宽度
	height=ey-sy+1;			    //得到图片的高度
 	for(i=0;i<height;i++)
	{
 		LCD_SetCursor(sx,sy+i); //设置光标位置 
		LCD_WriteGRAM();        //开始写入GRAM
		for(j=0;j<width;j++)
		   LCD_DATA=color[i*height+j];//写入颜色值
	}	  
}  

错误的显示效果。

解决方法
我当时在这里卡了好久,后来在百度上看到一位大佬的方法,他不是用的指定颜色填充函数而是用的颜色打点函数。于是我就想我用这个方法是否可行呢?一试,果然可以。修改过后的样子:
颜色打点函数原型如下:

/****************************************************************************
* 名    称: void LCD_Color_DrawPoint(u16 x,u16 y,u16 color)
* 功    能:在设置的坐标处画相应颜色(在该点写入自定义颜色)
* 入口参数:x:x坐标
            y:y坐标
            color 此点的颜色值
* 返回参数:无
* 说    明:color:写入此点的颜色值   GUI调用该函数
****************************************************************************/
void LCD_Color_DrawPoint(u16 x,u16 y,u16 color)
{	       
	 LCD_DrawPoint(x,y);
	 LCD_CMD=write_gramcmd; 
	 LCD_DATA=color;  
}	

编译下载。显示效果正常

添加触摸功能

lv_port_indev.c文件就是跟触摸有关的。在lv_port_indev.c文件里添加自己的触摸函数的头文件。在lv_port_indev.c文件中找到lv_port_indev_init函数,进行修改。这里只添加触摸功能,所以把其他功能屏蔽掉。
接在在下面找到touchpad_read函数进行修改 ,

static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static lv_coord_t last_x = 0;
    static lv_coord_t last_y = 0;

    /*Save the pressed coordinates and the state*/
//    if(touchpad_is_pressed()) {
//        touchpad_get_xy(&last_x, &last_y);
//        data->state = LV_INDEV_STATE_PR;
//    }
//    else {
//        data->state = LV_INDEV_STATE_REL;
//    }
	//上面注释的是原本的代码
		if(PEN==0)  //判断有按键按下,PEN在自己触摸函数头文件有定义,不同厂商提供的触摸函数不同,
				//如正点原子的,在这里就可以使用if(tp_dev.sta&TP_PRES_DOWN)
		{
			last_x = Xdown;   //按键按下抬起后的坐标,自己触摸函数头文件里定义的按键键值的存放变量
			last_y = Ydown;
			data->point.x = last_x;
			data->point.y = last_y;
			data->state = LV_INDEV_STATE_PR;
		}
		else
		{
			data->point.x = last_x;
			data->point.y = last_y;
			data->state = LV_INDEV_STATE_REL;
		}

    /*Set the last pressed coordinates*/
//    data->point.x = last_x;
//    data->point.y = last_y;
}

上述代码中我用PEN是否等于0判断是否触摸屏幕,还使用了Xdown和Ydown,这些在我使用的触摸函数头文件中有定义,如下:

这里还不能看出PEN的作用,在找到一个触摸扫描函数,

这里就可以看出当PEN为0即代表有屏幕被触摸。
这里不同的屏幕厂商提供的函数不同,所以判断方式也有不同,如正点原子的:
可以看到正点原子定义了一个结构体,结构体中有存放键值的变量 u16 x[CT_MAX_TOUCH];
u16 y[CT_MAX_TOUCH]。还有用于判断屏幕是否被触摸的变量 u8 sta;此外还有宏定义 #define TP_CATH_PRES 0x40。我们可以查看他的屏幕扫描函数看看他怎么用的。
我们可以看到他这里的屏幕扫描函数有返回值,返回的是 tp_dev.sta&TP_PRES_DOWN,代表当前屏幕状态,0,触屏无触摸;1,触屏有触摸,我们就可以在touchpad_read函数里使用 tp_dev.sta&TP_PRES_DOWN来进行判断。
正点原子的大家根据自己的屏幕实际情况进行修改,修改好了就可以添加测试代码,参考我前面的文章添加测试代码http://t.csdn.cn/qdxaY。

好了,我本次分享就结束了,大家有什么坑欢迎在评论区讨论。

物联沃分享整理
物联沃-IOTWORD物联网 » STM32移植LVGL:一路踩坑之旅

1 评论

  1. 感谢 大佬,我也遇到 同样的 问题 ,

发表评论