實用 | 手頭上無LCD卻又急著開發(fā)UI?LCD模擬器了解一下~

      網(wǎng)友投稿 878 2025-03-31

      LCD模擬器


      在我們嵌入式開發(fā)中,有時候有些調(diào)試環(huán)境、流程比較復(fù)雜/繁雜。比如有些bug需要跑很長的一段流程才可以復(fù)現(xiàn),這時候如果按照正常的流程來調(diào)試,單單是復(fù)現(xiàn)問題估計都需要話不少時間。

      這時候應(yīng)該要多思考需要怎么去模擬一個相同的環(huán)境,可以更方便地進行調(diào)試,一個好的仿真環(huán)境可以大大地提高工作效率。比如數(shù)據(jù)的模擬、流程的模擬、通信收發(fā)的模擬等方面,或是用一些網(wǎng)上現(xiàn)成的模擬器。

      本次就來給大家分享一個實用的LCD模擬器:VirtLCD。這個模擬器在我們的工作中有用到,覺得挺實用,分享給大家。

      這個模擬器的代碼是開源的,大家感興趣的話可以自己去下載來研究。地址:

      https://gitee.com/kerndev/VirtualLCD

      下面進行實踐演示。先看一個圖:

      使用VirtLCD時,我們同樣需要一個demo(VirtSTM32)工程編寫我們的界面設(shè)計代碼,調(diào)試好之后可以很快地移到STM32工程上。

      //畫點

      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?

      {

      *mem++?=?color;

      }

      }

      //畫垂直直線

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

      {

      PIXEL?*mem;

      mem?=?GET_FRAMEBUFFER(x1,?y1);

      for(;?y1?

      {

      *mem?=?color;

      mem?-=?LCD_WIDTH;

      }

      }

      下面我們新建一個VirtSTM32工程(VS2019控制臺程序)進行驗證,然后把這些函數(shù)加到我們的VirtSTM32工程里。同時,VirtSTM32需要依賴于VirtLCD.lib,導(dǎo)入即可,這個庫可以在VirtLCD SDK包里找到(文末統(tǒng)一發(fā)給大家)。

      有了這三個基礎(chǔ)函數(shù),我們可以就可以做很多的事情了,顯示字符串、顯示圖片等函數(shù)都是以畫點函數(shù)為基礎(chǔ)的,這些函數(shù)可以在各種開發(fā)板的lcd相關(guān)例程里找到,拿過來修改一下就可以。接下來我們顯示一些字符串到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;

      }

      運行結(jié)果:

      這就是模擬STM32裸機顯示字符串到VirtLCD中,調(diào)試好之后我們可以很快地移到真正的STM32工程中。這里只是進行簡單的演示,當(dāng)然,感興趣的話,還可以移植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坐標(biāo)的幀緩存指針

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

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

      //響應(yīng)鼠標(biāo)事件

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

      {

      }

      //響應(yīng)鍵盤事件

      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);

      實用 | 手頭上無LCD卻又急著開發(fā)UI?LCD模擬器了解一下~

      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?

      {

      *mem++?=?color;

      }

      }

      //畫垂直直線

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

      {

      PIXEL*?mem;

      mem?=?GET_FRAMEBUFFER(x1,?y1);

      for?(;?y1?

      {

      *mem?=?color;

      mem?-=?LCD_WIDTH;

      }

      }

      //在指定位置顯示一個字符

      //x,y:起始坐標(biāo)

      //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);??//得到字體一個字符對應(yīng)點陣集所占的字節(jié)數(shù)

      num=num-'?';//得到偏移后的值(ASCII字庫是從空格開始取模,所以-'?'就是對應(yīng)字符的字庫)

      for(t=0;t

      {

      if(size==12)temp=ascii_1206[num][t];????//調(diào)用1206字體

      else?if(size==16)temp=ascii_1608[num][t];?//調(diào)用1608字體

      else?if(size==24)temp=ascii_2412[num][t];?//調(diào)用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;??//超區(qū)域了

      if((y-y0)==size)

      {

      y=y0;

      x++;

      if(x>=LCD_WIDTH)return;?//超區(qū)域了

      break;

      }

      }

      }

      }

      //顯示字符串

      //x,y:起點坐標(biāo)

      //width,height:區(qū)域大小

      //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我已經(jīng)打包好了放在后臺,大家可以在本公眾號后臺回復(fù)關(guān)鍵詞:VLCD ,即可獲取。

      基礎(chǔ)很重要!elf和map文件有不同?

      為什么 128 KB 的魂斗羅可以塞下這么長的劇情?

      100元都不到的樹莓派Zero 2 W正式發(fā)布!

      API/SDK

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:c語言實現(xiàn)排序和查找所有算法
      下一篇:word2013制作三線表的方法(word三線表制作步驟)
      相關(guān)文章
      亚洲性69影院在线观看| 亚洲大尺码专区影院| 亚洲免费闲人蜜桃| 久久亚洲精品国产精品| 久久香蕉国产线看观看亚洲片| 中文字幕中韩乱码亚洲大片| 亚洲精品国产成人影院| 亚洲精品国精品久久99热| 亚洲国产精品人人做人人爽| 亚洲 小说区 图片区 都市| 亚洲AⅤ无码一区二区三区在线| 亚洲a∨国产av综合av下载| 亚洲欧美成人综合久久久| 亚洲中文字幕无码中文| 亚洲一级大黄大色毛片| 99热亚洲色精品国产88| 亚洲国产精品一区二区三区在线观看| 亚洲av永久无码嘿嘿嘿| 在线aⅴ亚洲中文字幕| 亚洲人AV在线无码影院观看| 亚洲日本一线产区和二线| 亚洲av专区无码观看精品天堂 | 精品国产亚洲一区二区在线观看 | 亚洲香蕉免费有线视频| 亚洲日韩乱码中文无码蜜桃| 亚洲黄色激情视频| 亚洲国产精品无码中文lv| 成人婷婷网色偷偷亚洲男人的天堂 | 久久亚洲最大成人网4438| 亚洲中文字幕精品久久| 精品亚洲成a人在线观看| 亚洲精品tv久久久久久久久久| 亚洲中文字幕无码专区| 亚洲一区爱区精品无码| 久久久久亚洲AV成人无码网站| 亚洲av成人无码久久精品| 亚洲无砖砖区免费| 亚洲熟妇无码一区二区三区| 久久久亚洲精华液精华液精华液| 亚洲精品国产V片在线观看 | 亚洲一区二区三区国产精华液|