我的小车调试进度之:实现OLED显示(汉字+英文+图片)

小车调试进度三更~


写在前面: 我的主控板上OLED部分片选端CS是直接接地的,底层中除汉字显示和图片显示的部分我参照的是:【常用模块】OLED显示模块(原理讲解、STM32实例操作),博主关于原理方面讲解地也比较详细,里面也有一些基本的底层,比如显示字符、数字、字符串都有,下面我只贴出汉字显示和图片显示部分的代码,汉字显示部分我用了两种方法,emmm,都会贴出来。
我的小车调试进度之:实现OLED显示(汉字+英文+图片)_第1张图片


  • 汉字显示方法一(这个方法是探索阶段的方法,有弊端但也可以借鉴)
  1. 首先肯定要取模(取模软件用的是Pctolcd2002),具体的取模步骤可以参照:
    OLED取模(汉字加图片),与博客有一点不同是,选项设置里的后缀和前缀我没有去掉,具体代码过长,我只截取一部分:
    我的小车调试进度之:实现OLED显示(汉字+英文+图片)_第2张图片
  2. 具体代码:
//显示一个汉字
void OLED_ShowGBK(u8 x, u8 y, u8 num, u8 size,u8 mode)
{
    u8 temp,t,t1;
    u8 y0=y;
    u8 csize=(size/8 + ((size%8)?1:0)) * size;     //得到字体一个字符对应点阵集所占的字节数
              
    for(t=0;t>=1;
            y++;
            if((y-y0)==size)
            {
                y=y0;
                x++;
                break;
            }
        }    
    } 	
}

//显示中文字符串
//x,y:起点坐标  
//*p:字符串起始地址
//用1616字体
//i的取值取最长的中文字符串的长度
void OLED_ShowChinese(u8 x,u8 y,const int *p)
{
#define MAX_CHIN_POSX 120
#define MAX_CHIN_POSY 49   
    u8 i = 0;
    while(i < 6)
    {       
        if(x>MAX_CHIN_POSX){x=0;y+=16;}
        if(y>MAX_CHIN_POSY){y=x=0;OLED_Clear();}
        OLED_ShowGBK(x+16*i,y,*(p+i),16,1);	 
        i+=1;
    }  
}	

emmm,显示一个汉字的思想与显示字符的思想差不多,主要就是显示中文字符串的函数,我觉得一个一个汉字地显示实在是太过麻烦,就想按照显示字符串的思想来显示中文字符串,但是这就要求*p必须是整形const int *p的,因为显示一个汉字的函数里传进去的参数num是一个整数(0、1、2等等),所以我就定义了一个整形的数组,用来存放需要显示的汉字字符串对应的汉字的数字 (这个数字就是用取模软件生成的字模后面带的数字),额,,感觉是比一个一个显示汉字省事了那么一点点,,,看一下应用:

int mode11[6] = {17,0,1,2,3,16};//【蓝牙模式】
int mode12[6] = {0,1,2,3,18,18};//蓝牙模式
int mode21[6] = {17,4,5,2,3,16};//【寻迹模式】
int mode22[6] = {4,5,2,3,18,18};//寻迹模式
int mode31[6] = {17,6,7,2,3,16};//【调速模式】
int mode32[6] = {6,7,2,3,18,18};//调速模式
int ret11[6] = {17,8,9,16,18,18};//【返回】
int ret12[6] = {8,9,18,18,18,18};//返回

void fun1(void)
{
    OLED_ShowChinese(10,0,mode11);//显示【蓝牙模式】
    OLED_ShowChinese(10,17,mode22);//显示寻迹模式
    OLED_ShowChinese(10,33,mode32);//显示调速模式
    OLED_ShowChinese(10,49,ret12);//显示返回
    OLED_Refresh_Gram();
}

这个方法可以显示汉字字符串了,但是不能显示汉字加上英文的字符串,于是就有了方法二,,,贼好使,通用

  • 汉字显示方法二
  1. 这个方法用到了GB2312编码(每个汉字就对应一个GB2312编码),还需要用到一个字符编码排序软件GB2312,把你想显示的汉字输入到字符编码软件中,然后按照GB2312编码大小排序:
    我的小车调试进度之:实现OLED显示(汉字+英文+图片)_第3张图片
    然后按照排序后的顺序生成字模!!!,一定要按照排序后的顺序,否则就会出现乱码,还要按照这个顺序建立一个GB2312精简汉字库,我们后面要用这个库的序号来索引汉字字模表中的汉字(这里应该就可以理解为什么两个表的汉字一定要对应啦)
    生成字模的方法就按照我贴出的博客里的步骤来就可以,关于GB2312精简汉字库,其实就是一个一维数组,存放每个汉字的GB2312编码,有两种写法:
//第一种
const unsigned short ChsIndex[CHS_TOTAL]={
    0xA1BE, 0xA1BF,0xA3BA,0xB0E6,0xB1BE,0xB5B1,0xB5F7,0xB6C8,0xB7B5,
    0xBAC5,0xBBD8,0xBCA3,0xC0B6,0xC4A3,0xC7B0,0xCABD,0xCBD9,0xD1B0,
    0xD1C0,0xD5DF, 0xD6B5, 0xD7F7};
//精简汉字字符库(顺序是):【】:版本当调度返号回迹蓝模前式速寻牙者值作

//第二种
const unsigned short ChsIndex[CHS_TOTAL]={
    '【','】',';','版','本','当','调','度','返','号','回','迹','蓝',
    '模','前','式','速','寻','牙','者','值','作'
};

第一种是用GB2312编码查询软件查询每个汉字的编码,第二种是直接用单引号获取字符编码,但是第二种方法会产生警告,但这个警告并不影响程序的正常运行。
2. 具体代码:

//显示一个汉字
void OLED_ShowGBK(u8 x, u8 y, u16 index, u8 size,u8 mode)
{
    u8 temp,t1,i;
    u8 y0=y;
              
    for(i=0;i<32;i++)
    {  
        if(size==16) 
            temp = gbk_1616[index*32+i];    //调用1616字体                             
        for(t1=0;t1<8;t1++)
        {
            if(temp&0x80)OLED_DrawPoint(x,y,mode);
            else OLED_DrawPoint(x,y,!mode);
            temp<<=1;
            y++;
            if((y-y0)==size)
            {
                y=y0;
                x++;
                break;
            }
        }    
    } 	
}

/* 二分法查找字符位置; chs-GB2312码; 返回值-汉字索引*/
u16 GetChsIndex(u16 chs)
{
    u16 Index,Min,Max;

    Min = 0;
    Max = CHS_TOTAL-1;
    while(1)
    {
        Index = (Min+Max) / 2;            //二分法查找字符
        if(chs == ChsIndex[Index])
        {
            break; //找到,退出
        }
        else if(chs > ChsIndex[Index])    //未找到时,更新二分点
        {
            Min = Index;
        }
        else
        {
            Max = Index;
        }
        if( (Max-Min) <= 1) //二分点相邻时,作最后的判断
        {
            if(chs == ChsIndex[Min])
            {
                Index = Min;
                break;
            }
            else if(chs == ChsIndex[Max])
            {
                Index = Max;
                break;
            }
            else
            {
                Index = 0; //未找到时,返回0
                break;
            }
        }
    }
    return  Index;
}

//OLED可显示汉字串和字符串以及二者的混合体
void OLEDShowString(u8 x, u8 y, char *str)
{
#define MAX_CHIN_POSX 120
#define MAX_CHIN_POSY 49  
    u16 index,chr;

    while(*str != '\0')
    {
        if(x>MAX_CHIN_POSX){x=0;y+=16;}
        if(y>MAX_CHIN_POSY){y=x=0;OLED_Clear();}
        if(*str > 127) //区分ASCII字符和汉字,编码大于127为汉字
        {
            chr = *str<<8 | *(str+1);                   //获取汉字GB2312码
            index = GetChsIndex(chr);                   //将GB2312编码转换为精简字库中的字符索引
            OLED_ShowGBK(x, y, index, 16,1);
            x += 16;
            str +=2;
        }
        else //编码小于等于127为ASCII码
        {
            OLED_ShowString(x,y,str);
            x += 8;
            str++;
        }
    }
}
  • 显示图片
  1. 图片取模,仍可参考上面给的博客
  2. 关于图片字模字模的存储: 可以用一个二维数组来储存,二维数组的行值用来作为图片的索引值,表示是哪一个图片,如下图,在这个二维数组里我放了三种像素的图片的字模,列值1024是最大像素128*64的图片所生成的字模中16进制数的个数:
    我的小车调试进度之:实现OLED显示(汉字+英文+图片)_第4张图片
  3. 具体代码:
//显示图片(通过改变索引值和图片对应的像素可以显示不同像素的图片)
//x,y:图片的起点坐标
//px,py:图片的像素(与实际取模的图片像素一致)
//index:图片索引
void OLED_ShowBMP(u8 x, u8 y, u8 px, u8 py, u8 index, u8 mode)
{
    u8 temp,t1;
    u16 j,i;
    u8 y0=y;
    
    i = (px/2)*(py/4);
 
    for(j = 0; j < i;j++)
    {
        temp = Image[index][j];    //调用图片                          
        for(t1=0;t1<8;t1++)
        {
            if(temp&0x80)OLED_DrawPoint(x,y,mode);
            else OLED_DrawPoint(x,y,!mode);
            temp<<= 1;
            y++;
            if((y-y0) == py)
            {
                y=y0;
                x++;
                break;
            }
        }
    }
}

你可能感兴趣的:(麦克纳姆轮小车制作)