zoukankan      html  css  js  c++  java
  • 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
    },
    
    //自由添加
    }
  • 相关阅读:
    机器学习读书笔记(六)
    机器学习读书笔记(五)AdaBoost
    机器学习读书笔记(三)决策树基础篇之从相亲说起
    机器学习读书笔记(四)朴素贝叶斯基础篇之网站账号分类
    机器学习读书笔记(二)使用k-近邻算法改进约会网站的配对效果
    机器学习读书笔记(一)k-近邻算法
    大数据集群常见问题总结
    Hadoop、Hbase基本命令及调优方式
    Java多线程优化方法及使用方式
    Linux-RED HAT6.8扩容
  • 原文地址:https://www.cnblogs.com/hexia7935/p/14612443.html
Copyright © 2011-2022 走看看