|
本帖最后由 萊鳥(niǎo) 于 2015-7-21 11:12 編輯
從學(xué)校的時(shí)候?qū)ζ骷杀静幻舾?凡是顯示,基本都用12864,一來(lái)不用花錢(qián)買(mǎi),二來(lái)是操作簡(jiǎn)單,(串行模式)占用io少,顯示內(nèi)容還多,
前段時(shí)間偶然從廢品站買(mǎi)了幾十片5110的lcd,雖然成色很爛,但是價(jià)格便宜,5塊錢(qián)一個(gè),個(gè)個(gè)都能顯示,有點(diǎn)占小便宜的感覺(jué),哈哈
之前就看到很多人玩5110的屏,屏倒是不貴,10元不到,運(yùn)費(fèi)卻要10元了,一直也沒(méi)買(mǎi)過(guò),
剛好這兩天很閑,而且做得轉(zhuǎn)接板也到手了,就把5110的文字顯示學(xué)了一下
以前做的計(jì)價(jià)器樣機(jī),帶字庫(kù)的12864 面積大,使用方便,
})}VESV_%M}}BMK~%FO%2%S.png (447.61 KB, 下載次數(shù): 121)
下載附件
2015-7-21 11:07 上傳
5110價(jià)格便宜,價(jià)格便宜,價(jià)格便宜
nEO_IMG_主圖.jpg (70.82 KB, 下載次數(shù): 132)
下載附件
2015-7-21 11:07 上傳
對(duì)于單片機(jī)來(lái)說(shuō),存儲(chǔ)較小,51的話(huà),內(nèi)置64k,存放3種ASCII點(diǎn)陣,加上 16x16和12x12的中文就基本可以滿(mǎn)足一般的顯示需要,比如上面diy的激光測(cè),
標(biāo)題用16的字體,其他用12的字體,感覺(jué)不算違和,
至于6x8的ASCII可以顯示不太重要的數(shù)據(jù)或者比較長(zhǎng)的數(shù)據(jù),
最后一行的8x12的ascii則可以用來(lái)顯示重要一點(diǎn)的數(shù)據(jù),第一樣就能看到,比如測(cè)距狀態(tài),OK還是ERROR等等
nEO_IMG_20150713_180442.jpg (210.62 KB, 下載次數(shù): 101)
下載附件
2015-7-21 11:10 上傳
5110的lcd控制器的y地址尋址是以字節(jié)為單位的,而不是像x一樣以位為單位,這就導(dǎo)致了,顯示英文比較方便,可以在某一行任意地址顯示,y方向就固定6行好了,
顯示16點(diǎn)陣的字體也方便,因?yàn)橐粋(gè)漢字剛好占據(jù)兩個(gè)y地址,不過(guò)實(shí)際來(lái)看,16的字體顯得太大,和這塊小屏幕不太和諧,而且顯示內(nèi)容少,所以可以選用比較秀氣的12像素字體,效果也很好,但是有個(gè)小問(wèn)題,12像素字體有的筆畫(huà)會(huì)缺失,但是沒(méi)有什么太大影響,比如下圖,順序都不會(huì)影響,缺個(gè)點(diǎn)之類(lèi)的更不用擔(dān)心啦
來(lái)看5110的控制器y地址尋址和12像素字體的關(guān)系,第0,2,4行顯示是沒(méi)問(wèn)題到只不過(guò) 1 3 5行會(huì)空出來(lái)4個(gè)像素,比較常見(jiàn)的取模軟件都是不足8位補(bǔ)足8位的,所以,y1的下半部分就是0,
顯示兩行12的漢字,需要用3個(gè)y地址,把第二行的漢字上移4就可以了,
地址.png (109.31 KB, 下載次數(shù): 120)
下載附件
2015-7-21 11:07 上傳
單獨(dú)來(lái)看y1,它包含了第一行漢字的下半部分,還包含了第二行漢字的上半部分,而且,第二行漢字的上半部分顯示在了y1的下半部分(比較繞口)看圖可以看得出來(lái)
地址 - 副本.png (107.71 KB, 下載次數(shù): 136)
下載附件
2015-7-21 11:07 上傳
不過(guò)這樣看好像就比較清楚了,其實(shí)第二行中文的y方向起始地址還是y1,和第一行漢字的y地址重合,數(shù)據(jù)移位處理即可
地址 - 副本 (2).png (111.8 KB, 下載次數(shù): 130)
下載附件
2015-7-21 11:07 上傳
那就可以使用單片機(jī)的xdata內(nèi)存區(qū)存放交叉區(qū)的緩存數(shù)據(jù),
顯示12像素的漢字,可以顯示4行,
我們把第一行的漢字的y1區(qū)0-83個(gè)地址都存下來(lái),叫做y0ram,
第二行中文的y1區(qū)0-83個(gè)地址都存下來(lái)叫做 y1ram
每當(dāng)顯示到這兩個(gè)地址的時(shí)候,就把這兩個(gè)ram緩存保存下來(lái),
再顯示下一行的時(shí)候進(jìn)行移位沒(méi)然后數(shù)據(jù)或運(yùn)算在寫(xiě)到控制器里,就可以了,
當(dāng)然也可以按照控制器的地址來(lái)劃分,y1就叫y1ram,y3就叫y3ram,這樣在數(shù)據(jù)保存的時(shí)候進(jìn)行移位,而且還節(jié)約了84*2字節(jié)的內(nèi)存,效果是一樣的,
可以用一張圖來(lái)表示
原理.png (402.92 KB, 下載次數(shù): 113)
下載附件
2015-7-21 11:07 上傳
在程序中
原理 - 副本.png (79.09 KB, 下載次數(shù): 119)
下載附件
2015-7-21 11:07 上傳
然后再?gòu)闹骱瘮?shù)里調(diào)用
6ZCYTEO1{0@3@H)J[NZAFEX.png (47.4 KB, 下載次數(shù): 114)
下載附件
2015-7-21 11:07 上傳
再說(shuō)一下字庫(kù)吧,因?yàn)楫吘共皇峭暾嬲淖謳?kù),所以顯示不知尋址來(lái)的,是查表來(lái)的,字庫(kù)呢,分為兩部分呢,一部分是索引,放在后面,一部分是點(diǎn)陣數(shù)據(jù),放前面,比如我查找到"滾"是結(jié)構(gòu)體中第0個(gè)元素索引中
那就調(diào)取播放圖標(biāo)進(jìn)行顯示,其他同理
F8ZX_SQ6N[`"3~8P~%NYU.png (63.56 KB, 下載次數(shù): 111)
下載附件
2015-7-21 11:07 上傳
實(shí)際效果如下
nEO_IMG_WP_20150721_00_32_58_Pro.jpg (87.02 KB, 下載次數(shù): 100)
下載附件
2015-7-21 11:07 上傳
nEO_IMG_WP_20150721_00_23_59_Pro.jpg (87.31 KB, 下載次數(shù): 115)
下載附件
2015-7-21 11:07 上傳
nEO_IMG_WP_20150721_00_22_46_Pro.jpg (75.29 KB, 下載次數(shù): 120)
下載附件
2015-7-21 11:07 上傳
nEO_IMG_WP_20150721_00_22_11_Pro.jpg (80.31 KB, 下載次數(shù): 132)
下載附件
2015-7-21 11:07 上傳
代碼部分,完整版
- /*
- 顯示12*12的字體,任意地址,上下錯(cuò)開(kāi)也解決了
- */
- #include<reg51.h>
- #include"Nokia5110Lcd.h"
- #include "lcd5110font.c"
- #include<intrins.h>
- #define nop() _nop_()
- #define uchar unsigned char
- #define uint unsigned int
- uchar xdata Y0Ram[84]; //第0行漢字的臨時(shí)緩存
- uchar xdata Y1Ram[84];
- uchar xdata Y2Ram[84];
- uchar xdata Y3Ram[84];
- void delay(int t)
- {
- uchar i;
- while (t--)
- {
- for (i=0;i<125;i++)
- {}
- }
- }
- void Lcd5110WriteDta(uchar dat)
- {
- unsigned char i;
- sce=0;
- dc=1;
- for (i=0;i<8;i++)
- {
- if (dat&0x80)
- sdin=1;
- else
- sdin=0;
- dat=dat<<1;
- sclk=0;
- nop();
- sclk=1;
- }
- dc=1;
- sce=1;
- sdin=1;
- }
- void Lcd5110WriteCMD(uchar dat)
- {
- unsigned char i;
- sce=0;
- dc=0;
- for (i=0;i<8;i++)
- {
- if (dat&0x80)
- sdin=1;
- else
- sdin=0;
- dat=dat<<1;
- sclk=0;
- nop();
- sclk=1;
- }
- dc=1;
- sce=1;
- sdin=1;
- }
- /*---------------------------------------
- LCD_init: 3310LCD初始化
- 編寫(xiě)日期:20080918
- ----------------------------------------- */
- void Lcd5110Init(void)
- {
- char i;
- // res=0;
- // delay(10);
- // res=1; //以上三句 不用也行
- Lcd5110WriteCMD(0x21 );//初始化Lcd,功能設(shè)定使用擴(kuò)充指令
- Lcd5110WriteCMD(0xb2 );//設(shè)定液晶偏置電壓
- //Lcd5110WriteCMD(0xc0);//設(shè)定液晶偏置電壓 //調(diào)試用 顯示全黑
- Lcd5110WriteCMD(0x02 );//溫度校正
- Lcd5110WriteCMD(0x13 );//1:48
- Lcd5110WriteCMD(0x20 );//使用基本指令
- Lcd5110WriteCMD(0x0C );//設(shè)定顯示模式,正常顯示
- for (i=0;i<84;i++)
- {
- Y0Ram[i]=Y1Ram[i]=Y2Ram[i]=Y3Ram[i]=0;
- }
- }
- /*-------------------------------------------
- LCD_set_XY: 設(shè)置LCD坐標(biāo)函數(shù)
- 輸入?yún)?shù):X:0-83 Y:0-5
- 編寫(xiě)日期:20080918
- ---------------------------------------------*/
- void Lcd5110SetXY(uchar X,Y)
- {
- Lcd5110WriteCMD(0x40 | Y );// 垂直方向 0-5
- Lcd5110WriteCMD(0x80 | X );// 水平方向0-83
- }
- /*------------------------------------------
- LCD_clear: LCD清屏函數(shù)
- 編寫(xiě)日期:20080918
- --------------------------------------------*/
- void Lcd5110Clear(void)
- {
- unsigned char t;
- unsigned char k;
- Lcd5110SetXY(0,0);
- for (t=0;t<6;t++)
- {
- for (k=0;k<84;k++)
- Lcd5110WriteDta(0x00);
- }
- }
- /*---------------------------------------------
- LCD_write_shu: 顯示8(寬)*16(高)點(diǎn)陣列數(shù)字字母符號(hào)等半角類(lèi)
- addr:寫(xiě)入地址
- row: 第幾行 對(duì)于6*8點(diǎn)陣 實(shí)際5*7留有空邊,字高8個(gè)點(diǎn), 屏幕一共6行 豎著48個(gè)點(diǎn)
- dd:字符
- -----------------------------------------------*/
- void Lcd5110Write6x8AtAddr(uchar row, addr, dat)
- {
- unsigned char i;
- dat=dat-32; //ascii轉(zhuǎn)換為字庫(kù)偏移地址
- Lcd5110SetXY(addr, row-1);// 某行的某個(gè)地址 行1-6地址0-83
- for (i=0; i<6;i++)
- {
- Lcd5110WriteDta(Ascii6x8[dat*6+i]);
- }
- }
- void Lcd5110show6x8AscWithNoAddr(uchar dat)//顯示一個(gè)6*8點(diǎn)陣
- {
- uchar i;
- dat-=32;
- for (i=0; i<6;i++)
- Lcd5110WriteDta(Ascii6x8[dat*6+i]);
- }
- void Lcd5110String6x8(uchar row , addr, uchar *p)
- {
- Lcd5110SetXY(addr, row);// 列,頁(yè)
- while (*p!='\0')
- {
- Lcd5110show6x8AscWithNoAddr(*p++);
- }
- }
- void Lcd5110show8x16AscAtAddr(uchar row,addr, dat)
- {
- uchar i ;
- dat-=32;
- Lcd5110SetXY(addr,row);
- for (i=0; i<8;i++)
- Lcd5110WriteDta(Ascii8x16[dat*16+i]);
- Lcd5110SetXY(addr,row+1);
- for (i=8; i<16;i++)
- Lcd5110WriteDta(Ascii8x16[dat*16+i]);
- }
- /*
- 行 范圍 1-6一共6行,但在行=6的時(shí)候會(huì)顯示不全
- */
- void Lcd5110String8x16(uchar row , addr, uchar *p)
- {
- //不再用8*16的ascii了,直接屏蔽掉,想用的時(shí)候在解除屏蔽即可
- uchar dat;
- while (*p!='\0')
- {
- dat =*p;
- Lcd5110show8x16AscAtAddr(row-1 ,addr, dat);
- *p++;
- addr+=8;
- }
- }
- void Lcd5110DisplayAscii8x12AtAddr(uchar row,addr, dat)
- {
- uchar i, LocalHalfWidth,LocalFullWidth; //半寬字體,全寬字體
- LocalHalfWidth=8;//8*12的字體,光看上面一半8字節(jié)
- LocalFullWidth=16;//8*12的字體,上下兩行就是16字節(jié)
- dat-=32;
- if (row==0)//按照4行顯示,首行為0,地址就是0-3行,不是控制器的地址
- {
- Lcd5110SetXY(addr, row);// 列,頁(yè)
- for (i=0; i<LocalHalfWidth;i++) //上半部分 12個(gè)像素
- {
- Lcd5110WriteDta(Ascii8x12[dat*LocalFullWidth+i]);
- }
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=LocalHalfWidth; i<LocalFullWidth;i++) //下半部分 12個(gè)像素
- {
- Y0Ram[addr+i-LocalHalfWidth]=Ascii8x12[dat*LocalFullWidth+i]; //第0行的下半部分12個(gè)字節(jié)存起來(lái)
- Lcd5110WriteDta(Y0Ram[addr+i-LocalHalfWidth] | Y1Ram[addr+i-LocalHalfWidth]<<4 );
- }
- }
- if (row==1)
- {
- Lcd5110SetXY(addr, row);// 列,頁(yè)
- for (i=0; i<LocalHalfWidth;i++) //上半部分 12個(gè)像素
- {
- Y1Ram[addr+i]=Ascii8x12[dat*LocalFullWidth+i];//第1行上半部分存起來(lái)
- Lcd5110WriteDta(Y1Ram[addr+i]<<4 | Y0Ram[addr+i]);
- }
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=LocalHalfWidth; i<LocalFullWidth;i++) //下半部分 12個(gè)像素
- {
- Lcd5110WriteDta(Ascii8x12[dat*LocalFullWidth+i]<<4 | Ascii8x12[dat*LocalFullWidth+i-LocalHalfWidth]>>4 );
- }
- }
- if (row==2)//按照4行顯示,首行為0,地址就是0-3行,不是控制器的地址
- {
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=0; i<LocalHalfWidth;i++) //上半部分 12個(gè)像素
- {
- Lcd5110WriteDta(Ascii8x12[dat*LocalFullWidth+i]);
- }
- Lcd5110SetXY(addr, row+2);// 列,頁(yè)
- for (i=LocalHalfWidth; i<LocalFullWidth;i++) //下半部分 12個(gè)像素
- {
- Y2Ram[addr+i-LocalHalfWidth]=Ascii8x12[dat*LocalFullWidth+i]; //第0行的下半部分12個(gè)字節(jié)存起來(lái)
- Lcd5110WriteDta(Y2Ram[addr+i-LocalHalfWidth] | Y3Ram[addr+i-LocalHalfWidth]<<4 );
- }
- }
- if (row==3)//按照4行顯示的話(huà),地址就是0-3行
- {
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=0; i<LocalHalfWidth;i++) //上半部分 12個(gè)像素
- {
- Y3Ram[addr+i]=Ascii8x12[dat*LocalFullWidth+i];//第1行上半部分存起來(lái)
- Lcd5110WriteDta(Y3Ram[addr+i]<<4 | Y2Ram[addr+i]);
- }
- Lcd5110SetXY(addr, row+2);// 列,頁(yè)
- for (i=LocalHalfWidth; i<LocalFullWidth;i++) //下半部分 12個(gè)像素
- {
- Lcd5110WriteDta(Ascii8x12[dat*LocalFullWidth+i]<<4 | Ascii8x12[dat*LocalFullWidth+i-LocalHalfWidth]>>4);
- }
- }
- }
- void Lcd5110String8x12(uchar row,addr,uchar *p)
- {
- uchar dat;
- while (*p!='\0')
- {
- dat =*p;
- Lcd5110DisplayAscii8x12AtAddr(row ,addr, dat);
- *p++;
- addr+=8;
- //delay(6000); //調(diào)試用 慢動(dòng)作
- }
- }
- /*---------------------------------------------
- 在某行某地址顯示中文字符,
- -----------------------------------------------*/
- void DispOneChs12x12(uchar row,addr,uchar *p)
- {
- uchar i, LocalHalfWidth,LocalFullWidth; //半寬字體,全寬字體
- if (row==0)//按照4行顯示,首行為0,地址就是0-3行,不是控制器的地址
- {
- Lcd5110SetXY(addr, row);// 列,頁(yè)
- for (i=0; i<12;i++) //上半部分 12個(gè)像素
- {
- Lcd5110WriteDta(p[i]);
- }
- Lcd5110SetXY(addr, row+1);
- /*字體的下半部分需要存儲(chǔ)起來(lái)*/
- for (i=12; i<24;i++) //下半部分 12個(gè)像素
- {
- Y0Ram[addr+i-12]=p[i]; //第0行的下半部分12個(gè)字節(jié)存起來(lái),數(shù)組要保存文字的下半部分和這些數(shù)據(jù)在什么位置 0-83
- Lcd5110WriteDta(Y0Ram[addr+i-12] | Y1Ram[addr+i-12]<<4 );
- }
- }
- if (row==1)
- {
- Lcd5110SetXY(addr, row);// 列,頁(yè)
- for (i=0; i<12;i++) //上半部分 12個(gè)像素
- {
- Y1Ram[addr+i]=p[i];//第1行上半部分存起來(lái)
- Lcd5110WriteDta(Y1Ram[ addr+i]<<4 |Y0Ram[addr+i]);
- }
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=12; i<24;i++) //下半部分 12個(gè)像素
- {
- Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4 );
- }
- }
- if (row==2)//按照4行顯示,首行為0,地址就是0-3行,不是控制器的地址
- {
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=0; i<12;i++) //上半部分 12個(gè)像素
- {
- Lcd5110WriteDta(p[i]);
- }
- Lcd5110SetXY(addr, row+2);
- /*字體的下半部分需要存儲(chǔ)起來(lái)*/
- for (i=12; i<24;i++) //下半部分 12個(gè)像素
- {
- Y2Ram[addr+i-12]=p[i]; //第0行的下半部分12個(gè)字節(jié)存起來(lái),數(shù)組要保存文字的下半部分和這些數(shù)據(jù)在什么位置 0-83
- Lcd5110WriteDta(Y2Ram[addr+i-12] | Y3Ram[addr+i-12]<<4 );
- }
- }
- if (row==3)
- {
- Lcd5110SetXY(addr, row+1);// 列,頁(yè)
- for (i=0; i<12;i++) //上半部分 12個(gè)像素
- {
- Y3Ram[addr+i]=p[i];//第1行上半部分存起來(lái)
- Lcd5110WriteDta(Y3Ram[ addr+i]<<4 |Y2Ram[addr+i]);
- }
- Lcd5110SetXY(addr, row+2);// 列,頁(yè)
- for (i=12; i<24;i++) //下半部分 12個(gè)像素
- {
- Lcd5110WriteDta(p[i]<<4 | p[i-12]>>4 );
- }
- }
- }
- void FindHZ12fromGBK12(uchar row ,addr ,uchar *dat)
- {
- uchar i;
- for (i=0;i<LenthOfGbk12;i++) //索引
- {
- if ( (GBK12[i].Index[0] == dat[0]) && (GBK12[i].Index[1] == dat[1])) break;
- }
- DispOneChs12x12(row,addr,GBK12[i].Matrix);
- }
- void Lcd5110ChString12(uchar row,addr, uchar*dat)
- {
- while (*dat)
- {
- FindHZ12fromGBK12(row,addr,dat);
- addr+=12;//12寬的字體,寫(xiě)完一個(gè)x地址加12
- dat+=2; //dat是索引數(shù)據(jù),一個(gè)漢字的索引由兩個(gè)字節(jié)組成
- }
- }
- //顯示一個(gè) 16*16的漢字,參數(shù)是指針,指向點(diǎn)陣數(shù)組
- void DispOneChs16x16(uchar row,addr,uchar *dat)
- {
- uchar i,j;
- for (j=0; j<2;j++)
- {
- Lcd5110SetXY(addr, row+j);// 列,頁(yè)
- for (i=0; i<16;i++)
- Lcd5110WriteDta(dat[16*j+i]);
- }
- }
- /*從字庫(kù)里 用 漢字的指針 查找一個(gè)漢字 并顯示出來(lái) 調(diào)用上面的函數(shù) */
- void FindHZ16fromGBK16(uchar row,addr, uchar *dat)
- {
- uchar i;
- for (i=0;i<LenthOfGbk16;i++) //索引
- {
- if ( (GBK16[i].Index[0] == dat[0]) && (GBK16[i].Index[1] == dat[1])) break;
- }
- switch (row)
- {
- case 0:
- row=0;
- break;
- case 1:
- row=2;
- break;
- case 2:
- row=4;
- break;
- default:
- break;
- }
- DispOneChs16x16(row,addr,GBK16[i].Matrix);//把這個(gè)漢字顯示出來(lái),指向點(diǎn)陣區(qū)
- }
- //把數(shù)組的漢字顯示出來(lái),傳入的參數(shù)是指針 雙引號(hào)
- void Lcd5110ChString16(uchar row,addr,uchar *dat)
- {
- while (*dat)
- {
- FindHZ16fromGBK16(row,addr,dat);
- addr+=16;//16寬的字體,寫(xiě)完一個(gè)x地址加16
- dat+=2; //dat是索引數(shù)據(jù),一個(gè)漢字的索引由兩個(gè)字節(jié)組成
- }
- }
- /*使用一個(gè)6x8的字體顯示一個(gè)3位整數(shù)*/
- void Lcd5110DispHundredIn6x8(uchar row,addr, int dat)
- {
- Lcd5110SetXY(addr,row);
- Lcd5110show6x8AscWithNoAddr(48+dat/100);
- Lcd5110show6x8AscWithNoAddr(48+dat%100/10);
- Lcd5110show6x8AscWithNoAddr(48+dat%100%10);
- }
- //row,地址,傳入
- void Lcd5110DispHundredIn12x12(uchar row,addr,int dat)
- {
- Lcd5110DisplayAscii8x12AtAddr(row,addr,48+dat/100);
- Lcd5110DisplayAscii8x12AtAddr(row,addr+8,48+dat%100/10);
- Lcd5110DisplayAscii8x12AtAddr(row,addr+16,48+dat%100%10);
- }
復(fù)制代碼
|
評(píng)分
-
查看全部評(píng)分
|