STM32 OLED屏显示字符串、汉字、图片教程(二)

上一节初始化了OLED屏,使得它完成了清屏,现在驱动它在屏幕上打印字符串、汉字以及图片。

        1.1   STM32+OLED屏初始化(一) 

        1.2  STM32+OLED屏显示字符串、汉字、图片(二)

        1.3  STM32+OLED屏多级菜单显示(三)

        1.4  STM32+OLED屏(软件IIC+位带+帧缓冲区)刷新速率优化(四) 

1.制作字库

字符集:

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

        要想屏幕上显示字符,需要相应的字库,现在先做一个字库。

        打开取模软件pctolcd2002完美版,再点击选项,配置如下所选,点击确定。

        点阵格式:阴码字体亮,阳码字体不亮 

        字符走向:逆向低位在前,顺向高位在前(主要看驱动IC的编码格式)、

        取模方式:指字模图形的扫描方向 

        输出数制:生成字模的数的进制 

        每行显示数据:生成数组的大小,字符的长(页)x字符的宽(如8*16字体,2页*8列 = 16;如12*24字体,3页*12列 = 36;如16*32字体,4页*16列 = 64)

        选择字库字体大小,最好选择8的倍数,因为64行已经分为8页(每页8行),如果不是8的倍数,就会显示到其他页去,操作会变得麻烦一些。

自命名字库名称

        一个8×16的英文字库就完成了,字符在字库中的存取是二维数组Ascii_8*16[95][16];就拿字符 ' A ' 来说,字符 ' A ' 存在Ascii_8*16[33][0] ~ Ascii_8*16[33][16]之间

生成其他大小的字库

        生成12*24的字库,首先要调节字体大小,其次要调节每行显示数据:24/8=3页,3*12=36,所以每行显示数据的点阵设置为36,最后,点击生成字模,复制粘贴到OLED_Fonnt.h文件中

三种大小不同的字库

        字库中存取了三种字体,第一个比较特殊(在网上找的,但不完整),自己尝试着生成,发现自己生成的字体显示不清晰,如果有朋友有完整的,请@我分享我一份,其他两个是自己生成的

2.显示一个字符 

        显示字符串从一个字符开始,字符串只不过是一串字符,完成显示一个字符后再循环多次,就可以完成字符串显示了,字符显示先定义起始光点,再把字库中的数据写入,即可完成。就拿8*16字体来说,8列*16行(2页),所以要写2页(i < 2),字宽写8列(j < 8),第一页设置起始光点写入数据,第二页再设置起光点偏移一位( + i),因为字宽是8,数据再偏移八位( + i*8),完成显示

/**
  * @brief  OLED显示一个字符
  * @param  Line 行位置
  * @param  Column 列位置
  * @param  Fontsize 字体大小
  * @param  Char 要显示的一个字符,
  * @retval 无
  */
void OLED_ShowChar(uint8_t Line, uint8_t Column, uint16_t Fontsize, char Char)
{      	
	uint8_t i, j;
	
	switch(Fontsize) {
		case 8:	{
			OLED_SetCursor(Line, Column);		
			for (j=0; j<6; j++) {//字宽为6
				OLED_Write_Data(Ascii_6x8[Char-' '][j]);			
			}
			break;
		}
		case 16: {
			for(i=0; i<2; i++) {
				OLED_SetCursor(Line+i, Column);	//循环2次显示上/下半部分内容	
				for (j=0; j<8; j++) {//字宽为8
					OLED_Write_Data(Ascii_8x16[Char-' '][j+i*8]);			
				}
			}
			break;
		}
		case 24: {
			for(i=0; i<3; i++) {
				OLED_SetCursor(Line+i, Column);	//循环3次显示上/中/下半部分内容	
				for (j=0; j<12; j++) {//字宽为12
					OLED_Write_Data(Ascii_12x24[Char-' '][j+i*12]);			
				}
			}
			break;
		}
	}
}

        6*8字体 ' A ', 8*16字体 ' A ', 12*24字体 ' A '

3.显示字符串

        字符串的显示较为简单,在显示字符的基础上偏移一个字符的字宽,就可以了。如6*8字体的字宽是6,就偏移 + i*6;8*16字体的字宽是8,就偏移 + i*8;12*24字体的字宽是12,就偏移 + i*12

/**
  * @brief  OLED显示字符串
  * @param  Line 行位置
  * @param  Column 列位置
  * @param  Fontsize 字体大小
  * @param  String 显示字符串,
  * @retval 无
  */
#include <string.h>
void OLED_ShowString(uint8_t Line, uint8_t Column, uint16_t Fontsize, const char* String)
{
	uint8_t i, len;
	len = strlen(String);//算出字符串长度
	
	for(i=0; i<len; i++) {
		switch(Fontsize) {
			case 8:OLED_ShowChar(Line, Column+i*6, Fontsize, String[i]);
			break;
			case 16:OLED_ShowChar(Line, Column+i*8, Fontsize, String[i]);
			break;
			case 24:OLED_ShowChar(Line, Column+i*12, Fontsize, String[i]);
			break;
		}
	}
}

         6*8字体 " ABCD ", 8*16字体 " ABCD ", 12*24字体 " ABCD "

4.显示汉字

        汉字的显示同理,先制作中文字库,但是中文汉字太多了,简单选择几个“ 点个赞吧!”显示即可,首先,制作汉字字库:因为字宽为16*2页 = 32

        加入OLED_Font.h,自定义二维数组名称:

        显示一个汉字,显示汉字和显示字符同理,只不过汉字的字宽是16,所以字宽写16列(j < 16),后续的数据偏移也自然是16位( + i*16);完成显示

/**
  * @brief  OLED显示汉字
  * @param  Line 行位置
  * @param  Column 列位置
  * @param  Chinese 显示汉字编号
  * @retval 无
  */
void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t Chinese)
{
	uint8_t i, j;
	
	for(i=0; i<2; i++) {
		OLED_SetCursor(Line+i, Column);	//循环2次显示上/下半部分内容	
		for (j=0; j<16; j++) {//字宽为16
			OLED_Write_Data(Chinese_16x16[Chinese][j+i*16]);			
		}
	}
}

        显示效果:

5.显示图片

        同理,制作图源库,找一张自己喜欢的图片,选择画图工具打开

        设置像素大小,进行裁剪

        另存为BMP单色位图片

        打开取模工具,选择图形模式,再打开刚刚制作的图片,生成字模

        保存到OLED_Font.h中,删除所有的大括号,保存为一维数组

        写法一样,依次取数 

/**
  * @brief  OLED显示图片
  * @param  无
  * @retval 无
  */
void OLED_ShowImageBMG(void)
{
	uint8_t i, j;
	
	for(i=0; i<8; i++) {
		OLED_SetCursor(0+i, 0);	//循环8次显示8页内容	
		for (j=0; j<128; j++) {//字宽为8
			OLED_Write_Data(ImageBMG64x128[j+i*128]);			
		}
	}
}

显示效果:

6.编写RTC显示时钟

        最后,再编写一个实时时钟完成显示,常规时钟配置就不展示了,直接上最终源码

/**
  * @brief  OLED显示RTC
  * @param  无
  * @retval 无
  */
void OLED_ShowRTC(void)
{
	char buff[50];
	
	RTC_Get_StdTime(RTC_GetCounter());
	
	sprintf(buff,"%0.2d-%0.2d-%0.2d",RTC_CLOCK.hour, RTC_CLOCK.min, RTC_CLOCK.sec);
	OLED_ShowString(4, 10,  24, buff);
	
	sprintf(buff,"Date:%0.4d-%0.2d-%0.2d",RTC_CLOCK.year,RTC_CLOCK.mon,RTC_CLOCK.day);
	OLED_ShowString(1, 6,  16, buff);
}

        

7.主函数 

main.c函数

//#include "main.c"

int main(void)
{
	OLED_Init();
	Usart_Init();

	printf("OLED显示字符串、汉字、图片\r\n");

//	//显示字符串
//	OLED_ShowString(0,0,8,"ABCD");
//	OLED_ShowString(1,0,16,"ABCD");
//	OLED_ShowString(3,0,24,"ABCD");
//	
//	//显示汉字
//	OLED_ShowChinese(3,16*2,0);// 点
//	OLED_ShowChinese(3,16*3,1);// 个
//	OLED_ShowChinese(3,16*4,2);// 赞
//	OLED_ShowChinese(3,16*5,3);// 吧
//	OLED_ShowChinese(3,16*6,4);// ! 
	
//	//显示图片
//	OLED_ShowImageBMG();
    
    //显示时钟
    OLED_ShowRTC();
	while (1) {
		
		delay_ms(1000);
	}
}

        总结:历经万险终于完了,虽然最终的效果都实现了,但代码并不健壮。问题在于访问光点缺少越界保护,屏幕的范围在64*128之间,可是起始光点设置的范围却没有限制;除此之外,字符串的一部分超出显示范围没有进行换行换页,这些问题可能在今后造成巨大的错误。

源码分享:

链接:https://pan.baidu.com/s/1ZpaEZhR0IvtqoiW-65ATKw?pwd=p08k 
提取码:p08k

物联沃分享整理
物联沃-IOTWORD物联网 » STM32 OLED屏显示字符串、汉字、图片教程(二)

发表评论