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

举报
小麦大叔 发表于 2021/12/05 00:03:38 2021/12/05
【摘要】 LCD模拟器 在我们嵌入式开发中,有时候有些调试环境、流程比较复杂/繁杂。比如有些bug需要跑很长的一段流程才可以复现,这时候如果按照正常的流程来调试,单单是复现问题估计都需要话不少时间。 这时候应该要多思考需要怎么去模拟一个相同的环境,可以更方便地进行调试,一个好的仿真环境可以大大地提高工作效率。比如数据的模拟、流程的模拟、...

LCD模拟器

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

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

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

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

https://gitee.com/kerndev/VirtualLCD

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

e2d4b3b3388889a198748a1e5725f18f.png

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

我们在使用STM32做LCD显示时,常常会封装一些基础的绘制函数,如画点、画线等函数。同样的,使用VirtSTM32与VirtLCD做调试时,也要封装类似函数,作者也给我们提供了一些参考,如:


   
  1. //画点
  2. void  LCD_DrawPoint(int x, int y, PIXEL color)
  3. {
  4.     PIXEL *mem;
  5.     mem = GET_FRAMEBUFFER(x, y);
  6.     *mem = color;
  7. }
  8. //画水平直线
  9. void  LCD_DrawHLine(int x1, int y1, int x2, PIXEL color)
  10. {
  11.     PIXEL *mem;
  12.     mem = GET_FRAMEBUFFER(x1, y1);
  13.     for(; x1 < x2; x1++)
  14.     {
  15.         *mem++ = color;
  16.     }
  17. }
  18. //画垂直直线
  19. void  LCD_DrawVLine(int x1, int y1, int y2, PIXEL color)
  20. {
  21.     PIXEL *mem;
  22.     mem = GET_FRAMEBUFFER(x1, y1);
  23.     for(; y1 < y2; y1++)
  24.     {
  25.         *mem = color;
  26.         mem -= LCD_WIDTH;
  27.     }
  28. }

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

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

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


   
  1. int main(void)
  2. {
  3.     LCD_Init();
  4.     printf("hello virtlcd, i am ZhengN");
  5.     LCD_DrawHLine(1010350, WHITE);
  6.     LCD_ShowString(1030, LCD_WIDTH, LCD_HEIGHT, 12"hello virtlcd, i am ZhengN");
  7.     LCD_ShowString(1050, LCD_WIDTH, LCD_HEIGHT, 16"hello virtlcd, i am ZhengN");
  8.     LCD_ShowString(1070, LCD_WIDTH, LCD_HEIGHT, 24"hello virtlcd, i am ZhengN");
  9.     LCD_DrawHLine(10110350, WHITE);
  10.     while(1);
  11.     return 0;
  12. }

运行结果:

5134c5d72cfcfa074394bb40337b0fa2.png

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

附VirtSTM32主要代码:


   
  1. #include "virtlcd.h"
  2. #include "font.h"
  3. #include <stdio.h>
  4. #pragma comment(lib, "virtlcd.lib")
  5. #define LCD_FILENAME    "virtlcd.exe"
  6. #define LCD_WIDTH       480
  7. #define LCD_HEIGHT      320
  8. #define LCD_BPP         32
  9. #define WHITE           0xFFFFFFFF
  10. #define BLACK           0x00000000  
  11. #define FRONT_COLOR WHITE
  12. #define BACK_COLOR BLACK
  13. //定义像素类型
  14. typedef unsigned long   PIXEL;
  15. //帧缓存指针
  16. static PIXEL* m_pFrameBuffer;
  17. //计算在X,Y坐标的帧缓存指针
  18. #define GET_OFFSET(x, y)        (( LCD_WIDTH * ( LCD_HEIGHT - (y) - 1) ) + (x) )
  19. #define GET_FRAMEBUFFER(x, y)   ( m_pFrameBuffer + GET_OFFSET(x, y))
  20. //响应鼠标事件
  21. static void on_mouse_input(int event, int x, int y)
  22. {
  23. }
  24. //响应键盘事件
  25. static void on_keybd_input(int event, int key)
  26. {
  27. }
  28. //初始化LCD
  29. int LCD_Init(void)
  30. {
  31.     int ret;
  32.     ret = VirtLCD_Init(LCD_FILENAME, LCD_WIDTH, LCD_HEIGHT, LCD_BPP);
  33.     if (!ret)
  34.     {
  35.         return 0;
  36.     }
  37.     m_pFrameBuffer = VirtLCD_GetFrameBuffer();
  38.     VirtLCD_SetMouseProc(on_mouse_input);
  39.     VirtLCD_SetKeybdProc(on_keybd_input);
  40.     return 1;
  41. }
  42. //画点
  43. void  LCD_DrawPoint(int x, int y, PIXEL color)
  44. {
  45.     PIXEL* mem;
  46.     mem = GET_FRAMEBUFFER(x, y);
  47.     *mem = color;
  48. }
  49. //画水平直线
  50. void  LCD_DrawHLine(int x1, int y1, int x2, PIXEL color)
  51. {
  52.     PIXEL* mem;
  53.     mem = GET_FRAMEBUFFER(x1, y1);
  54.     for (; x1 < x2; x1++)
  55.     {
  56.         *mem++ = color;
  57.     }
  58. }
  59. //画垂直直线
  60. void  LCD_DrawVLine(int x1, int y1, int y2, PIXEL color)
  61. {
  62.     PIXEL* mem;
  63.     mem = GET_FRAMEBUFFER(x1, y1);
  64.     for (; y1 < y2; y1++)
  65.     {
  66.         *mem = color;
  67.         mem -= LCD_WIDTH;
  68.     }
  69. }
  70. //在指定位置显示一个字符
  71. //x,y:起始坐标
  72. //num:要显示的字符:" "--->"~"
  73. //size:字体大小 12/16/24
  74. //mode:叠加方式(1)还是非叠加方式(0)
  75. void LCD_ShowChar(int x, int y, int num, int size, int mode)
  76. {           
  77.     int temp,t1,t;
  78.     int y0=y;
  79.     int csize=(size/8+((size%8)?1:0))*(size/2);  //得到字体一个字符对应点阵集所占的字节数 
  80.   num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
  81.  for(t=0;t<csize;t++)
  82.  {   
  83.   if(size==12)temp=ascii_1206[num][t];    //调用1206字体
  84.   else if(size==16)temp=ascii_1608[num][t]; //调用1608字体
  85.   else if(size==24)temp=ascii_2412[num][t]; //调用2412字体
  86.   else return;        //没有的字库
  87.   for(t1=0;t1<8;t1++)
  88.   {       
  89.    if(temp&0x80)LCD_DrawPoint(x,y,FRONT_COLOR);
  90.    else if(mode==0)LCD_DrawPoint(x,y,BACK_COLOR);
  91.    temp<<=1;
  92.    y++;
  93.    if(y>=LCD_HEIGHT)return;  //超区域了
  94.    if((y-y0)==size)
  95.    {
  96.     y=y0;
  97.     x++;
  98.     if(x>=LCD_WIDTH)return//超区域了
  99.     break;
  100.    }
  101.   }    
  102.  }                
  103. }  
  104. //显示字符串
  105. //x,y:起点坐标
  106. //width,height:区域大小  
  107. //size:字体大小
  108. //*p:字符串起始地址    
  109. void LCD_ShowString(int x, int y, int width, int height, int size, char* p)
  110. {
  111.     int x0 = x;
  112.     width += x;
  113.     height += y;
  114.     while ((*p <= '~') && (*p >= ' '))//判断是不是非法字符!
  115.     {
  116.         if (x >= width) { x = x0; y += size; }
  117.         if (y >= height)break;//退出
  118.         LCD_ShowChar(x, y, *p, size, 0);
  119.         x += size / 2;
  120.         p++;
  121.     }
  122. }
  123. int main(void)
  124. {
  125.     LCD_Init();
  126.     printf("hello virtlcd, i am ZhengN");
  127.     LCD_DrawHLine(1010350, WHITE);
  128.     LCD_ShowString(1030, LCD_WIDTH, LCD_HEIGHT, 12"hello virtlcd, i am ZhengN");
  129.  LCD_ShowString(1050, LCD_WIDTH, LCD_HEIGHT, 16"hello virtlcd, i am ZhengN");
  130.  LCD_ShowString(1070, LCD_WIDTH, LCD_HEIGHT, 24"hello virtlcd, i am ZhengN");
  131.     LCD_DrawHLine(10110350, WHITE);
  132.     while(1);
  133.     return 0;
  134. }

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

代码下载

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

2dcdd0e17e21f37c7e6cc3b883430cc6.png

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


93f47099b38ed711de80e7a49bb6dd53.png

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


3aa5286419e5ecdcb3bdacd06558508b.png

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

文章来源: great.blog.csdn.net,作者:小麦大叔,版权归原作者所有,如需转载,请联系作者。

原文链接:great.blog.csdn.net/article/details/121113090

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。