網上有很多關于pos機字體下載,F7水星開發(fā)板資料連載第四十六章 漢字顯示實驗的知識,也有很多人為大家解答關于pos機字體下載的問題,今天pos機之家(www.rcqwhg.com)為大家整理了關于這方面的知識,讓我們一起來看下吧!
本文目錄一覽:
1、pos機字體下載
pos機字體下載
1)實驗平臺:正點原子水星 STM32F4/F7 開發(fā)板
2)摘自《STM32F7 開發(fā)指南(HAL 庫版)》關注官方微信號公眾號,獲取更多資料:正點原子
3)全套實驗源碼+手冊+視頻下載地址:http://www.openedv.com/thread-13912-1-1.html
第四十六章 漢字顯示實驗
漢字顯示在很多單片機系統(tǒng)都需要用到,少則幾個字,多則整個漢字庫的支持,更有甚者
還要支持多國字庫,那就更麻煩了。本章,我們將向大家介紹,如何用 STM32F767 控制 LCD
顯示漢字。在本章中,我們將使用外部 SPI FLASH 來存儲字庫,并可以通過 SD 卡更新字庫。
STM32F767 讀取存在 SPI FLASH 里面的字庫,然后將漢字顯示在 LCD 上面。本章分為如下幾
個部分:
46.1 漢字顯示原理簡介
46.2 硬件設計
46.3 軟件設計
46.4 下載驗證
46.1 漢字顯示原理簡介
常用的漢字內碼系統(tǒng)有 GB2312,GB13000,GBK,BIG5(繁體)等幾種,其中 GB2312
支持的漢字僅有幾千個,很多時候不夠用,而 GBK 內碼不僅完全兼容 GB2312,還支持了繁體
字,總漢字數有 2 萬多個,完全能滿足我們一般應用的要求。
本實例我們將制作三個 GBK 字庫,制作好的字庫放在 SD 卡里面,然后通過 SD 卡,將字
庫文件復制到外部 FLASH 芯片 W25Q256 里,這樣,W25Q256 就相當于一個漢字字庫芯片了。
漢字在液晶上的顯示原理與前面顯示字符的是一樣的。漢字在液晶上的顯示其實就是一些
點的顯示與不顯示,這就相當于我們的筆一樣,有筆經過的地方就畫出來,沒經過的地方就不
畫,我們以 12*12 的漢字為例,假設其取模方向為從上到下,從左到右的方向取模,且高位在
前,那么其取模原理如圖 46.1.1 所示:
圖 46.1.1 從上到下,從左到右取模原理
圖中,我們取模的時候,從最左上方的點開始取(從上到下,從左到右),且高位在前(bit7
在表示第一個位),那么第一個字節(jié)就是:0X11(1,表示淺藍色的點,即要畫出來的點,0
則表示不要畫出來),第二個字節(jié)是:0X10,第三個字節(jié)(到第二列了,每列 2 個字節(jié))是:
0X1E……,依次類推,一個 12*12 的漢字,總共有 12 列,每列 2 個字節(jié),總共需要 24 個字節(jié)
來表示。
在顯示的時候,我們只需要讀取這個漢字的點陣數據(12*12 字體,一個漢字的點陣數據
為 24 個字節(jié)),然后將這些數據,按取模方式,反向解析出來(坐標要處理好),每個字節(jié),
是 1 的位,就畫出來,不是 1 的位,就忽略,這樣,就可以顯示出這個漢字了。
所以要顯示漢字,我們首先要知道漢字的點陣數據,這些數據可以由專門的軟件來生成。
知道顯示了一個漢字,就可以推及整個漢字庫了。漢字在各種文件里面的存儲不是以點陣數據
的形式存儲的(否則那占用的空間就太大了),而是以內碼的形式存儲的,就是
GB2312/GBK/BIG5 等這幾種的一種,每個漢字對應著一個內碼,在知道了內碼之后再去字庫
里面查找這個漢字的點陣數據,然后在液晶上顯示出來。這個過程我們是看不到,但是計算機
是要去執(zhí)行的。
單片機要顯示漢字也與此類似:漢字內碼(GBK/GB2312)→查找點陣庫→解析→顯示。
所以只要我們有了整個漢字庫的點陣,就可以把電腦上的文本信息在單片機上顯示出來了。
這里我們要解決的最大問題就是制作一個與漢字內碼對得上號的漢字點陣庫。而且要方便單片
機的查找。每個 GBK 碼由 2 個字節(jié)組成,第一個字節(jié)為 0X81~0XFE,第二個字節(jié)分為兩部分,
一是 0X40~0X7E,二是 0X80~0XFE。其中與 GB2312 相同的區(qū)域,字完全相同。
我們把第一個字節(jié)代表的意義稱為區(qū),那么 GBK 里面總共有 126 個區(qū)(0XFE-0X81+1),
每個區(qū)內有 190 個漢字(0XFE-0X80+0X7E-0X40+2),總共就有 126*190=23940 個漢字。我
們的點陣庫只要按照這個編碼規(guī)則從 0X8140 開始,逐一建立,每個區(qū)的點陣大小為每個漢字
所用的字節(jié)數*190。這樣,我們就可以得到在這個字庫里面定位漢字的方法:
當 GBKL<0X7F 時:Hp=((GBKH-0x81)*190+GBKL-0X40)*(size*2);
當 GBKL>0X80 時:Hp=((GBKH-0x81)*190+GBKL-0X41)*(size*2);
其中 GBKH、GBKL 分別代表 GBK 的第一個字節(jié)和第二個字節(jié)(也就是高位和低位),size
代表漢字字體的大小(比如 16 字體,12 字體等),Hp 則為對應漢字點陣數據在字庫里面的起
始地址(假設是從 0 開始存放)。
這樣我們只要得到了漢字的 GBK 碼,就可以顯示這個漢字了。從而實現漢字在液晶上的
顯示。
上一章,我們提到要用 cc936.c,以支持長文件名,但是 cc936.c 文件里面的兩個數組太大
了(172KB),直接刷在單片機里面,太占用 flash 了,所以我們必須把這兩個數組存放在外部
flash。cc936 里面包含的兩個數組 oem2uni 和 uni2oem 存放 unicode 和 gbk 的互相轉換對照表,
這兩個數組很大,這里我們利用 ALIENTEK 提供的一個 C 語言數組轉 BIN(二進制)的軟件:
C2B 轉換助手 V1.1.exe,將這兩個數組轉為 BIN 文件,我們將這兩個數組拷貝出來存放為一個
新的文本文件,假設為 UNIGBK.TXT,然后用 C2B 轉換助手打開這個文本文件,如圖 46.1.2
所示:
圖 46.1.2 C2B 轉換助手
然后點擊轉換,就可以在當前目錄下(文本文件所在目錄下)得到一個 UNIGBK.bin 的文
件。這樣就完成將 C 語言數組轉換為.bin 文件,然后只需要將 UNIGBK.bin 保存到外部 FLASH
就實現了該數組的轉移。
在 cc936.c 里面,主要是通過 ff_convert 調用這兩個數組,實現 UNICODE 和 GBK 的互轉,
該函數原代碼如下:
WCHAR ff_convert ( /* Converted code, 0 means conversion error */WCHAR src, /* Character code to be converted */UINTdir/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */){const WCHAR *p;WCHAR c;int i, n, li, hi;if (src < 0x80) {/* ASCII */c = src;} else {if (dir) {/* OEMCP to unicode */p = oem2uni;hi = sizeof(oem2uni) / 4 - 1;} else {/* Unicode to OEMCP */p = uni2oem;hi = sizeof(uni2oem) / 4 - 1;}li = 0;for (n = 16; n; n--) {i = li + (hi - li) / 2;if (src == p[i * 2]) break;if (src > p[i * 2]) li = i;else hi = i;}c = n ? p[i * 2 + 1] : 0;}return c;}
此段代碼,通過二分法(16 階)在數組里面查找 UNICODE(或 GBK)碼對應的 GBK(或
UNICODE)碼。當我們將數組存放在外部 flash 的時候,將該函數修改為:
WCHAR ff_convert ( /* Converted code, 0 means conversion error */WCHAR src,/* Character code to be converted */UINTdir/* 0: Unicode to OEMCP, 1: OEMCP to Unicode */){WCHAR t[2];WCHAR c;u32 i, li, hi;u16 n;u32 gbk2uni_offset=0;if (src < 0x80)c = src;//ASCII,直接不用轉換.else{if(dir) gbk2uni_offset=ftinfo.ugbksize/2;//GBK 2 UNICODEelse gbk2uni_offset=0;//UNICODE 2 GBK/* Unicode to OEMCP */hi=ftinfo.ugbksize/2;//對半開.hi =hi / 4 - 1;li = 0;for (n = 16; n; n--){i = li + (hi - li) / 2;W25QXX_Read((u8*)&t,ftinfo.ugbkaddr+i*4+gbk2uni_offset,4);//讀出 4 個字節(jié)if (src == t[0]) break;if (src > t[0])li = i;else hi = i;}c = n ? t[1] : 0;}return c;}
代碼中的 ftinfo.ugbksize 為我們剛剛生成的 UNIGBK.bin 的大小,而 ftinfo.ugbkaddr 是我們
存放 UNIGBK.bin 文件的首地址。這里同樣采用的是二分法查找,關于 cc936.c 的修改,我們就
介紹到這。
字庫的生成,我們要用到一款軟件,由易木雨軟件工作室設計的點陣字庫生成器 V3.8。該
軟件可以在 WINDOWS 系統(tǒng)下生成任意點陣大小的 ASCII,GB2312(簡體中文)、GBK(簡體中
文)、BIG5(繁體中文)、HANGUL(韓文)、SJIS(日文)、Unicode 以及泰文,越南文、俄文、烏克
蘭文,拉丁文,8859 系列等共二十幾種編碼的字庫,不但支持生成二進制文件格式的文件,也
可以生成 BDF 文件,還支持生成圖片功能,并支持橫向,縱向等多種掃描方式,且掃描方式
可以根據用戶的需求進行增加。該軟件的界面如圖 46.1.3 所示:
圖 46.1.3 點陣字庫生成器默認界面
要生成 16*16 的 GBK 字庫,則選擇:936 中文 PRC GBK,字寬和高均選擇 16,字體大小
選擇 12,然后模式選擇縱向取模方式二(從上到下,從左到右,且字節(jié)高位在前,低位在后),
最后點擊創(chuàng)建,就可以開始生成我們需要的字庫了(.DZK 文件,在生成完以后,我們手動修改
后綴為.fon)。具體設置如圖 46.1.4 所示:
圖 46.1.4 生成 GBK16*16 字庫的設置方法
注意:電腦端的字體大小與我們生成點陣大小的關系為:
fsize=dsize*6/8
其中,fsize 是電腦端字體大小,dsize 是點陣大小(12、16、24、32 等)。所以 16*16 點陣
大小對應的是 12 字體。
生成完以后,我們把文件名和后綴改成:GBK16.FON(這里是手動修改后綴?。。?。同樣的
方法,生成 12*12 的點陣庫(GBK12.FON)、24*24 的點陣庫(GBK24.FON)和 32*32 的點陣
庫(GBK32.FON),總共制作 4 個字庫。
另外,該軟件還可以生成其他很多字庫,字體也可選,大家可以根據自己的需要按照上面
的方法生成即可。該軟件的詳細介紹請看軟件自帶的《點陣字庫生成器說明書》,關于漢字顯示
原理,我們就介紹到這。
46.2 硬件設計
本章實驗功能簡介:開機的時候先檢測 W25Q256 中是否已經存在字庫,如果存在,則按
次序顯示漢字(四種字體都顯示)。如果沒有,則檢測 SD 卡和文件系統(tǒng),并查找 SYSTEM 文件
夾下的 FONT 文件夾,在該文件夾內查找 UNIGBK.BIN、GBK12.FON、GBK16.FON、
GBK24.FON 和 GBK32.FON(這幾個文件的由來,我們前面已經介紹了)。在檢測到這些文
件之后,就開始更新字庫,更新完畢才開始顯示漢字。通過按按鍵 KEY0,可以強制更新字庫。
同樣我們也是用 DS0 來指示程序正在運行。
所要用到的硬件資源如下:
1) 指示燈 DS0
2) KEY0 按鍵
3) 串口
4) LCD 模塊
5) SD 卡
6) SPI FLASH
這幾部分分,在之前的實例中都介紹過了,我們在此就不介紹了。
46.3 軟件設計
打開本章實驗目錄可以看到,首先在工程根目錄文件夾下面新建了一個 TEXT 的文件夾。
在 TEXT 文件夾下新建 fontupd.c、fontupd.h、text.c、text.h 這 4 個文件。同時,我們在實驗工
程中新建了 TEXT 分組,將新建的源文件加入到了分組之下,并將頭文件包含路徑加入到了工
程的 PATH 中。
打開 fontupd.c,代碼如下:
//字庫區(qū)域占用的總扇區(qū)數大小(4 個字庫+unigbk 表+字庫信息=6302984 字節(jié),約占 1539 個W25QXX 扇區(qū),一個扇區(qū) 4K 字節(jié))#define FONTSECSIZE1539//字庫存放起始地址#define FONTINFOADDR 1024*1024*25//開發(fā)板是從 25M 地址以后開始存放字庫//前面 25M 被 fatfs 占用了,25M 以后緊跟 4 個字庫+UNIGBK.BIN,總大//小 6.01M,被字庫占用了,不能動! 31.01M 以后,用戶可以自由使用.//用來保存字庫基本信息,地址,大小等_font_info ftinfo;//字庫存放在磁盤中的路徑u8*const GBK_PATH[5]={"/SYSTEM/FONT/UNIGBK.BIN",//UNIGBK.BIN 的存放位置"/SYSTEM/FONT/GBK12.FON", //GBK12 的存放位置"/SYSTEM/FONT/GBK16.FON", //GBK16 的存放位置"/SYSTEM/FONT/GBK24.FON", //GBK24 的存放位置"/SYSTEM/FONT/GBK32.FON", //GBK32 的存放位置};//更新時的提示信息u8*const UPDATE_REMIND_TBL[5]={"Updating UNIGBK.BIN", //提示正在更新 UNIGBK.bin"Updating GBK12.FON",//提示正在更新 GBK12"Updating GBK16.FON",//提示正在更新 GBK16"Updating GBK24.FON",//提示正在更新 GBK24"Updating GBK32.FON",//提示正在更新 GBK32};//顯示當前字體更新進度//x,y:坐標//size:字體大小//fsize:整個文件大小//pos:當前文件指針位置u32 fupd_prog(u16 x,u16 y,u8 size,u32 fsize,u32 pos){…//此處省略部分代碼}//更新某一個//x,y:坐標//size:字體大小//fxpath:路徑//fx:更新的內容 0,ungbk;1,gbk12;2,gbk16;3,gbk24;4,gbk32;//返回值:0,成功;其他,失敗.u8 updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx){u32 flashaddr=0;FIL * fftemp;u8 *tempbuf;u8 res;u16 bread;u32 offx=0;u8 rval=0;fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配內存if(fftemp==NULL)rval=1;tempbuf=mymalloc(SRAMIN,4096);//分配 4096 個字節(jié)空間if(tempbuf==NULL)rval=1;res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ);if(res)rval=2;//打開文件失敗if(rval==0){switch(fx){case 0://更新 UNIGBK.BINftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo);//信息頭之后,緊跟 UNIGBK 轉換碼表ftinfo.ugbksize=fftemp->fsize;//UNIGBK 大小flashaddr=ftinfo.ugbkaddr;break;case 1:ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize;//UNIGBK 之后,緊跟 GBK12 字庫ftinfo.gbk12size=fftemp->fsize; //GBK12 字庫大小flashaddr=ftinfo.f12addr;//GBK12 的起始地址break;case 2:ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size;//GBK12 之后,緊跟 GBK16 字庫ftinfo.gbk16size=fftemp->fsize; //GBK16 字庫大小flashaddr=ftinfo.f16addr;//GBK16 的起始地址break;case 3:ftinfo.f24addr=ftinfo.f16addr+ftinfo.gbk16size;//GBK16 之后,緊跟 GBK24 字庫ftinfo.gbk24size=fftemp->fsize;//GBK24 字庫大小flashaddr=ftinfo.f24addr;//GBK24 的起始地址break;case 4:ftinfo.f32addr=ftinfo.f24addr+ftinfo.gbk24size;//GBK24 之后,緊跟 GBK32 字庫ftinfo.gbk32size=fftemp->fsize;//GBK32 字庫大小flashaddr=ftinfo.f32addr;//GBK32 的起始地址break;}while(res==FR_OK)//死循環(huán)執(zhí)行{res=f_read(fftemp,tempbuf,4096,(UINT *)&bread);//讀取數據if(res!=FR_OK)break;//執(zhí)行錯誤W25QXX_Write(tempbuf,offx+flashaddr,4096); //從 0 開始寫入 4096 個數據offx+=bread;fupd_prog(x,y,size,fftemp->fsize,offx);//進度顯示if(bread!=4096)break;//讀完了.}f_close(fftemp);}myfree(SRAMIN,fftemp);//釋放內存myfree(SRAMIN,tempbuf); //釋放內存return res;}//更新字體文件,UNIGBK,GBK12,GBK16,GBK24,GBK32 一起更新//x,y:提示信息的顯示地址//size:字體大小//src:字庫來源磁盤."0:",SD 卡;"1:",FLASH 盤,"2:",U 盤.//提示信息字體大小//返回值:0,更新成功;//其他,錯誤代碼.u8 update_font(u16 x,u16 y,u8 size,u8* src){u8 *pname;u32 *buf;u8 res=0;u16 i,j;FIL *fftemp;u8 rval=0;res=0XFF;ftinfo.fontok=0XFF;pname=mymalloc(SRAMIN,100); //申請 100 字節(jié)內存buf=mymalloc(SRAMIN,4096); //申請 4K 字節(jié)內存fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配內存if(buf==NULL||pname==NULL||fftemp==NULL){myfree(SRAMIN,fftemp);myfree(SRAMIN,pname);myfree(SRAMIN,buf);return 5;//內存申請失敗}for(i=0;i<5;i++)//先查找文件 UNIGBK,GBK12,GBK16,GBK24,GBK32 是否正常{strcpy((char*)pname,(char*)src);//copy src 內容到 pnamestrcat((char*)pname,(char*)GBK_PATH[i]);//追加具體文件路徑res=f_open(fftemp,(const TCHAR*)pname,FA_READ);//嘗試打開if(res){rval|=1<<7; //標記打開文件失敗break;//出錯了,直接退出}}myfree(SRAMIN,fftemp);//釋放內存if(rval==0)//字庫文件都存在.{LCD_ShowString(x,y,240,320,size,"Erasing sectors... ");//提示正在擦除扇區(qū)for(i=0;i<FONTSECSIZE;i++)//先擦除字庫區(qū)域,提高寫入速度{fupd_prog(x+20*size/2,y,size,FONTSECSIZE,i);//進度顯示W25QXX_Read((u8*)buf,((FONTINFOADDR/4096)+i)*4096,4096);//讀出整個扇區(qū)的內容for(j=0;j<1024;j++)//校驗數據{if(buf[j]!=0XFFFFFFFF)break;//需要擦除}if(j!=1024)W25QXX_Erase_Sector((FONTINFOADDR/4096)+i);//需要擦除的扇區(qū)}for(i=0;i<5;i++)//依次更新 UNIGBK,GBK12,GBK16,GBK24,GBK32{LCD_ShowString(x,y,240,320,size,UPDATE_REMIND_TBL[i]);strcpy((char*)pname,(char*)src);//copy src 內容到 pnamestrcat((char*)pname,(char*)GBK_PATH[i]);//追加具體文件路徑res=updata_fontx(x+20*size/2,y,size,pname,i); //更新字庫if(res){myfree(SRAMIN,buf);myfree(SRAMIN,pname);return 1+i;}}//全部更新好了ftinfo.fontok=0XAA;W25QXX_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//保存字庫信息}myfree(SRAMIN,pname);//釋放內存myfree(SRAMIN,buf);return rval;//無錯誤.}//初始化字體//返回值:0,字庫完好.//其他,字庫丟失u8 font_init(void){u8 t=0;W25QXX_Init();while(t<10)//連續(xù)讀取 10 次,都是錯誤,說明確實是有問題,得更新字庫了{t++;W25QXX_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//讀出 ftinfo 結構體數據if(ftinfo.fontok==0XAA)break;delay_ms(20);}if(ftinfo.fontok!=0XAA)return 1;return 0;}
此部分代碼主要用于字庫的更新操作(包含 UNIGBK 的轉換碼表更新),其中 ftinfo 是我
們在 fontupd.h 里面定義的一個結構體,用于記錄字庫首地址及字庫大小等信息。因為我們將
W25Q256 的前 25M 字節(jié)給 FATFS 管理(用做本地磁盤),隨后,緊跟字庫結構體、UNIGBK.bin、
和三個字庫,這部分內容首地址是:(1024*12)*1024,大小約 6.01M,最后 W25Q256 還剩下約
0.99M 給用戶自己用。
接下來我們打開 fontupd.h 文件代碼如下:
extern u32 FONTINFOADDR; //字體信息保存地址,占 41 個字節(jié),第 1 個字節(jié)用于標記字庫
//是否存在.后續(xù)每 8 個字節(jié)一組,分別保存起始地址和文件大小//字庫信息結構體定義//用來保存字庫基本信息,地址,大小等__packed typedef struct{u8 fontok;//字庫存在標志,0XAA,字庫正常;其他,字庫不存在u32 ugbkaddr;//unigbk 的地址u32 ugbksize;//unigbk 的大小u32 f12addr;//gbk12 地址u32 gbk12size;//gbk12 的大小u32 f16addr;//gbk16 地址u32 gbk16size;//gbk16 的大小u32 f24addr;//gbk24 地址u32 gbk24size;//gbk24 的大小u32 f32addr;//gbk32 地址u32 gbk32size;//gbk32 的大小}_font_info;extern _font_info ftinfo; //字庫信息結構體u32 fupd_prog(u16 x,u16 y,u8 size,u32 fsize,u32 pos);//顯示更新進度u8 updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx);//更新指定字庫u8 update_font(u16 x,u16 y,u8 size,u8* src);//更新全部字庫u8 font_init(void);//初始化字庫#endif這里,我們可以看到 ftinfo 的結構體定義,總共占用 41 個字節(jié),第一個字節(jié)用來標識字庫是否 OK,其他的用來記錄地址和文件大小。接下來打開 text.c 文件,代碼如下://code 字符指針開始//從字庫中查找出字模//code 字符串的開始地址,GBK 碼//mat 數據存放地址 (size/8+((size%8)?1:0))*(size) bytes 大小//size:字體大小void Get_HzMat(unsigned char *code,unsigned char *mat,u8 size){unsigned char qh,ql;unsigned char i;unsigned long foffset;u8 csize=(size/8+((size%8)?1:0))*(size);//得到字體一個字符對應點陣集所占的字節(jié)數qh=*code;ql=*(++code);if(qh<0x81||ql<0x40||ql==0xff||qh==0xff)//非 常用漢字{ for(i=0;i<csize;i++)*mat++=0x00;//填充滿格 return; //結束訪問}if(ql<0x7f)ql-=0x40;//注意!else ql-=0x41;qh-=0x81;foffset=((unsigned long)190*qh+ql)*csize; //得到字庫中的字節(jié)偏移量switch(size){case 12:W25QXX_Read(mat,foffset+ftinfo.f12addr,csize);break;case 16:W25QXX_Read(mat,foffset+ftinfo.f16addr,csize);break;case 24:W25QXX_Read(mat,foffset+ftinfo.f24addr,csize);break;case 32:W25QXX_Read(mat,foffset+ftinfo.f32addr,csize);break;}}//顯示一個指定大小的漢字//x,y :漢字的坐標//font:漢字 GBK 碼//size:字體大小//mode:0,正常顯示,1,疊加顯示void Show_Font(u16 x,u16 y,u8 *font,u8 size,u8 mode){u8 temp,t,t1;u16 y0=y;u8 dzk[128];u8 csize=(size/8+((size%8)?1:0))*(size);//得到字體一個字符對應點陣集所占的字節(jié)數if(size!=12&&size!=16&&size!=24&&size!=32)return;//不支持的 sizeGet_HzMat(font,dzk,size); //得到相應大小的點陣數據for(t=0;t<csize;t++){temp=dzk[t];//得到點陣數據for(t1=0;t1<8;t1++){if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);temp<<=1;y++;if((y-y0)==size){y=y0;x++;break;}}}}//在指定位置開始顯示一個字符串//支持自動換行//(x,y):起始坐標//width="360px",height="auto" />
此部分代碼總共有 4 個函數,我們省略了兩個函數(Show_Str_Mid 和 Show_Str)的代碼,
另外兩個函數,Get_HzMat 函數用于獲取 GBK 碼對應的漢字字庫,通過我們 47.1 節(jié)介紹的辦
法,在外部 flash 查找字庫,然后返回對應的字庫點陣。Show_Font 函數用于在指定地址顯示一
個指定大小的漢字,采用的方法和 LCD_ShowChar 所采用的方法一樣,都是畫點顯示,這里就
不細說了。
text.h 頭文件是一些函數申明,我們這里不細說了。
前面提到我們對 cc936.c 文件做了修改,我們將其命名為 mycc936.c,并保存在 exfuns 文件
夾下,將工程 FATFS 組下的 cc936.c 刪除,然后重新添加 mycc936.c 到 FATFS 組下,mycc936.c
的源碼就不貼出來了,其實就是在 cc936.c 的基礎上去掉了兩個大數組,然后對 ff_convert 進行
了修改,詳見本例程源碼。
最后,我們看看 main 函數如下:
int main(void){u32 fontcnt;u8 i,j;u8 fontx[2]; //gbk 碼u8 key,t; Cache_Enable(); //打開 L1-Cache MPU_Memory_Protection(); //保護相關存儲區(qū)域 HAL_Init(); //初始化 HAL 庫 Stm32_Clock_Init(432,25,2,9); //設置時鐘,216Mhz delay_init(216); //延時初始化uart_init(115200); //串口初始化 LED_Init();//初始化 LED KEY_Init(); //初始化按鍵 SDRAM_Init(); //初始化 SDRAM LCD_Init();//初始化 LCDW25QXX_Init();//初始化 W25Q256 my_mem_init(SRAMIN);//初始化內部內存池 my_mem_init(SRAMEX); //初始化外部 SDRAM 內存池 my_mem_init(SRAMDTCM); //初始化內部 DTCM 內存池 exfuns_init(); //為 fatfs 相關變量申請內存 f_mount(fs[0],"0:",1); //掛載 SD 卡 f_mount(fs[1],"1:",1); //掛載 SPI FLASH. f_mount(fs[2],"2:",1); //掛在 NAND FLASHwhile(font_init())//檢查字庫{ UPD:LCD_Clear(WHITE);//清屏POINT_COLOR=RED;//設置字體為紅色LCD_ShowString(30,50,200,16,16,"Apollo STM32F4/F7");while(SD_Init())//檢測 SD 卡{ LCD_ShowString(30,70,200,16,16,"SD Card Failed!"); delay_ms(200); LCD_Fill(30,70,200+30,70+16,WHITE); delay_ms(200);}LCD_ShowString(30,70,200,16,16,"SD Card OK");LCD_ShowString(30,90,200,16,16,"Font Updating...");key=update_font(20,110,16,"0:");//更新字庫while(key)//更新失敗{LCD_ShowString(30,110,200,16,16,"Font Update Failed!");delay_ms(200);LCD_Fill(20,110,200+20,110+16,WHITE);delay_ms(200);}LCD_ShowString(30,110,200,16,16,"Font Update Success! ");delay_ms(1500);LCD_Clear(WHITE);//清屏}POINT_COLOR=RED;Show_Str(30,30,200,16,"水星 STM32F4/F7 開發(fā)板",16,0);Show_Str(30,50,200,16,"GBK 字庫測試程序",16,0);Show_Str(30,70,200,16,"正點原子@ALIENTEK",16,0);Show_Str(30,90,200,16,"2016 年 7 月 15 日",16,0);Show_Str(30,110,200,16,"按 KEY0,更新字庫",16,0);POINT_COLOR=BLUE;Show_Str(30,130,200,16,"內碼高字節(jié):",16,0);Show_Str(30,150,200,16,"內碼低字節(jié):",16,0);Show_Str(30,170,200,16,"漢字計數器:",16,0);Show_Str(30,200,200,32,"對應漢字為:",32,0);Show_Str(30,232,200,24,"對應漢字為:",24,0);Show_Str(30,256,200,16,"對應漢字(16*16)為:",16,0);Show_Str(30,272,200,12,"對應漢字(12*12)為:",12,0);while(1){fontcnt=0;for(i=0x81;i<0xff;i++){fontx[0]=i;LCD_ShowNum(118,150,i,3,16);//顯示內碼高字節(jié)for(j=0x40;j<0xfe;j++){if(j==0x7f)continue;fontcnt++;LCD_ShowNum(118,150,j,3,16); //顯示內碼低字節(jié)LCD_ShowNum(118,170,fontcnt,5,16);//漢字計數顯示fontx[1]=j;Show_Font(30+176,200,fontx,32,0);Show_Font(30+132,232,fontx,24,0);Show_Font(30+144,256,fontx,16,0);Show_Font(30+108,272,fontx,12,0);t=200;while(t--)//延時,同時掃描按鍵{delay_ms(1);key=KEY_Scan(0);if(key==KEY0_PRES)goto UPD;}LED0_Toggle;}}}}
此部分代碼就實現了我們在硬件描述部分所描述的功能,至此整個軟件設計就完成了。這
節(jié)有太多的代碼,而且工程也增加了不少,我們來看看工程的截圖吧,整個工程截圖如圖 46.3.1
所示:
圖 46.3.1 工程建成截圖
46.4 下載驗證
在代碼編譯成功之后,我們通過下載代碼到 ALIENTEK 水星 STM32 開發(fā)板上,可以看到
LCD 開始顯示漢字及漢字內碼,如圖 46.4.1 所示:
圖 46.4.1 漢字顯示實驗顯示效果
一開始就顯示漢字,是因為 ALIENTEK 水星 STM32F767 開發(fā)板在出廠的時候都是測試過
的,里面刷了綜合測試程序,已經把字庫寫入到了 W25Q256 里面,所以并不會提示更新字庫。
如果你想要更新字庫,那么則必須先找一張 SD 卡,把:光盤\\5,SD 卡根目錄文件 文件夾下
面的 SYSTEM 文件夾拷貝到 SD 卡根目錄下,插入開發(fā)板,并按復位,之后,在顯示漢字的時
候,按下 KEY0,就可以開始更新字庫了。
字庫更新界面如圖 46.4.2 所示:
圖 46.4.2 漢字字庫更新界面
我們還可以通過 USMART 來測試該實驗,將 Show_Str 函數加入 USMART 控制(方法前
面已經講了很多次了),就可以通過串口調用該函數,在屏幕上顯示任何你想要顯示的漢字了,
有興趣的朋友可以測試一下。
以上就是關于pos機字體下載,F7水星開發(fā)板資料連載第四十六章 漢字顯示實驗的知識,后面我們會繼續(xù)為大家整理關于pos機字體下載的知識,希望能夠幫助到大家!