首先上OLED_ShowChar()函數
//在指定位置顯示一個字符,包括部分字符 //x:0~127 //y:0~63 //mode:0,反白顯示;1,正常顯示 //size:選擇字體 48/24/32/16/12 void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 Char_Size) { unsigned char c = 0, i = 0; c = chr - ' '; //得到偏移后的值 if (x > Max_Column - 1) {x = 0; y = y + 2;} if (Char_Size == 48) { OLED_Set_Pos(x, y); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i], OLED_DATA); OLED_Set_Pos(x, y + 1); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i +24], OLED_DATA); OLED_Set_Pos(x, y + 2); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i +48], OLED_DATA); OLED_Set_Pos(x, y + 3); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i +72], OLED_DATA); OLED_Set_Pos(x, y + 4); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i +96], OLED_DATA); OLED_Set_Pos(x, y + 5); for (i = 0; i < 24; i++) OLED_WR_Byte(F24X48[c * 144 + i +120], OLED_DATA); } else if(Char_Size == 32) { OLED_Set_Pos(x, y); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i], OLED_DATA); OLED_Set_Pos(x, y+1); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64+ i+16], OLED_DATA); OLED_Set_Pos(x, y+2); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i+32], OLED_DATA); OLED_Set_Pos(x, y+3); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i+48], OLED_DATA); } //F12X24字庫:一行36個, else if (Char_Size == 24) { OLED_Set_Pos(x, y); for (i = 0; i < 12; i++) OLED_WR_Byte(F12X24[c * 36 + i], OLED_DATA); //18*2 OLED_Set_Pos(x, y + 1); for (i = 0; i < 12; i++) OLED_WR_Byte(F12X24[c * 36 + i +12], OLED_DATA); OLED_Set_Pos(x, y + 2); for (i = 0; i < 12; i++) OLED_WR_Byte(F12X24[c * 36 + i +24], OLED_DATA); } else if (Char_Size == 16) { OLED_Set_Pos(x, y); for (i = 0; i < 8; i++) OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA); OLED_Set_Pos(x, y + 1); for (i = 0; i < 8; i++) OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA); } else { OLED_Set_Pos(x, y); for (i = 0; i < 6; i++) OLED_WR_Byte(F6x8[c][i], OLED_DATA); } }
這個函數原來沒有Char_Size == 32這個分支,我在使用過程中需要顯示適中的大小,所以研究了下,完成了16*32字體。
這個函數內能夠顯示的只有ASCALL碼表內的符號,並且字庫內的符號必須要按照ASCALL碼表順序排列,否則顯示出來的不是你想要的。
我之前不懂,為了顯示℃這個符號,隨意在字庫內找了個位置,將℃的對應的值粘貼,結果OLED原本顯示正常的符號“.”變成了“-”,我看下了,這兩個正好是上下關系,所以,一定要按順序寫字庫。
其次是取字符軟件的正確使用,因為沒有人可以請教,一個小問題都要研究好久。
第一是取模方式的設置:
第二是如何取到你想要大小的模,我想要取16*32的模,可是取出來后總覺得有問題,參考已有的字庫,取其他大小的模,發現行數不對。
直到我偶然瞥見這句話“對應英文長寬比xx*xx”
才發現我如果想取16*32,那么紅圈內參數的設置應該是32*32。生成字模后,得到4*16個十六進制數。

因為我手頭其他大小的字體是能正常運行的,我只需要依葫蘆畫瓢的寫32大小的else if 就好了,但是我還是花了不少時間,為了方便大家也為了給將來的自己看,我把分析模仿的過程寫下來。
首先是函數內的第一句話, c = chr - ' '; chr代表你輸入的字符,稍微了解下ASCALL碼就能明白,這是為了得到輸入字符在表內的排名。
16*32字庫是一堆十六進制的數組,一個16*32的字符實際上就是16*32,一共512個像素點的亮滅顯示的,一個16進制數代表8個像素點的亮滅,例如0x51=>01010001,1表示亮,0表示滅。
512/8=64
所以16*32的字符需要64個數來表示。
使用OLED_Set_Pos(x, y);確認起始坐標后,就可以開始逐列逐行的寫入,
for (i = 0; i < 16; i++)
OLED_WR_Byte(F16X32[c * 64 + i], OLED_DATA);
i<16:16這個值怎么得到,因為我們要的是16*32,所以是16,假如你要24*48,那你就需要寫24
c * 64:表示我們所要寫的字符的起始位置
假設我們需要顯示空格,空格在ASCALL碼表內是第0個位置,所以 c = chr - ' ';得到C=0, 我們就從字庫的第0個16進制數開始寫入(所以假如我們字庫的順序不對,就不能正確顯示我們想要的字符)
屏幕寫完一行后,開始寫下一行,x不變,y+1
一行寫16個,我們一共64個,所以需要寫4行
else if(Char_Size == 32) { OLED_Set_Pos(x, y); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i], OLED_DATA); OLED_Set_Pos(x, y+1); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64+ i+16], OLED_DATA); OLED_Set_Pos(x, y+2); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i+32], OLED_DATA); OLED_Set_Pos(x, y+3); for (i = 0; i < 16; i++) OLED_WR_Byte(F16X32[c * 64 + i+48], OLED_DATA); }
我在調試時,忘記了將y+1,最后只顯示了最后一行,雖然當時錯了,但是我知道離成功不遠了。
當然我們日常使用不會只使用ASCALL表內的內容,我們要顯示中文等字符,就需要創建一張新的表。這張表不需要按順序排列。
下面是void OLED_Print(u8 x, u8 y, char *s,u8 size)的函數,可以顯示ASCALL表字符,也可以顯示自己字庫內的字符。
太長了,只截取字體大小為16的部分
void OLED_Print(u8 x, u8 y, char *s,u8 size) { u8 i,k,t,length; u8 c[2]; length = strlen(s);//取字符串總長 if(size==16) { for(k=0; k<length; k++) { if(*(s+k) <= 127){//小於128是ASCII符號 OLED_ShowChar(x,y,*(s+k),16); x += 8;//x坐標右移8 }else if(*(s+k) > 127){//大於127,為漢字,前后兩個組成漢字內碼 c[0]=*(s+k); c[1]=*(s+k+1);//取漢字的內碼 for(i=0;i<sizeof(codeGB_16)/ sizeof(codeGB_16[0]);i++){//查數組 if(c[0] == codeGB_16[i].Index[0]&&c[1] == codeGB_16[i].Index[1]){ //查詢到這個字 OLED_Set_Pos(x,y); for(t=0;t<16;t++) OLED_WR_Byte(codeGB_16[i].Msk[t],OLED_DATA);//寫入字模 OLED_Set_Pos(x,y+1); for(t=16;t<32;t++) OLED_WR_Byte(codeGB_16[i].Msk[t],OLED_DATA); x += 16; k += 1; //漢字占2B,跳過一個 break; } } } } } }
struct typFNT_GB16 codeGB_16[] = // 數據表 16x16 掃描方式:列行式 { "屏",{0x00,0x00,0xFE,0x12,0x92,0xB2,0xD2,0x92,0x92,0x92,0xD2,0xB2,0x9E,0x00,0x00,0x00, 0x40,0x30,0x0F,0x04,0x84,0x64,0x1F,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x00,0x00 }, "保",{0x00,0x80,0x60,0xF8,0x07,0x00,0x3E,0x22,0x22,0xE2,0x22,0x22,0x3E,0x00,0x00,0x00, 0x01,0x00,0x00,0xFF,0x20,0x11,0x09,0x05,0x03,0xFF,0x03,0x05,0x09,0x11,0x20,0x00 }, //自由添加 }
