0.96寸OLED模塊-簡述如何修改OLED_ShowChar()函數達到修改顯示字體大小的目的


首先上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
},

//自由添加
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM