全彩OLED(SSD1351)程序设计与应用(3)字符,字符串以及位图的生成与显示

本文开发环境:

  • MCU型号:STM32F103ZE
  • IDE环境: MDK 5.27
  • 显示模块:1.27寸全彩OLED(SSD1351)驱动

本文内容:

  1. 位图的显示
  2. 字符和字符串的显示

OLED 系列博客索引 :

  1. 全彩OLED(SSD1351)程序设计与应用(1)驱动的移植
  2. 全彩OLED(SSD1351)程序设计与应用(2)显存优化:显存的设计与实现
  3. 全彩OLED(SSD1351)程序设计与应用(3)字符,字符串以及位图的生成与显示

一、图片的显示

在上一节中已经了解了OLED的显示原理,我们通过填充一个数组,然后将数组的数据通过spi发送到OLED中,就完成了显示。我们还使用menset来对数组的值进行设置,因为设置为同一个值,所以每次显示都是纯色,如果要显示一个图片,那么就需要根据图片的色彩来填充数组,当然,我们不需要每一个像素点数据都手动输入,而是使用工具进行转换。

1. Image2Lcd 工具的使用

文末附件中 提供了 Image2Lcd 工具的下载。

1.1 图片准备

Image2Lcd可以将图片转换转化为我们需要的数组,首先需要准备一张图片,我在红白机《顽皮狗》游戏中截取了一张大小为128x128(像素)的图片,如下所示:
在这里插入图片描述

1.2 打开图片

首先打开Image2Lcd工具,在菜单栏中点击 “打开”,选择要转换的图片,注意,这个工具有图片格式要求,在此版本中,不支持PNG格式,如果你原图片不符合格式要求,请用工具(如画图等)转换为合适的格式,否则在Image2Lcd中无法找到目标图片。具体操作如下所示:
在这里插入图片描述

1.3 Image2Lcd 配置

前文提及到,程序设置了OLED绘图方式为从左到右,颜色为565的RGB彩色,本次图片的大小为128x128(像素),这些信息都需要告诉转换工具,这样才能正确生成所需数组,具体配置如下图所示:
在这里插入图片描述
当我们配置参数以后,就可以生成图像了,注意到,如果你使用的是未注册或非破解的版本,图片会有Image2lcd的水印,这并非设置问题。当然,在本系列中,由于使用的是1.27寸OLED,却使用1.5寸的驱动配置,所以上面有一行是不被显示的,Image2lcd水印正好不被显示。最后,如果你对这些配置参数不够熟悉,请不了解的每一项都与上图保持一致。

1.4 生成图片数组

参数设置完成以后,就可以点击保存来生成图片数组
在这里插入图片描述
当我们点击第4步的保存以后,就会弹出一个文本框,里面的内容即是我们所需要的点阵数据:
在这里插入图片描述

程序设计

我还需要将工具转换到的数组拷贝到工程中,一般我们可以建立一个Image.h文件来存放这个数组,在需要使用该数组的程序中,使用 #include “Image.h” 来引入,这样就不会由于这个数据过长,而影响我们查看其他程序了。

Image.h文件只存放图片数组,注意需要使用const声明,这样会存放在Flash中,减轻RAM的负担:
在这里插入图片描述我们将OLED_Test()函数修改如下:

文件 OLED.c :

... ... 
#include "Image.h"
.. ... 
void OLED_Test(void)
{
    memcpy(oled_ram,gImage_dog,OLED_RAM_SIZE);              //拷贝图片数据到显存中
    OLED_Refresh();                                         //刷新oled,显示图片
    HAL_Delay(5000);
}

由于我们正好是128x128(像素)的图片,所以这里只需要最简单的全部复制即可,如果不是,则需要根据图片的长度,一行一行的复制填充数组。其原理和字符的显示相似,这里则不做介绍。以上代码演示效果如下所示:
在这里插入图片描述

二、字符的显示

文末附件中 提供了 PCtoLCD2002 工具的下载。

1. 字符显示的原理

其实对于OLED来说,字符也只是一个点阵数据而已,所以我们同样是使用工具来生成生成点阵数组,一般我们将字符到点阵数组的过程称之为取模,本文我们使用工具 PCtoLCD2002 工具来进行取模。
在这里插入图片描述

2. 参数的配置

和图片的显示一样,我们需要对工具进行一些配置,才可以生成我们所需要的点阵数据。首先打开取模软件,点击菜单栏齿轮图标打开设置,配置好参数,具体操作如下所示:
在这里插入图片描述
如果你不清楚每一个参数的意义,请保持每一项与上文一致即可。

3.生成 ASCII 字符点阵

我们可以一个一个生成,但是工具还提供了一次性生成128个字符串数据的功能,首先需要选择字体:
在这里插入图片描述
选择字体为:幼圆。字宽和字高都为16,注意,这里是针对汉字而言,对应的英文的宽度为8x16。接着点击文本图标,进行整体生成,具体操作如下所示:
在这里插入图片描述
接着输入文件名:
在这里插入图片描述
点击保存以后将会在桌面生成一个font.h的文件,剪贴并拷贝到工程中,完成字库的导入。

3. 程序设计

字库导入到工程中后,其实是一系列的点整数组,我们需要把它转成一个二维数组,以便我们程序使用,具体操作如下:
font.h 文件:

const unsigned char ACSII_Font[][16] = {    
	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",32*/
	{0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00},/*"!",33*/
	{0x00,0x12,0x24,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",34*/
	{0x00,0x00,0x00,0x12,0x12,0x12,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00,0x00},/*"#",35*/
	... ...
	{0x20,0x5A,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",126*/
	{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"",127*/
};

我们只需要添加2行代码,就将其转换成一个为二维数组,注意到,我们数组的第一个元素为Ascill的空格,序号为32,即 Ascill 码的第33个,这是因为,前32个为非显示字符,所以不需要数据。以上代码我们创建了一个ACSII_Font的二维数组,其每一个成员都是一个字符,并且是按Ascill表格排序的。通用需要注意声明为 const,以减轻MCU中RAM的负担。

3.1 绘制点函数

我们需要能有一个绘制指定坐标,指定颜色的绘点函,来为后续的功能实现提供基础,其代码如下所示:

OLED.c 文件 :

void Draw_Point(unsigned char x, unsigned char y, uint16_t Colour_RGB)
{ 
    //判断x和y的值,避免某些不安全的操作
    if(x > 127)
        x = 127;
    if(y > 127)
        y = 127;
        
    uint16_t temp;                                            //坐标的数组位置
    temp = ((y*128 + x)*2);                                   //计算点阵的值
    
    oled_ram[temp] = (Colour_RGB >> 8);                      //写入填充颜色高字节
    oled_ram[temp + 1] = Colour_RGB;                         //写入填充颜色低字节
}

该函数可以在显存中存入一个值,其中x,y对应横坐标和纵坐标,Colour_RGB为565颜色。

3.2 绘制字符函数

字符串需要根据前文提供的表格来绘制,其程序如下所示:
OLED.c 文件 :

void Draw_Char(unsigned char x, unsigned char y, unsigned char Var_Char, int Colour_RGB)
{
    unsigned char i, j;
    unsigned char Var_Temp, x_Temp; 

    x_Temp = x;                                                //获取x起始坐标
    for (i = 0; i < 16; i++)
    {
        Var_Temp = ACSII_Font[Var_Char - 0x20][i];             //获取字符在数组的偏移量
        for ( j = 0; j < 8; j++)
        {
            if (Var_Temp & 0x80)                               //先画最高位的点,为1则画对应的颜色
                Draw_Point(x, y, Colour_RGB);
            //else
                //Draw_Point(x, y, 0x0000);                      //为0则黑色(都不亮),可作为背景色

            Var_Temp <<= 1;                                    //移位,准备画下一个点
            x++;                                               //x坐标加1

            if((x - x_Temp) == 8)
            { 
                x = x_Temp;                                     //x坐标回到起始位置
                y++;                                            //y坐标加1
                break;                                          //退出当前循环
            }
        }
    }
}

注意到,在本程序中,我们注释掉 Draw_Point(x,y,0x0000),即使当我们读取到黑色点数据的时候,不处理。实现的就是黑色表示透明,但是这样黑色就无法显示了,用来告诉程序,这部分不改变原有像素,一般来说,我们会使用一个很少见的颜色,如丑茄色来作为透明颜色。

3.3 绘制字符串函数

字符串对比字符显示简单一些,他只是轮询每个字符,然后显示,一直到字符结束,程序如下所示:

OLED.c 文件:

void Draw_String(unsigned char x, unsigned char y, unsigned char *chr, int Colour_RGB)
{
    unsigned char i = 0;                     //定义变量

    while(chr[i] != '\0')                    //判断是否结束
    {
        Draw_Char(x, y, chr[i], Colour_RGB); //显示字符
        x += 8;                              //x坐标加8(一个字符x方向占8个点,Y方向占16个点)
        i++;                                 //下一个字符
    }
}

3.4 示例程序

我们已经实现了绘制字符串和字符的函数,接下来写一个测试函数,修改OLED_Test()函数来测试代码:
OLED.c 文件:

void OLED_Test(void)
{
    memcpy(oled_ram,gImage_dog,OLED_RAM_SIZE);    //填充背景:背景总是第一个填充的,这样才不会覆盖其他显示
    
    Draw_String(60,75,"NAUGHTY",0xAAAA);         //填充字符串 “NAUGHT”
    Draw_Char(70,95,'D',0x0F00);                 //填充字符 ‘D’
    Draw_Char(80,95,'O',0x00F0);                 //填充字符 ‘O’
    Draw_Char(90,95,'G',0xFFFF);                 //填充字符 ‘G’
    OLED_Refresh();                              //刷新屏幕                      
    
    HAL_Delay(5000); 
}

程序运行效果如下所示:
**OLED.c :**

附件

链接:资源下载
提取码:jz28

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值