赞
踩
【前言】
LVGL能实现非常简约美观的UI界面,前面移植好显示后,这章移植LVGL,实现一个对LED灯控制的小实例。
【开发环境】
【硬件环境】
【实现步骤】
屏线接口原理图为:
使用到触的接口主要有TCLK(时钟)、TCS(片选)、TDI(MOSI)、TDO(MISO)、TPEN(中断)。电阻屏的原理就是当触摸屏按下后,取两个点的电压,来判断坐标在哪里,当屏被按下时,TPEN会给出信号。然后通过spi总线读取两个坐标点,计算出按下的坐标。
我们选取spi3为电阻触摸的通信,其接线如下
开发板 电阻屏
PEN PC9 //INT
DOUT PC11 //MISO
TDIN PC12 //MOSI
TCLK PC10 //SCLK
TCS PC8 //CS
驱动程序的实现按下面的步骤来实现:
1、首先,宏定义如下:
- #define TCLK_GPIO_Port GPIOC
-
-
-
- #define TCLK_PIN GPIO_PIN_10
-
-
-
- #define TCLK_L TCLK_GPIO_Port->BRR = TCLK_PIN; //拉低SCK
-
-
-
- #define TCLK_H TCLK_GPIO_Port->BSRR = TCLK_PIN; //拉高SCK
-
-
-
- #define TDIN_GPIO_Port GPIOC
-
-
-
- #define TDIN_PIN GPIO_PIN_12
-
-
-
- #define TDIN_L TDIN_GPIO_Port->BRR = TDIN_PIN; //MOSI 低电平
-
-
-
- #define TDIN_H TDIN_GPIO_Port->BSRR = TDIN_PIN; //MOSI 高电平
-
-
-
- #define TCS_GPIO_Port GPIOC
-
-
-
- #define TCS_PIN GPIO_PIN_13
-
-
-
- #define TCS_L TCS_GPIO_Port->BRR = TCS_PIN; //cs 低电平
-
-
-
- #define TCS_H TCS_GPIO_Port->BSRR = TCS_PIN; //cs 高电平
-
-
-
- #define DOUT_GPIO_Port GPIOC
-
-
-
- #define DOUT_Pin GPIO_PIN_11
-
-
-
- #define PEN HAL_GPIO_ReadPin(PEN_GPIO_Port, PEN_Pin)
-
-
-
- #define DOUT HAL_GPIO_ReadPin(DOUT_GPIO_Port, DOUT_Pin)
-
-
-
- 初始化GPIO,把TCK、TDIN、TCS配置为输出模式,把DOUT、PEN配置为输入模式。
-
-
-
- //注意,时钟使能之后,对GPIO的操作才有效
-
-
-
- //所以上拉之前,必须使能时钟.才能实现真正的上拉输出
-
-
-
- GPIO_InitTypeDefGPIO_InitStruct = {0};
-
-
-
- //注意,时钟使能之后,对GPIO的操作才有效
-
-
-
- //所以上拉之前,必须使能时钟.才能实现真正的上拉输出
-
-
-
- /*Configure GPIO pin : PtPin */
-
-
-
- GPIO_InitStruct.Pin = TCLK_PIN | TDIN_PIN;
-
-
-
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
-
-
-
- GPIO_InitStruct.Pull = GPIO_PULLUP;
-
-
-
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
-
-
-
- HAL_GPIO_Init(TCLK_GPIO_Port, &GPIO_InitStruct);
-
-
-
- /*Configure GPIO pin : PtPin */
-
-
-
- GPIO_InitStruct.Pin = PEN_Pin | DOUT_Pin;
-
-
-
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
-
-
-
- GPIO_InitStruct.Pull = GPIO_NOPULL;
-
-
-
- HAL_GPIO_Init(PEN_GPIO_Port, &GPIO_InitStruct);

2、实现对电阻屏的写一个字节的函数TP_Write_Byte,代码如下:
- void TP_Write_Byte(uint8_t num)
-
- {
-
- uint8_t count=0;
-
- for(count=0;count<8;count++)
-
- {
-
- if(num&0x80)
-
- {TDIN_H;}
-
- else
-
- {TDIN_L;}
-
- num<<=1;
-
- TCLK_L;
-
- TCLK_H; //上升沿有效
-
- }
-
- }
-

3、实现对电阻屏的读一个字节的函数TP_Read_AD(uint8_t CMD),代码如下:
- uint16_t TP_Read_AD(uint8_t CMD)
-
- {
-
- uint8_t count=0;
-
- uint16_t Num=0;
-
- TCLK_L; //先拉低时钟
-
- TDIN_L; //拉低数据线
-
- TCS_L; //选中触摸屏IC
-
- TP_Write_Byte(CMD);//发送命令字
-
- delay_us(6);//ADS7846的转换时间最长为6us
-
- TCLK_L;
-
- delay_us(1);
-
- TCLK_H; //给1个时钟,清除BUSY
-
- TCLK_L;
-
- for(count=0;count<16;count++)//读出16位数据,只有高12位有效
-
- {
-
- Num<<=1;
-
- TCLK_L; //下降沿有效
-
- TCLK_H;
-
- if(DOUT)Num++;
-
- }
-
- Num>>=4; //只有高12位有效.
- TCS_H; //释放片选
-
- return(Num);
-
-
-
- }

4、实现读取指定寄存器的函数 TP_Read_XOY(uint8_t xy),代码如下:
- uint16_t TP_Read_XOY(uint8_t xy)
-
- {
-
- uint16_t i, j;
-
- uint16_t buf[READ_TIMES];
-
- uint16_t sum=0;
-
- uint16_t temp;
-
- for(i=0;i<READ_TIMES;i++)buf[i]=TP_Read_AD(xy);
-
- for(i=0;i<READ_TIMES-1; i++)//排序
-
- {
-
- for(j=i+1;j<READ_TIMES;j++)
-
- {
-
- if(buf[i]>buf[j])//升序排列
-
- {
-
- temp=buf[i];
-
- buf[i]=buf[j];
-
- buf[j]=temp;
-
- }
-
- }
-
- }
-
- sum=0;
-
- for(i=LOST_VAL;i<READ_TIMES-LOST_VAL;i++)sum+=buf[i];
-
- temp=sum/(READ_TIMES-2*LOST_VAL);
-
- return temp;
-
- }

5、实现读取指定xy坐标函数TP_Read_XY(uint16_t *x,uint16_t *y),代码如下:
- uint8_t TP_Read_XY(uint16_t *x,uint16_t *y)
-
- {
-
- uint16_t xtemp,ytemp;
-
- xtemp=TP_Read_XOY(CMD_RDX);
-
- ytemp=TP_Read_XOY(CMD_RDY);
-
- //if(xtemp<100||ytemp<100)return 0;//读数失败
-
- *x=xtemp;
-
- *y=ytemp;
-
- return 1;//读数成功
-
- }

6、为了准备的读取坐标植,定义了误差值范围为50,进行滤波算法,连续采集5次,丢弃一个,然后做平均,来得出坐标。TP_Read_XY2(uint16_t *x,uint16_t *y),代码如下:
- uint8_t TP_Read_XY2(uint16_t *x,uint16_t *y)
-
- {
-
- uint16_t x1,y1;
-
- uint16_t x2,y2;
-
- uint8_t flag;
-
- flag=TP_Read_XY(&x1,&y1);
-
- if(flag==0)return(0);
-
- flag=TP_Read_XY(&x2,&y2);
-
- if(flag==0)return(0);
-
- if(((x2<=x1&&x1<x2+ERR_RANGE)||(x1<=x2&&x2<x1+ERR_RANGE))//前后两次采样在+-50内
-
- &&((y2<=y1&&y1<y2+ERR_RANGE)||(y1<=y2&&y2<y1+ERR_RANGE)))
-
- {
-
- *x=(x1+x2)/2;
-
- *y=(y1+y2)/2;
-
- return 1;
-
- }else return 0;
-
- }
-

7、电阻屏需要读取4个着的坐标进行屏幕较准,为此驱动设计了四点较准法来对屏幕进行较准,此次的较准点为:
1 (20,20) (x0,y0)
2 (lcddev.width-20,20) (x1,y1)
3 (20,lcddev.height-20) (x2,y2)
4 (lcddev.width-20,lcddev.height-20) (x3,y3)
8、算法步骤:
9、较准函数如下:
- /*****************************************************************************
-
- * [url=home.php?mod=space&uid=139335]@name[/url] :uint8_t TP_Get_Adjdata(void)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Calibration touch screen and Get 4 calibration parameters
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :None
- * @retvalue :None
- ******************************************************************************/
-
- void TP_Adjust(void)
-
- {
-
- uint16_t pos_temp[4][2];//坐标缓存值
-
- uint8_t cnt=0;
-
- uint16_t d1,d2;
-
- uint32_t tem1,tem2;
-
- float fac;
-
- uint16_t outtime=0;
-
- cnt=0;
-
-
-
-
-
- fillScreen(ILI9488_WHITE);//清屏
-
- ILI9488_printText("Please use the stylus click the", 10,40,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- ILI9488_printText("cross on the screen.The cross will", 10,56,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- ILI9488_printText("always move until the screen", 10,72,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- ILI9488_printText("adjustment is completed.", 10,88,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- TP_Drow_Touch_Point(20,20,ILI9488_RED);//画点1
-
- tp_dev.sta=0;//消除触发信号
-
- tp_dev.xfac=0;//xfac用来标记是否校准过,所以校准之前必须清掉!以免错误
-
- while(1)//如果连续10秒钟没有按下,则自动退出
-
- {
-
- tp_dev.scan(1);//扫描物理坐标
-
- if((tp_dev.sta&0xc0)==TP_CATH_PRES)//按键按下了一次(此时按键松开了.)
-
- {
-
- outtime=0;
-
- tp_dev.sta&=~(1<<6);//标记按键已经被处理过了.
-
-
-
- pos_temp[cnt][0]=tp_dev.x;
-
- pos_temp[cnt][1]=tp_dev.y;
-
- cnt++;
-
- switch(cnt)
-
- {
-
- case 1:
-
- TP_Drow_Touch_Point(20,20,ILI9488_WHITE); //清除点1
-
- TP_Drow_Touch_Point(lcddev.width-20,20,ILI9488_RED); //画点2
-
- break;
-
- case 2:
-
- TP_Drow_Touch_Point(lcddev.width-20,20,ILI9488_WHITE); //清除点2
-
- TP_Drow_Touch_Point(20,lcddev.height-20,ILI9488_RED); //画点3
-
- break;
-
- case 3:
-
- TP_Drow_Touch_Point(20,lcddev.height-20,ILI9488_WHITE); //清除点3
-
- TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,ILI9488_RED); //画点4
-
- break;
-
- case 4: //全部四个点已经得到
-
- //对边相等
-
- tem1=abs(pos_temp[0][0]-pos_temp[1][0]);//x1-x2
-
- tem2=abs(pos_temp[0][1]-pos_temp[1][1]);//y1-y2
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d1=sqrt(tem1+tem2);//得到1,2的距离
-
-
-
- tem1=abs(pos_temp[2][0]-pos_temp[3][0]);//x3-x4
-
- tem2=abs(pos_temp[2][1]-pos_temp[3][1]);//y3-y4
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d2=sqrt(tem1+tem2);//得到3,4的距离
-
- fac=(float)d1/d2;
-
- if(fac<0.95||fac>1.05||d1==0||d2==0)//不合格
-
- {
-
- cnt=0;
-
- TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,ILI9488_WHITE); //清除点4
-
- TP_Drow_Touch_Point(20,20,ILI9488_RED); //画点1
-
- TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据
-
- continue;
-
- }
-
- tem1=abs(pos_temp[0][0]-pos_temp[2][0]);//x1-x3
-
- tem2=abs(pos_temp[0][1]-pos_temp[2][1]);//y1-y3
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d1=sqrt(tem1+tem2);//得到1,3的距离
-
-
-
- tem1=abs(pos_temp[1][0]-pos_temp[3][0]);//x2-x4
-
- tem2=abs(pos_temp[1][1]-pos_temp[3][1]);//y2-y4
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d2=sqrt(tem1+tem2);//得到2,4的距离
-
- fac=(float)d1/d2;
-
- if(fac<0.95||fac>1.05)//不合格
-
- {
-
- cnt=0;
-
- TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,ILI9488_WHITE); //清除点4
-
- TP_Drow_Touch_Point(20,20,ILI9488_RED); //画点1
-
- TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据
-
- continue;
-
- }//正确了
-
-
-
- //对角线相等
-
- tem1=abs(pos_temp[1][0]-pos_temp[2][0]);//x1-x3
-
- tem2=abs(pos_temp[1][1]-pos_temp[2][1]);//y1-y3
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d1=sqrt(tem1+tem2);//得到1,4的距离
-
-
-
- tem1=abs(pos_temp[0][0]-pos_temp[3][0]);//x2-x4
-
- tem2=abs(pos_temp[0][1]-pos_temp[3][1]);//y2-y4
-
- tem1*=tem1;
-
- tem2*=tem2;
-
- d2=sqrt(tem1+tem2);//得到2,3的距离
-
- fac=(float)d1/d2;
-
- if(fac<0.95||fac>1.05)//不合格
-
- {
-
- cnt=0;
-
- TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,ILI9488_WHITE); //清除点4
-
- TP_Drow_Touch_Point(20,20,ILI9488_RED); //画点1
-
- TP_Adj_Info_Show(pos_temp[0][0],pos_temp[0][1],pos_temp[1][0],pos_temp[1][1],pos_temp[2][0],pos_temp[2][1],pos_temp[3][0],pos_temp[3][1],fac*100);//显示数据
-
- continue;
-
- }//正确了
-
- //计算结果
-
- tp_dev.xfac=(float)(lcddev.width-40)/(pos_temp[1][0]-pos_temp[0][0]);//得到xfac
-
- tp_dev.xoff=(lcddev.width-tp_dev.xfac*(pos_temp[1][0]+pos_temp[0][0]))/2;//得到xoff
-
-
-
- tp_dev.yfac=(float)(lcddev.height-40)/(pos_temp[2][1]-pos_temp[0][1]);//得到yfac
-
- tp_dev.yoff=(lcddev.height-tp_dev.yfac*(pos_temp[2][1]+pos_temp[0][1]))/2;//得到yoff
-
- if(abs(tp_dev.xfac)>2||abs(tp_dev.yfac)>2)//触屏和预设的相反了.
-
- {
-
- cnt=0;
-
- TP_Drow_Touch_Point(lcddev.width-20,lcddev.height-20,ILI9488_WHITE); //清除点4
-
- TP_Drow_Touch_Point(20,20,ILI9488_RED); //画点1
-
- ILI9488_printText("TP Need readjust!", 40,26,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- tp_dev.touchtype=!tp_dev.touchtype;//修改触屏类型.
-
- if(tp_dev.touchtype)//X,Y方向与屏幕相反
-
- {
-
- CMD_RDX=0X90;
-
- CMD_RDY=0XD0;
-
- }else //X,Y方向与屏幕相同
-
- {
-
- CMD_RDX=0XD0;
-
- CMD_RDY=0X90;
-
- }
-
- continue;
-
- }
-
-
-
- fillScreen(ILI9488_WHITE);//清屏
-
- ILI9488_printText("Touch Screen Adjust OK!", 35,110,ILI9488_BLACK, ILI9488_WHITE, 2);
-
- HAL_Delay(1000);
-
- TP_Save_Adjdata();
-
- fillScreen(ILI9488_WHITE);//清屏
-
- return;//校正完成
-
- }
-
- }
-
- HAL_Delay(10);
-
- outtime++;
-
- if(outtime>1000)
-
- {
-
- TP_Get_Adjdata();
-
- break;
-
- }
-
- }
-
- }
-

10、较准参数的保存
较准参数,工程设计保存到备份寄存器中,stm32U5A5有32个TMP备份寄存器可以用,工程里RTC已初始化好了备份寄存器,并且有HAL的扩展读写函数。RTC已使用了RTC_BKP_DR1-RTC_BKP_DR5,因此此存我们使用RTC_BKP_DR6-11来保存较准因素、X偏移量、Y偏移量、触屏的模竖类型,以及是否较准的标记。具体读写代码如下:
- void TP_Save_Adjdata(void)
-
- {
-
- int32_t temp;
-
- //保存校正结果!
-
- temp=tp_dev.xfac*100000000;//保存x校正因素
-
-
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, temp);
-
- temp=tp_dev.yfac*100000000;//保存y校正因素
-
-
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR7, temp);
-
- //保存x偏移量
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR8, tp_dev.xoff);
-
-
-
- //保存y偏移量
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR9, tp_dev.yoff);
-
-
-
- //保存触屏类型
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR10, tp_dev.touchtype);
-
-
-
- temp=0X0A;//标记校准过了
-
- HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR11, temp);
-
-
-
- }
-
-
-
- /*****************************************************************************
-
- * [url=home.php?mod=space&uid=139335]@name[/url] :uint8_t TP_Get_Adjdata(void)
- * [url=home.php?mod=space&uid=212281]@date[/url] :2018-08-09
- * [url=home.php?mod=space&uid=42490]@function[/url] :Gets the calibration values stored in the EEPROM
- * [url=home.php?mod=space&uid=2814924]@parameters[/url] :None
- * @retvalue :1-get the calibration values successfully
- 0-get the calibration values unsuccessfully and Need to recalibrate
-
- ******************************************************************************/
-
- uint8_t TP_Get_Adjdata(void)
-
- {
-
- int32_t tempfac;
-
-
-
- tempfac = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR11);
-
- if(tempfac==0X0A)//触摸屏已经校准过了
-
- {
-
- tempfac=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6);
-
- tp_dev.xfac=(float)tempfac/100000000;//得到x校准参数
-
- tempfac=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR7);
-
- tp_dev.yfac=(float)tempfac/100000000;//得到y校准参数
-
- //得到x偏移量
-
- tp_dev.xoff=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR8);
-
- //得到y偏移量
-
- tp_dev.yoff=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR9);
-
- tp_dev.touchtype=HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR10);//读取触屏类型标记
-
- if(tp_dev.touchtype)//X,Y方向与屏幕相反
-
- {
-
- CMD_RDX=0X90;
-
- CMD_RDY=0XD0;
-
- }else //X,Y方向与屏幕相同
-
- {
-
- CMD_RDX=0XD0;
-
- CMD_RDY=0X90;
-
- }
-
- return 1;
-
- }
-
- return 0;
-
- }

至此,已经实了触摸的驱动,可以正式进入LVGL的移植了。
【LVGL移植】
3、把文件夹的目录添加到工程里面:
4、复制lv_port_disp_template.h/c、lv_port_indev_template.h/c到src目录下面,并且重命名为lv_port_disp.h/c、lv_port_indev.h/c。
5、打开lv_port_disp.h,把if 0修改为if 1,同时把文件的引用路径修改为#include “lvgl.h”
6、打开lv_port_disp.c,修改if 0,为if 1。添加lcd屏、的头文件引用,添加hspi1、touch、lcd等的变量的扩展声明。
7、在函数lv_port_disp_init中定义宽的参数,以及刷新缓存的方式
8、修改disp_flush函数为内容如下:
- static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
-
- {
-
- /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
-
-
-
- uint32_t i, n, cnt, buf_size,h,w;
-
- uint8_t r,g,b;
-
- w = area->x2- area->x1 +1;
-
- h = area->y2- area->y1 +1;
-
- setAddrWindow(area->x1, area->y1, area->x2, area->y2); //设置显示块大小
-
- n = w*h*3;
-
-
-
- //割分发送给屏
-
- if (n <= 65535){
-
- cnt = 1;
-
- buf_size = n;
-
- }
-
- else {
-
- cnt = n/3;
-
- buf_size = 3;
-
- uint8_t min_cnt = n/(65535)+1;
-
- for (i=min_cnt; i < n/3; i++)
-
- {
-
- if(n%i == 0)
-
- {
-
- cnt = i;
-
- buf_size = n/i;
-
- break;
-
- }
-
- }
-
- }
-
-
-
- DC_DATA();
-
- CS_A();
-
- while(cnt>0)
-
- {
-
- uint8_t frm_buf[buf_size];
-
- for (i=0; i < buf_size/3; i++)
-
- {
-
- r = (((color_p->full & 0xF800) >> 11) * 255) / 31;
- g = (((color_p->full & 0x07E0) >> 5) * 255) / 63;
- b = (color_p->full & 0x001F * 255) / 31;
-
- frm_buf[i*3] = r;
-
- frm_buf[i*3+1] = g;
-
- frm_buf[i*3+2] = b;
-
- color_p++;
-
- }
-
- //HAL_SPI_Transmit(&hspi1, frm_buf, buf_size, HAL_MAX_DELAY);
-
- HAL_SPI_Transmit(&hspi1, frm_buf, buf_size, 10);
-
- cnt -= 1;
-
- }
-
- CS_D();
-
-
-
-
-
- /*IMPORTANT!!!
-
- *Inform the graphics library that you are ready with the flushing*/
-
- lv_disp_flush_ready(disp_drv);
-
- }
-

10、在disp_init函数中,加入LCD屏初始化,设置屏有横竖类型,同时修改电阻屏的横竖:
11、重命名lvgl目录下的lvgl_conf_template.h为lvgl_conf.h。
12、打开lvgl_conf.h,修改if 0为if 1,打开代码。
13、为lvgl添加freertos的tick心跳包,在第88行左右,找到#define LV_TICK_CUSTOM,把他修改为1,同时修改内容如下,使得lvgl的心跳包为freertos来提供:
- #define LV_TICK_CUSTOM 1
-
-
-
- #if LV_TICK_CUSTOM
-
-
-
- #define LV_TICK_CUSTOM_INCLUDE "FreeRTOS.h"/*Header for the system time function*/
-
-
-
- #define LV_TICK_CUSTOM_SYS_TIME_EXPR (xTaskGetTickCount()) /*Expression evaluating to current system time in ms*/
-
-
-
- /*If using lvgl as ESP32 component*/
-
-
-
- // #define LV_TICK_CUSTOM_INCLUDE "esp_timer.h"
-
-
-
- // #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((esp_timer_get_time() / 1000LL))
-
-
-
- #endif/*LV_TICK_CUSTOM*/

14、打开lv_port_indev.h 修改if 0为 if 1打开代码。
15、打开lv_port_indev.c,修改if 0 为if 1, 打开代码,同时添加touch.h的头文件引用:
16、修改touchpad_read函数内容如下:
- /*Will be called by the library to read the touchpad*/
-
- 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;
-
-
-
- TP_Scan(0);
-
- if(tp_dev.sta&TP_PRES_DOWN)
-
- {
-
- last_x = tp_dev.x;
-
- last_y = tp_dev.y;
-
-
-
- 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;
-
- }
-
- }

到此代码的移植全部完成,编译后有些错误提示,可以根据提示来添加头文件的引用等。
【测试代码】
1、在main.c中,我们需要先添加lcd的初始化与电阻屏的初化与较准。
2、在app_freertos.c文件中,我们在任务中添加一个LED的控制程序,添加一个LED及一个开关部件来实现对板载LED红灯的控制。添加一个label标签,用于展示当前的时间,开启一个定时器,在定时器回调函数中刷定时间显示。
- lv_obj_t *led ; //LED�?
-
- lv_obj_t *sw_led; //按键
-
- lv_obj_t *lab_time; //时间显示标签
-
- lv_timer_t * lvgl_task1 = NULL;
-
- lv_obj_t *obj1;
-
- RTC_DateTypeDef GetData; //获取日期结构
-
-
-
- RTC_TimeTypeDef GetTime; //获取时间结构
-
-
-
- static void switc_led_envet_handler(lv_event_t* e)
-
- {
-
- lv_event_code_t code = lv_event_get_code(e);
-
- if (code == LV_EVENT_VALUE_CHANGED)
-
- {
-
- if(lv_obj_has_state(sw_led, LV_STATE_CHECKED))
-
- {
-
- lv_led_on(led);
-
- HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, SET);
-
- }
-
- else
-
- {
-
- lv_led_off(led);
-
- HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, RESET);
-
- }
-
- }
-
- }
-
-
-
- static void lvgl_rtc_cb(lv_timer_t *tmr)
-
- {
-
- HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
-
- /* Get the RTC current Date */
-
- HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
-
- lv_label_set_text_fmt(lab_time, "%04d/%02d/%02d %02d:%02d:%02d",
-
- 2000 + GetData.Year, GetData.Month, GetData.Date, GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
-
- lv_obj_align_to(lab_time,obj1,LV_ALIGN_OUT_BOTTOM_MID,0,20);
-
- }
-
-
-

- void StartTask02(void *argument)
-
- {
-
- /* USER CODE BEGIN myTask02 */
-
- lv_init(); /* lvgl系统初始 */
-
- lv_port_disp_init(); /* lvgl显示接口初始�????????,放在lv_init() */
-
- lv_port_indev_init();
-
- obj1 = lv_obj_create(lv_scr_act());
-
- lv_obj_set_size(obj1,200,300);
-
- lv_obj_set_align(obj1, LV_ALIGN_CENTER); //居中
-
-
-
- lv_obj_t *label1 = lv_label_create(lv_scr_act());
-
-
-
- lv_obj_set_style_text_font(label1,&lv_font_montserrat_24,LV_STATE_DEFAULT);
-
- lv_label_set_text(label1, "STM32U5A5 LED DEMO");
-
- lv_obj_align_to(label1,obj1,LV_ALIGN_OUT_TOP_MID,0,-20);
-
-
-
- led = lv_led_create(obj1);
-
- lv_obj_set_size(led,80,80);
-
-
-
- lab_time = lv_label_create(lv_scr_act());
-
- lv_obj_set_style_text_font(lab_time, &lv_font_montserrat_24,LV_STATE_DEFAULT);
-
-
-
- lv_led_off(led);
-
-
-
- sw_led = lv_switch_create(obj1);
-
- lv_obj_set_size(sw_led,100,50);
-
- lv_obj_add_event_cb(sw_led, switc_led_envet_handler,LV_EVENT_VALUE_CHANGED,NULL);
-
-
-
- lv_obj_align_to(led,obj1,LV_ALIGN_CENTER,0,-60);
-
- lv_obj_align_to(sw_led,obj1,LV_ALIGN_CENTER,0,60);
-
-
-
-
-
-
-
- lvgl_task1 = lv_timer_create(lvgl_rtc_cb, 1000, 0); // 运行周期为lvgl�?1000个滴答时�?
-
-
-
- /* Infinite loop */
-
- for(;;)
-
- {
-
-
-
- lv_timer_handler(); /* LVGL计时 */
-
- osDelay(10);
-
- }
-
- /* USER CODE END myTask02 */
-
- }

【实现效果】
【总结】
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。