实用 | 手头上无LCD却又急着开发UI?LCD模拟器了解一下~

网友投稿 725 2022-05-29

LCD模拟器

在我们嵌入式开发中,有时候有些调试环境、流程比较复杂/繁杂。比如有些bug需要跑很长的一段流程才可以复现,这时候如果按照正常的流程来调试,单单是复现问题估计都需要话不少时间。

这时候应该要多思考需要怎么去模拟一个相同的环境,可以更方便地进行调试,一个好的仿真环境可以大大地提高工作效率。比如数据的模拟、流程的模拟、通信收发的模拟等方面,或是用一些网上现成的模拟器。

本次就来给大家分享一个实用的LCD模拟器:VirtLCD。这个模拟器在我们的工作中有用到,觉得挺实用,分享给大家。

这个模拟器的代码是开源的,大家感兴趣的话可以自己去下载来研究。地址:

https://gitee.com/kerndev/VirtualLCD

下面进行实践演示。先看一个图:

使用VirtLCD时,我们同样需要一个demo(VirtSTM32)工程编写我们的界面设计代码,调试好之后可以很快地移到STM32工程上。

//画点

void  LCD_DrawPoint(int x, int y, PIXEL color)

{

PIXEL *mem;

实用 | 手头上无LCD却又急着开发UI?LCD模拟器了解一下~

mem = GET_FRAMEBUFFER(x, y);

*mem = color;

}

//画水平直线

void  LCD_DrawHLine(int x1, int y1, int x2, PIXEL color)

{

PIXEL *mem;

mem = GET_FRAMEBUFFER(x1, y1);

for(; x1 < x2; x1++)

{

*mem++ = color;

}

}

//画垂直直线

void  LCD_DrawVLine(int x1, int y1, int y2, PIXEL color)

{

PIXEL *mem;

mem = GET_FRAMEBUFFER(x1, y1);

for(; y1 < y2; y1++)

{

*mem = color;

mem -= LCD_WIDTH;

}

}

下面我们新建一个VirtSTM32工程(VS2019控制台程序)进行验证,然后把这些函数加到我们的VirtSTM32工程里。同时,VirtSTM32需要依赖于VirtLCD.lib,导入即可,这个库可以在VirtLCD SDK包里找到(文末统一发给大家)。

有了这三个基础函数,我们可以就可以做很多的事情了,显示字符串、显示图片等函数都是以画点函数为基础的,这些函数可以在各种开发板的lcd相关例程里找到,拿过来修改一下就可以。接下来我们显示一些字符串到Virtlcd上,如:

左右滑动查看全部代码>>>

int main(void)

{

LCD_Init();

printf("hello virtlcd, i am ZhengN");

LCD_DrawHLine(10, 10, 350, WHITE);

LCD_ShowString(10, 30, LCD_WIDTH, LCD_HEIGHT, 12, "hello virtlcd, i am ZhengN");

LCD_ShowString(10, 50, LCD_WIDTH, LCD_HEIGHT, 16, "hello virtlcd, i am ZhengN");

LCD_ShowString(10, 70, LCD_WIDTH, LCD_HEIGHT, 24, "hello virtlcd, i am ZhengN");

LCD_DrawHLine(10, 110, 350, WHITE);

while(1);

return 0;

}

运行结果:

这就是模拟STM32裸机显示字符串到VirtLCD中,调试好之后我们可以很快地移到真正的STM32工程中。这里只是进行简单的演示,当然,感兴趣的话,还可以移植LVGL、emwin等GUI进去。

附VirtSTM32主要代码:

#include "virtlcd.h"

#include "font.h"

#include 

#pragma comment(lib, "virtlcd.lib")

#define LCD_FILENAME    "virtlcd.exe"

#define LCD_WIDTH       480

#define LCD_HEIGHT      320

#define LCD_BPP         32

#define WHITE           0xFFFFFFFF

#define BLACK           0x00000000

#define FRONT_COLOR WHITE

#define BACK_COLOR BLACK

//定义像素类型

typedef unsigned long   PIXEL;

//帧缓存指针

static PIXEL* m_pFrameBuffer;

//计算在X,Y坐标的帧缓存指针

#define GET_OFFSET(x, y)        (( LCD_WIDTH * ( LCD_HEIGHT - (y) - 1) ) + (x) )

#define GET_FRAMEBUFFER(x, y)   ( m_pFrameBuffer + GET_OFFSET(x, y))

//响应鼠标事件

static void on_mouse_input(int event, int x, int y)

{

}

//响应键盘事件

static void on_keybd_input(int event, int key)

{

}

//初始化LCD

int LCD_Init(void)

{

int ret;

ret = VirtLCD_Init(LCD_FILENAME, LCD_WIDTH, LCD_HEIGHT, LCD_BPP);

if (!ret)

{

return 0;

}

m_pFrameBuffer = VirtLCD_GetFrameBuffer();

VirtLCD_SetMouseProc(on_mouse_input);

VirtLCD_SetKeybdProc(on_keybd_input);

return 1;

}

//画点

void  LCD_DrawPoint(int x, int y, PIXEL color)

{

PIXEL* mem;

mem = GET_FRAMEBUFFER(x, y);

*mem = color;

}

//画水平直线

void  LCD_DrawHLine(int x1, int y1, int x2, PIXEL color)

{

PIXEL* mem;

mem = GET_FRAMEBUFFER(x1, y1);

for (; x1 < x2; x1++)

{

*mem++ = color;

}

}

//画垂直直线

void  LCD_DrawVLine(int x1, int y1, int y2, PIXEL color)

{

PIXEL* mem;

mem = GET_FRAMEBUFFER(x1, y1);

for (; y1 < y2; y1++)

{

*mem = color;

mem -= LCD_WIDTH;

}

}

//在指定位置显示一个字符

//x,y:起始坐标

//num:要显示的字符:" "--->"~"

//size:字体大小 12/16/24

//mode:叠加方式(1)还是非叠加方式(0)

void LCD_ShowChar(int x, int y, int num, int size, int mode)

{

int temp,t1,t;

int y0=y;

int csize=(size/8+((size%8)?1:0))*(size/2);  //得到字体一个字符对应点阵集所占的字节数

num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)

for(t=0;t

{

if(size==12)temp=ascii_1206[num][t];    //调用1206字体

else if(size==16)temp=ascii_1608[num][t]; //调用1608字体

else if(size==24)temp=ascii_2412[num][t]; //调用2412字体

else return;        //没有的字库

for(t1=0;t1<8;t1++)

{

if(temp&0x80)LCD_DrawPoint(x,y,FRONT_COLOR);

else if(mode==0)LCD_DrawPoint(x,y,BACK_COLOR);

temp<<=1;

y++;

if(y>=LCD_HEIGHT)return;  //超区域了

if((y-y0)==size)

{

y=y0;

x++;

if(x>=LCD_WIDTH)return; //超区域了

break;

}

}

}

}

//显示字符串

//x,y:起点坐标

//width,height:区域大小

//size:字体大小

//*p:字符串起始地址

void LCD_ShowString(int x, int y, int width, int height, int size, char* p)

{

int x0 = x;

width += x;

height += y;

while ((*p <= '~') && (*p >= ' '))//判断是不是非法字符!

{

if (x >= width) { x = x0; y += size; }

if (y >= height)break;//退出

LCD_ShowChar(x, y, *p, size, 0);

x += size / 2;

p++;

}

}

int main(void)

{

LCD_Init();

printf("hello virtlcd, i am ZhengN");

LCD_DrawHLine(10, 10, 350, WHITE);

LCD_ShowString(10, 30, LCD_WIDTH, LCD_HEIGHT, 12, "hello virtlcd, i am ZhengN");

LCD_ShowString(10, 50, LCD_WIDTH, LCD_HEIGHT, 16, "hello virtlcd, i am ZhengN");

LCD_ShowString(10, 70, LCD_WIDTH, LCD_HEIGHT, 24, "hello virtlcd, i am ZhengN");

LCD_DrawHLine(10, 110, 350, WHITE);

while(1);

return 0;

}

以上就是本次的分享。如果文章对你有帮助,麻烦三连支持一下

代码下载

VirtLCD SDK包及本文的VirtSTM32工程demo我已经打包好了放在后台,大家可以在本公众号后台回复关键词:VLCD ,即可获取。

基础很重要!elf和map文件有不同?

为什么 128 KB 的魂斗罗可以塞下这么长的剧情?

100元都不到的树莓派Zero 2 W正式发布!

API/SDK

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详细解析如何对spark进行全方位的调优
下一篇:java nio 基础用法
相关文章