忙活了小半年,轉眼間聖誕將至。這次我是沒時間像以前那樣,走一套方案、PCB、焊接、程序、調試的流程了,只好在現有的開發板上寫代碼了。
當我做出這個決定時,我的想法只是用EasyElectronics板在0.96寸OLED顯示屏上畫一顆愛心。但是寫着寫着我就覺得這個愛心難畫——
-
我找不到一個含蓄之中帶有三分活潑三分俏皮四分可愛的愛心形狀;
-
相比以前做過的雙色666光立方(也許以后會寫吧),畫個愛心實在入不了我的法眼。
於是怒改方案,把摳到一半的愛心圖扔進了回收站。
但是畫什么呢?靜態的愛心不行,要畫個會動的。什么會動呢?GIF!世上GIF千千萬,選哪個呢?
我選了微信表情包“長草顏團子過年啦”第一行第二個“喜歡你”。
一、獲取每一幀圖像
網上查閱了一下相關資料,發布的表情想要獲得GIF是基本沒戲的。只有暴力截屏了。
工具:手機。
操作:錄屏。
並傳輸到電腦,此步驟省略。然后把每一幀挖出來。
工具:PotPlayer(也可以用其他軟件)。
操作:對於每一幀(用D與F來逐幀播放),保存當前幀(png格式)。
一共獲得19張不同的圖片。我沒找到可以批量裁剪圖片的軟件。
工具:畫圖。
操作:對於每一幀,裁剪出表情部分。
二、極致色彩->簡約線條
現在有了表情的每一幀(不過背景是灰色的),但在轉換為OLED可以接受的格式之前,還需要先把彩色圖片轉換為黑白。
如果直接用畫圖保存為單色位圖,中間的愛心會消失。
工具:Word 2019(不太老的版本應該都行吧)。
操作:
對於每一幀:
插入圖片;
圖片格式->顏色->重新着色->黑白50%;
另存為PDF;
在Word中保存圖片,輸出的是原始圖片。換個工具。
工具:Adobe Acrobat Pro DC。
操作:對於每一幀,保存圖片為bmp。
現在有了黑白圖片,但尺寸是手機上顯示的大小。
工具:畫圖(沒錯又是畫圖,萬能的畫圖)。
操作:對於每一幀:
另存為單色位圖;
如果圖中有愛心,先補全邊框(如果邊框不完整),再填充顏色;
重新調整大小,高度64(長度自動70);
調整一些看得不順眼的像素。
三、翻譯為代碼
工具:PCtoLCD2002(網上很容易找到)。
操作:對於每一幀:
打開圖片;
生成字模(右下角;格式自己搗鼓吧);
保存字模;
把txt文件的內容復制到代碼中。
一共19張圖,最后一張復制一遍,有定格的效果。
四、單片機程序
先放鏈接,把Release\heart.hex
燒寫進單片機就可以運行啦!
程序用C語言寫成,分成4個文件:
-
data.h
,保存圖片數據(想想把聲明和定義都放在.h
文件里會出什么問題?); -
driver.h
,OLED與定時器相關函數聲明; -
driver.c
,SPI發送、OLED指令、定時器中斷等實現; -
main.c
,定時器回調函數與程序入口。
大致思路是在main
中初始化,在定時器中斷中讀取並顯示圖片。
圖片為70*64像素,每一像素用一個bit存儲,一張圖片需要560字節,20張就是11KB,內存里放不下。<avr/pgmspace.h>
提供了把數據放在程序空間(program space,即flash)的宏PROGMEM
,以及函數memcpy_P
,與memcpy
類似,不過是從flash中拷貝到內存中。
由於進入與退出中斷需要push與pop所有使用的寄存器,相比12.5MHz的SPI與3us的間隔(否則OLED不能正常工作,不知道為什么)所花的時間相當,在中斷中發送數據沒有意義,所以數據是阻塞發送的。
為了優雅,驅動庫與客戶之間用回調函數解耦:客戶定義函數display
,在main
的初始化中把display
的指針作為參數,注冊回調;驅動庫在中斷中通過函數指針調用display
函數(函數指針可以不寫取地址和解引用)。
實現細節就寫這么多吧,其余的看代碼和datasheet即可。
最后放一張效果圖: