stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)

stm32汉字字库显示实验与OLED的使用

1.字库的使用

  • GBK字库的简介:

    GBK库的由两部分组成,如下图:
    stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第1张图片

    • 高位从0x81开始是为了兼容ASII字符,因为未扩展的ASII字符是从0-128,即0x00-0x80;
    • 汉字编码均为连个字节,所以在ASII字符显示8 * 16的字符时,汉字为16 * 16;

    这儿需要注意一点,我们使用的编辑器的方式,要与字库的编码方式对应才行(GBK);

    因为在使用字库的过程中是1️⃣从字符的地址访问出它的(2字节)编码(编辑时使用GBK,则为GBK编码),2️⃣再根据这个编码去GBK点阵字库(原子存放在SD卡中,再系统初始化时加载到Flash中以便能快速读取)里找这个编码对应的点阵数组;3️⃣ 最后将这个点阵由OLED屏或LCD屏显示。

    流程和对应点阵地址偏移的计算公式如下图:

    stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第2张图片 stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第3张图片

    注意:GBK编码的第四位跳过了0X7F这个字节。

2.OLED的使用:

1)OLED通用的初始化流程:

不论是使用I2C协议还是SPI协议,或者是6800和8080的并口协议进行通讯,OLED初始化的通用流程都如下图所示:

stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第4张图片

2)原子OLED屏芯片SSD1306的部分指令集

stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第5张图片
  • 注意:当我们发送列地址时,列地址会被拆分成两个字节发送,注意列地址(1个字节)的高四位发送时需要在其前面加上0X10,以便让OLED芯片能识别到我们发送的这个命令是列地址的高四位 ,实际上第四位发送时也加上了0x00,不过,这个0x00加上去没有显示出来而已。

  • 有些驱动芯片是在列地址开始是有偏移量的,如洋桃使用SH1106具有0X02的起始偏移(列地址加上即可)。

  • OLED驱动芯片中,将0.96寸的OLED上的点阵对应成内部的SRAM上的每个位,(纵向下高位的模式)安排字节,即,0.96寸的OLED上是 64*128个像素点,将其8个像素点一行,分成8个大行,对应内部SRAM的8页(B0-B7)一页有128个字节,这128个字节是”竖着放的“,即每个字节对应一列,每个字节中的每个位(bit)对应每个大行中中的1个像素点

    OLED驱动芯片的显示SRAM对应如下:(分页,及下高位取模)

    stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第6张图片

    将每个页放大的下高位取模如下:

    stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第7张图片

  • 因此对于这样的芯片,就有以下两种不同的显示方式:

    • 洋桃的方法:

      显示时,为了方便,不用在不同页之间来回切换,取模方式使用: **从左往右,再从上到下 ** (因为从左往右在同一页) 纵向取模下高位 。(这样取模得到得点阵可以直接显示,较方便)

    • 原子的方法:

      现在单片机内部定义一个二维数组BUFFER,大小于SRAM相同;每次画点时都是往这个SRAM上置位,最后将这个SRAM一次性更新到OLED内部的SRAM上(更新方式于第一种方法相同)。(好处时,取模方式没有限制,可以兼容多种取模方式,画点时也比较快,不用每次画点都需要重新与OLED发起通讯,坏处是对单片机的SRAM要求比较高,容量要足够大。而且需要记得在每次画点结束后都要调用SRAM的更新函数。)

3.小项目练习

这次没有过于探究底层的程序,关于i2c,和6800,8080协议,以及字库的生成,读取和查找,以后再做总结吧,(毕竟现在学的还很浅)。

主要是利用原子的图库和洋桃的OLED——i2c驱动显示函数(因为手头只有一个i2c驱动的OLED),将不同取模方式的进行转换会比较麻烦些,显示函数还比较好处理。(如果有涉及侵权问题,联系我删除)

主要自己写的三个函数如下:

OLED0561.里的三个函数:

主要是实现了字库功能,这样就不用每个想要的汉字都去取模了。

/*******************************************************************************
 函 数 名         : void OLED_Show_str(u8 row,u8 colon,u8* str,u8 mode)
 函数功能			 : 显示中英文混合字串
 输    入         : row行,colon列,str字符串,mode显示模式(1汉字反白显示)
 输    出         : 无
 说    明         : 1.ASII字符不会反白显示,2.行列输入可以超过8,128,超过时会换行回环显示,但建议不要使用过大;
*******************************************************************************/
void OLED_Show_str(u8 row,u16 colon,u8* str,u8 mode)
{							  	  
    u8 is_Hz=0;     //字符或者中文  
	u8 size =16;    				    				  	  
    while(*str!=0)//数据未结束
    { 
		if(colon>=128)//换行
		{
			row+=2*(colon/128);colon%=128;
			if(row>=8)row%=8;//溢出回环重显
		}
        if(!is_Hz)
        {
	        if(*str>0x80)is_Hz=1;//标记为中文 
	        else              //字符处理
	        {           
				OLED_DISPLAY_8x16(row,colon,*str);//字符写入 
				str++; 
		        colon+=size/2; //字符,为全字的一半 
	        }
        }else//中文 
        {     
            is_Hz=0;//清零变量用于下一次识别
	        OLED_Show_HZ(row,colon,str,mode); //显示这个汉字,
	        str+=2; 
	        colon+=size;//下一个汉字偏移	    
        }						 
    } 
}

/*******************************************************************************
 函 数 名         : void OLED_Show_HZ(u8 x,u8 y,u8*ZH,u8 mode)
 函数功能			 : 显示一个中文GBK16字符
 输    入         : x行,y列,ZH,单个汉字的字符串,mode模式(1反白显示)
 输    出         : 无
 说    明         : 注意x是行,不是x指横轴(我写的坑,懒得修了)
*******************************************************************************/
void OLED_Show_HZ(u8 x,u8 y,u8*ZH,u8 mode)
{
	u8 i=0;
	u8 j,t,c=0;
	u8 dzk[32];
	Get_HzMat(ZH,dzk,16);
	for(i=0;i<32;i++)
	{
		if(mode)dzk[i] =~( char_revolve(dzk[i]) ) ;//mode1,反白显示;
		else dzk[i] = char_revolve(dzk[i]);
	}
	for(t=0;t<2;t++)
	{
		I2C_SAND_BYTE(OLED0561_ADD,COM,0xb0+x); //页地址(从0xB0到0xB7)
		I2C_SAND_BYTE(OLED0561_ADD,COM,y/16+0x10); //起始列地址的高4位(OLED芯片用高四位区分它第四位是指列地址的高四位还是低四位)
		I2C_SAND_BYTE(OLED0561_ADD,COM,y%16);	//起始列地址的低4位(实际上是加了高四位的0x00)
		for(j=0;j<16;j++)
		{ //整页内容填充
			if(t==0){c=2*j;}
			else {c=2*j+1;}
 			I2C_SAND_BYTE(OLED0561_ADD,DAT,dzk[c]);
		}x++; //页地址加1
	}
	I2C_SAND_BYTE(OLED0561_ADD,COM,0xAF); //开显示 
}

/*******************************************************************************
 函 数 名         : static u8 char_revolve(u8 temp_char)
 函数功能			 : 字节1反序函数
 输    入         : 供 void OLED_Show_HZ(u8 x,u8 y,u8*ZH,u8 mode) 显示GBK16字库字符使用
 输    出         : 反序后的GBK16码表值
 说    明         : 无
*******************************************************************************/
static u8 char_revolve(u8 temp_char)
{
	u8 result=0;
	u8 i=0;
	u8 Mask_bit=0x01;
	for(i=0;i<8;i++)
	{
		if(temp_char&0x80)result|=Mask_bit;
		temp_char<<=1;
		Mask_bit<<=1;
	}
	return result;
}

主函数中实现了个小弹幕:原理不难。同时也将OLED_Show_str()函数置于USMART中,供串口调用,有兴趣的同学可以试试看:

代码仓库的连接如下:(仓库中的Project4,之前忘了用分支把练习项目分开了)使用正点原子精英板,插SD卡(提供字库,FLASH内有的则不需要),I2C驱动的0.96寸OLED屏。

ZET6小项目: 是学习stm32zet6时做的一些小项目练习。 (gitee.com)

效果如下:

stm32汉字字库显示实验与OLED的使用(开始于2021-09-01)_第8张图片

你可能感兴趣的:(stm32自学笔记(欢迎指正),stm32)