完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:alientek 阿波罗 STM32F767 开发板
2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子 第十六章 OLED 显示实验 前面几章的实例,均没涉及到液晶显示,这一章,我们将向大家介绍 OLED 的使用。在本章中,我们将使用阿波罗 STM32 开发板上的 OLED 模块接口,来点亮 OLED,并实现 ASCII字符的显示。本章分为如下几个部分: 16.1 OLED 简介 16.2 硬件设计 16.3 软件设计 16.4 下载验证 16.1 OLED 简介 OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。OLED 由于同时具备自发光,不需背光源、对比度高、 厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优 异之特性,被认为是下一代的平面显示器新兴应用技术。 LCD 都需要背光,而 OLED 不需要,因为它是自发光的。这样同样的显示,OLED 效果要 来得好一些。以目前的技术,OLED 的尺寸还难以大型化,但是分辨率确可以做到很高。在本 章中,我们使用的是 ALINETEK 的 OLED 显示模块,该模块有以下特点: 1)模块有单色和双色两种可选,单色为纯蓝色,而双色则为黄蓝双色。 2)尺寸小,显示尺寸为 0.96 寸,而模块的尺寸仅为 27mm*26mm 大小。 3)高分辨率,该模块的分辨率为 128*64。 4)多种接口方式,该模块提供了总共 4 种接口包括:6800、8080 两种并行接口方式、4 线 SPI 接口方式以及 IIC 接口方式(只需要 2 根线就可以控制 OLED 了!)。 5)不需要高压,直接接 3.3V 就可以工作了。 这里要提醒大家的是,该模块不和 5.0V 接口兼容,所以请大家在使用的时候一定要小心, 别直接接到 5V 的系统上去,否则可能烧坏模块。以上 4 种模式通过模块的 BS1 和 BS2 设置, BS1 和 BS2 的设置与模块接口模式的关系如表 16.1.1 所示: 表 16.1.1 OLED 模块接口方式设置表 表 16.1.1 中:“1”代表接 VCC,而“0”代表接 GND。 该模块的外观图如图 16.1.1 所示: 图 16.1.1 ALIENTEK OLED 模块外观图 ALIENTEK OLED 模块默认设置是:BS1 和 BS2 接 VCC ,即使用 8080 并口方式,如果 你想要设置为其他模式,则需要在 OLED 的背面,用烙铁修改 BS1 和 BS2 的设置。 模块的原理图如图 16.1.2 所示 图 16.1.2 ALIENTEK OLED 模块原理图 该模块采用 8*2 的 2.54 排针与外部连接,总共有 16 个管脚,在 16 条线中,我们只用了 15 条,有一个是悬空的。15 条线中,电源和地线占了 2 条,还剩下 13 条信号线。在不同模式下, 我们需要的信号线数量是不同的,在 8080 模式下,需要全部 13 条,而在 IIC 模式下,仅需要 2 条线就够了!这其中有一条是共同的,那就是复位线 RST(RES),RST 上的低电平,将导致 OLED 复位,在每次初始化之前,都应该复位一下 OLED 模块。 ALIENTEK OLED 模块的控制器是 SSD1306,本章,我们将学习如何通过 STM32F767 来 控制该模块显示字符和数字,本章的实例代码将可以支持两种方式与 OLED 模块连接,一种是 8080 的并口方式,另外一种是 4 线 SPI 方式。 首先我们介绍一下模块的 8080 并行接口,8080 并行接口的发明者是 INTEL,该总线也被 广泛应用于各类液晶显示器,ALIENTEK OLED 模块也提供了这种接口,使得 MCU 可以快速 的访问 OLED。ALIENTEK OLED 模块的 8080 接口方式需要如下一些信号线: CS:OLED 片选信号。 WR:向 OLED 写入数据。 RD:从 OLED 读取数据。 D[7:0]:8 位双向数据线。 RST(RES):硬复位 OLED。 DC:命令/数据标志(0,读写命令;1,读写数据)。 模块的 8080 并口读/写的过程为:先根据要写入/读取的数据的类型,设置 DC 为高(数据) /低(命令),然后拉低片选,选中 SSD1306,接着我们根据是读数据,还是要写数据置 RD/WR 为低,然后: 在 RD 的上升沿, 使数据锁存到数据线(D[7:0])上; 在 WR 的上升沿,使数据写入到 SSD1306 里面; SSD1306 的 8080 并口写时序图如图 16.1.3 所示: 图 16.1.3 8080 并口写时序图 SSD1306 的 8080 并口读时序图如图 16.1.4 所示: 图 16.1.4 8080 并口读时序图 SSD1306 的 8080 接口方式下,控制脚的信号状态所对应的功能如表 16.1.2: 表 16.1.2 控制脚信号状态功能表 在 8080 方式下读数据操作的时候,我们有时候(例如读显存的时候)需要一个假读命 (Dummy Read),以使得微控制器的操作频率和显存的操作频率相匹配。在读取真正的数据之 前,由一个的假读的过程。这里的假读,其实就是第一个读到的字节丢弃不要,从第二个开始, 才是我们真正要读的数据。 一个典型的读显存的时序图,如图 16.1.5 所示: 图 16.1.5 读显存时序图 可以看到,在发送了列地址之后,开始读数据,第一个是 Dummy Read,也就是假读,我 们从第二个开始,才算是真正有效的数据。 并行接口模式就介绍到这里,我们接下来介绍一下 4 线串行(SPI)方式,4 先串口模式使 用的信号线有如下几条: CS:OLED 片选信号。 RST(RES):硬复位 OLED。 DC:命令/数据标志(0,读写命令;1,读写数据)。 SCLK:串行时钟线。在 4 线串行模式下,D0 信号线作为串行时钟线 SCLK。 SDIN:串行数据线。在 4 线串行模式下,D1 信号线作为串行数据线 SDIN。 模块的 D2 需要悬空,其他引脚可以接到 GND。在 4 线串行模式下,只能往模块写数据而 不能读数据。 在 4 线 SPI 模式下,每个数据长度均为 8 位,在 SCLK 的上升沿,数据从 SDIN 移入到 SSD1306,并且是高位在前的。DC 线还是用作命令/数据的标志线。在 4 线 SPI 模式下,写操 作的时序如图 16.1.6 所示: 图 16.1.6 4 线 SPI 写操作时序图 4 线串行模式就为大家介绍到这里。其他还有几种模式,在 SSD1306 的数据手册上都有详 细的介绍,如果要使用这些方式,请大家参考该手册。 接下来,我们介绍一下模块的显存,SSD1306 的显存总共为 128*64bit 大小,SSD1306 将 这些显存分为了 8 页,其对应关系如表 16.1.3 所示: 表 16.1.3 SSD1306 显存与屏幕对应关系表 可以看出,SSD1306 的每页包含了 128 个字节,总共 8 页,这样刚好是 128*64 的点阵大 小。因为每次写入都是按字节写入的,这就存在一个问题,如果我们使用只写方式操作模块, 那么,每次要写 8 个点,这样,我们在画点的时候,就必须把要设置的点所在的字节的每个位 都搞清楚当前的状态(0/1?),否则写入的数据就会覆盖掉之前的状态,结果就是有些不需要 显示的点,显示出来了,或者该显示的没有显示了。这个问题在能读的模式下,我们可以先读 出来要写入的那个字节,得到当前状况,在修改了要改写的位之后再写进 GRAM,这样就不会 影响到之前的状况了。但是这样需要能读 GRAM,对于 4 线 SPI 模式/IIC 模式,模块是不支持 读的,而且读改写的方式速度也比较慢。 所以我们采用的办法是在STM32F767 的内部建立一个 OLED 的GRAM(共 128*8 个字节), 在每次修改的时候,只是修改 STM32F767 上的 GRAM(实际上就是 SRAM),在修改完了之后, 一次性把 STM32F767 上的 GRAM 写入到 OLED 的 GRAM。当然这个方法也有坏处,就是对 于那些 SRAM 很小的单片机(比如 51 系列)就比较麻烦了。 SSD1306 的命令比较多,这里我们仅介绍几个比较常用的命令,这些命令如表 16.1.4 所示: 表 16.1.4 SSD1306 常用命令表 第一个命令为 0X81,用于设置对比度的,这个命令包含了两个字节,第一个 0X81 为命令, 随后发送的一个字节为要设置的对比度的值。这个值设置得越大屏幕就越亮。 第二个命令为 0XAE/0XAF。0XAE 为关闭显示命令;0XAF 为开启显示命令。 第三个命令为 0X8D,该指令也包含 2 个字节,第一个为命令字,第二个为设置值,第二 个字节的 BIT2 表示电荷泵的开关状态,该位为 1,则开启电荷泵,为 0 则关闭。在模块初始化 的时候,这个必须要开启,否则是看不到屏幕显示的。 第四个命令为 0XB0~B7,该命令用于设置页地址,其低三位的值对应着 GRAM 的页地址。 第五个指令为 0X00~0X0F,该指令用于设置显示时的起始列地址低四位。 第六个指令为 0X10~0X1F,该指令用于设置显示时的起始列地址高四位。 其他命令,我们就不在这里一一介绍了,大家可以参考 SSD1306 datasheet 的第 28 页。从 这页开始,对 SSD1306 的指令有详细的介绍。 最后,我们再来介绍一下 OLED 模块的初始化过程,SSD1306 的典型初始化框图如图 16.1.7 所示: 图 16.1.7 SSD1306 初始化框图 驱动 IC 的初始化代码,我们直接使用厂家推荐的设置就可以了,只要对细节部分进行一些 修改,使其满足我们自己的要求即可,其他不需要变动。 OLED 的介绍就到此为止,我们重点向大家介绍了 ALIENTEK OLED 模块的相关知识,接 下来我们将使用这个模块来显示字符和数字。通过以上介绍,我们可以得出 OLED 显示需要的 相关设置步骤如下: 1)设置 STM32F767 与 OLED 模块相连接的 IO。 这一步,先将我们与 OLED 模块相连的 IO 口设置为输出,具体使用哪些 IO 口,这里需要 根据连接电路以及 OLED 模块所设置的通讯模式来确定。这些将在硬件设计部分向大家介绍。 2)初始化 OLED 模块。 其实这里就是上面的初始化框图的内容,通过对 OLED 相关寄存器的初始化,来启动 OLED 的显示。为后续显示字符和数字做准备。 3)通过函数将字符和数字显示到 OLED 模块上。 这里就是通过我们设计的程序,将要显示的字符送到 OLED 模块就可以了,这些函数将在 软件设计部分向大家介绍。 通过以上三步,我们就可以使用 ALIENTEK OLED 模块来显示字符和数字了,在后面我们 还将会给大家介绍显示汉字的方法。这一部分就先介绍到这里。 16.2 硬件设计 本实验用到的硬件资源有: 1) 指示灯 DS0 2) OLED 模块 OLED 模块的电路在前面已有详细说明了,这里我们介绍 OLED 模块与阿波罗 STM32F767 开发板的连接,开发板底板的 OLED/CAMERA 接口(P7 接口)可以和 ALIENTEK OLED 模块 直接对插(靠左插!),连接如图 16.2.1 所示: 图 16.2.1 OLED 模块与开发板连接示意图 图中圈出来的部分就是连接 OLED 的接口,这里在硬件上,OLED 与阿波罗 STM32F767 开发板的 IO 口对应关系如下: OLED_CS 对应 DCMI_VSYNC,即:PB7; OLED_RS 对应 DCMI_SCL,即:PB4; OLED_WR 对应 DCMI_HREF,即:PH8; OLED_RD 对应 DCMI_SDA,即:PB3; OLED_RST 对应 DCMI_RESET,即:PA15; OLED_D[7:0]对应 DCMI_D[7:0],即:PB9/PB8/PD3/PC11/PC9/PC8/PC7/PC6; 这些线的连接,开发板的内部已经连接好了,我们只需要将 OLED 模块插上去就好了,注 意,这里的 OLED_D[7:0]因为不是接的连续的 IO,所以得用拼凑的方式去组合一下,后续会介 绍。实物连接如图 16.2.2 所示: 图 16.2.2 OLED 模块与开发板连接实物图 16.3 软件设计 本实验,我们新建了 oled.c 和 oled.h 文件。这两个文件用来存放 OLED 相关的驱动函数以及申明等。 oled.c 的代码,由于比较长,这里我们就不贴出来了,仅介绍几个比较重要的函数。首先 是 OLED_Init 函数,该函数的结构比较简单,开始是对 IO 口的初始化,这里我们用了宏定义 OLED_MODE 来决定要设置的 IO 口,其他就是一些初始化序列了,我们按照厂家提供的资料 来做就可以。最后要说明一点的是,因为 OLED 是无背光的,在初始化之后,我们把显存都清 空了,所以我们在屏幕上是看不到任何内容的,跟没通电一个样,不要以为这就是初始化失败, 要写入数据模块才会显示的。OLED_Init 函数代码如下: //初始化 SSD1306 void OLED_Init(void) { GPIO_InitTypeDef GPIO_Initure; __HAL_RCC_GPIOA_CLK_ENABLE(); //使能 GPIOA 时钟 __HAL_RCC_GPIOB_CLK_ENABLE(); //使能 GPIOB 时钟 __HAL_RCC_GPIOC_CLK_ENABLE(); //使能 GPIOC 时钟 __HAL_RCC_GPIOD_CLK_ENABLE(); //使能 GPIOD 时钟 __HAL_RCC_GPIOF_CLK_ENABLE(); //使能 GPIOF 时钟 __HAL_RCC_GPIOH_CLK_ENABLE(); //使能 GPIOH 时钟 #if OLED_MODE==1 //使用 8080 并口模式 //GPIO 初始化设置 GPIO_Initure.Pin=GPIO_PIN_15; //PA15 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速 HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化 //PB3,4,7,8,9 GPIO_Initure.Pin=GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9; HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化 //PC6,7,8,9,11 GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_11; HAL_GPIO_Init(GPIOC,&GPIO_Initure);//初始化 //PD3 GPIO_Initure.Pin=GPIO_PIN_3; HAL_GPIO_Init(GPIOD,&GPIO_Initure);//初始化 //PH8 GPIO_Initure.Pin=GPIO_PIN_8; HAL_GPIO_Init(GPIOH,&GPIO_Initure);//初始化 OLED_WR(1); OLED_RD(1); #else //使用 4 线 SPI 串口模式 //GPIO 初始化设置 GPIO_Initure.Pin=GPIO_PIN_15; //PA15 GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出 GPIO_Initure.Pull=GPIO_PULLUP; //上拉 GPIO_Initure.Speed=GPIO_SPEED_FAST; //高速 HAL_GPIO_Init(GPIOA,&GPIO_Initure); //初始化 //PB4,7 GPIO_Initure.Pin=GPIO_PIN_4|GPIO_PIN_7; HAL_GPIO_Init(GPIOB,&GPIO_Initure);//初始化 //PC6,7 GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7; HAL_GPIO_Init(GPIOC,&GPIO_Initure);//初始化 OLED_SDIN(1);OLED_SCLK(1); #endif OLED_CS(1);OLED_RS(1); OLED_RST(0);delay_ms(100);OLED_RST(1); OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示 OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率 …//此处省略部分代码,详情请参考实验工程 OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 OLED_Clear(); } 接着,要介绍的是OLED_Refresh_Gram函数。我们在 STM32F7 内部定义了一个块GRAM: u8 OLED_GRAM[128][8];此部分 GRAM 对应 OLED 模块上的 GRAM。在操作的时候,我们只 要修改 STM32F7 内部的 GRAM 就可以了,然后通过 OLED_Refresh_Gram 函数把 GRAM 一次 刷新到 OLED 的 GRAM 上。该函数代码如下: //更新显存到 LCD void OLED_Refresh_Gram(void) { u8 i,n; for(i=0;i<8;i++) { OLED_WR_Byte (0xb0+i,OLED_CMD); //设置页地址(0~7) OLED_WR_Byte (0x00,OLED_CMD); //设置显示位置—列低地址 OLED_WR_Byte (0x10,OLED_CMD); //设置显示位置—列高地址 for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n],OLED_DATA); } } OLED_Refresh_Gram 函数先设置页地址,然后写入列地址(也就是纵坐标),然后从 0 开 始写入 128 个字节,写满该页,最后循环把 8 页的内容都写入,就实现了整个从 STM32F7 显 存到 OLED 显存的拷贝。 OLED_Refresh_Gram 函数还用到了一个外部函数,也就是我们接着要介绍的函数: OLED_WR_Byte,该函数直接和硬件相关,函数代码如下: #if OLED_MODE==1 //8080 并口 //通过拼凑的方法向 OLED 输出一个 8 位数据 //data:要输出的数据 void OLED_Data_Out(u8 data) { u16 dat=data&0X0F; GPIOC->ODR&=~(0XF<<6); //清空 6~9 GPIOC->ODR|=dat<<6; //D[3:0]-->PC[9:6] GPIOC->ODR&=~(0X1<<11); //清空 11 GPIOC->ODR|=((data>>4)&0x01)<<11; GPIOD->ODR&=~(0X1<<3); //清空 3 GPIOD->ODR|=((data>>5)&0x01)<<3; GPIOB->ODR&=~(0X3<<8); //清空 8,9 GPIOB->ODR|=((data>>6)&0x01)<<8; GPIOB->ODR|=((data>>7)&0x01)<<9; } //向 SSD1306 写入一个字节。 //dat:要写入的数据/命令 //cmd:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(u8 dat,u8 cmd) { OLED_Data_Out(dat); OLED_RS(cmd); OLED_CS(0); OLED_WR(0); OLED_WR(1); OLED_CS(1); OLED_RS(1); } #else //向 SSD1306 写入一个字节。 //dat:要写入的数据/命令 //cmd:数据/命令标志 0,表示命令;1,表示数据; void OLED_WR_Byte(u8 dat,u8 cmd) { u8 i; OLED_RS(cmd); //写命令 OLED_CS(0); for(i=0;i<8;i++) { OLED_SCLK(0); if(dat&0x80)OLED_SDIN(1); else OLED_SDIN(0); OLED_SCLK(1); dat<<=1; } OLED_CS(1); OLED_RS(1); } #endif 首先,我们看 OLED_Data_Out 函数,这就是我们前面说的,因为 OLED 的 D0~D7 不是接的连续 IO,所以必须将数据,拆分到各个 IO,以实现一次完整的数据传输,该函数就 是根据我们 OLED_D[7:0]具体连接的 IO,对数据进行拆分,然后输出给对应位的各个 IO,实 现并口数据输出。这种方式会降低并口速度,但是我们 OLED 模块,是单色的,数据量不是很 大,所以这种方式也不会造成视觉上的影响,大家可以放心使用,但是如果是 TFTLCD,就不 推荐了。 然然后,看 OLED_WR_Byte 函数,这里有 2 个一样的函数,通过宏定义 OLED_MODE 来 决定使用哪一个。如果 OLED_MODE=1,就定义为并口模式,选择第一个函数,而如果为 0, 则为 4 线串口模式,选择第二个函数。这两个函数输入参数均为 2 个:dat 和 cmd,dat 为要写 入的数据,cmd则表明该数据是命令还是数据。这两个函数的时序操作就是根据上面我们对8080 接口以及 4 线 SPI 接口的时序来编写的。 OLED_GRAM[128][8]中的 128 代表列数(x 坐标),而 8 代表的是页,每页又包含 8 行, 总共 64 行(y 坐标)。从高到低对应行数从小到大。比如,我们要在 x=100,y=29 这个点写入 1,则可以用这个句子实现: OLED_GRAM[100][4]|=1<<2; 一个通用的在点(x,y)置 1 表达式为: OLED_GRAM[x][7-y/8]|=1<<(7-y%8); 其中 x 的范围为:0~127;y 的范围为:0~63。 因此,我们可以得出下一个将要介绍的函数:画点函数,void OLED_DrawPoint(u8 x,u8 y, u8 t);函数代码如下: void OLED_DrawPoint(u8 x,u8 y,u8 t) { u8 pos,bx,temp=0; if(x>127||y>63)return;//超出范围了. pos=7-y/8; bx=y%8; temp=1<<(7-bx); if(t)OLED_GRAM[x][pos]|=temp; else OLED_GRAM[x][pos]&=~temp; } 该函数有 3 个参数,前两个是坐标,第三个 t 为要写入 1 还是 0。该函数实现了我们在 OLED 模块上任意位置画点的功能。 接下来,我们介绍一下显示字符函数,OLED_ShowChar,在介绍之前,我们来介绍一下字 符(ASCII 字符集)是怎么显示在 OLED 模块上去的。要显示字符,我们先要有字符的点阵数 据,ASCII 常用的字符集总共有 95 个,从空格符开始,分别为: !"#$%&'()*+,-0123456789:;<= >?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~. 我们先要得到这个字符集的点阵数据,这里我们介绍一个款很好的字符提取软件: PCtoLCD2002 完美版。该软件可以提供各种字符,包括汉字(字体和大小都可以自己设置)阵 提取,且取模方式可以设置好几种,常用的取模方式,该软件都支持。该软件还支持图形模式, 也就是用户可以自己定义图片的大小,然后画图,根据所画的图形再生成点阵数据,这功能在 制作图标或图片的时候很有用。 该软件的界面如图 16.3.1 所示: 图 16.3.1 PCtoLCD2002 软件界面 然后我们选择设置,在设置里面设置取模方式如图 16.3.2 所示: 图 16.3.2 设置取模方式 上图设置的取模方式,在右上角的取模说明里面有,即:从第一列开始向下每取 8 个点作 为一个字节,如果最后不足 8 个点就补满 8 位。取模顺序是从高到低,即第一个点作为最高位。 如*-------取为 10000000。其实就是按如图 16.3.3 所示的这种方式: 图 16.3.3 取模方式图解 从上到下,从左到右,高位在前。我们按这样的取模方式,然后把 ASCII 字符集按 12*6 大小、16*8 和 24*12 大小取模出来(对应汉字大小为 12*12、16*16 和 24*24,字符的只有汉字 的一半大!),保存在 oledfont.h 里面,每个 12*6 的字符占用 12 个字节,每个 16*8 的字符占用 16 个字节,每个 24*12 的字符占用 36 个字节。具体见 oledfont.h 部分代码(该部分我们不再这 里列出来了,请大家参考光盘里面的代码)。 在知道了取模方式之后,我们就可以根据取模的方式来编写显示字符的代码了,这里我们 针对以上取模方式的显示字符代码如下: //在指定位置显示一个字符,包括部分字符 //x:0~127 //y:0~63 //mode:0,反白显示;1,正常显示 //size:选择字体 12/16/24 void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size,u8 mode) { u8 temp,t,t1; u8 y0=y; u8 csize=(size/8+((size%8)?1:0))*(size/2);//得到字体一个字符对应点阵集所占的字节数 chr=chr-' ';//得到偏移后的值 for(t=0;t if(size==12)temp=asc2_1206[chr][t]; //调用 1206 字体 else if(size==16)temp=asc2_1608[chr][t]; //调用 1608 字体 else if(size==24)temp=asc2_2412[chr][t]; //调用 2412 字体 else return; //没有的字库 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; } } } } 该函数为字符以及字符串显示的核心部分,函数中 chr=chr-' ';这句是要得到在字符点阵数 据里面的实际地址,因为我们的取模是从空格键开始的,例如 oled_asc2_1206[0][0],代表的是 空格符开始的点阵码。在接下来的代码,我们也是按照从上到小(先 y++),从左到右(再 x++) 的取模方式来编写的,先得到最高位,然后判断是写 1 还是 0,画点;接着读第二位,如此循 环,直到一个字符的点阵全部取完为止。这其中涉及到列地址和行地址的自增,根据取模方式 来理解,就不难了。 oled.c 的内容就为大家介绍到这里。oled.h 头文件内容比较简单,主要是一些宏定义和函数 声明, 这里就不做过多讲解。 最后我们来看看主函数代码: int main(void) { u8 t=0; Cache_Enable(); //打开 L1-Cache HAL_Init(); //初始化 HAL 库 Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz delay_init(216); //延时初始化 uart_init(115200); //串口初始化 LED_Init(); //初始化 LED OLED_Init(); //初始化 OLED OLED_ShowString(0,0,"ALIENTEK",24); OLED_ShowString(0,24, "0.96' OLED TEST",16); OLED_ShowString(0,40,"ATOM 2016/7/11",12); OLED_ShowString(0,52,"ASCII:",12); OLED_ShowString(64,52,"CODE:",12); OLED_Refresh_Gram();//更新显示到 OLED t=' '; while(1) { OLED_ShowChar(36,52,t,12,1); //显示 ASCII 字符 OLED_ShowNum(94,52,t,3,12); //显示 ASCII 字符的码值 OLED_Refresh_Gram(); //更新显示到 OLED t++; if(t>'~')t=' '; delay_ms(500); LED0_Toggle; } } 该部分代码用于在 OLED 上显示一些字符,然后从空格键开始不停的循环显示 ASCII 字符 集,并显示该字符的 ASCII 值。然后我们编译此工程,直到编译成功为止。 16.4 下载验证 将代码下载到开发板后,可以看到 DS0 不停的闪烁,提示程序已经在运行了。同时可以看 到 OLED 模块显示如图 16.4.1 所示: 图 16.4.1 OLED 显示效果 图中 OLED 显示了三种尺寸的字符:24*12(ALIENTEK)、16*8(0.96’ OLED TEST)和 12*6(剩下的内容)。说明我们的实验是成功的,实现了三种不同尺寸 ASCII 字符的显示,在 最后一行不停的显示 ASCII 字符以及其码值。 通过这一章的学习,我们学会了 ALIENTEK OLED 模块的使用,在调试代码的时候,又多 了一种显示信息的途径,在以后的程序编写中,大家可以好好利用。 |
|
相关推荐
|
|
STM32进行DMA数据转运,为什么只有A组最后一位数据被转运到B组去?
1265 浏览 2 评论
1585 浏览 3 评论
1206 浏览 0 评论
嵌入式开发 Win11安装ST-Link 提示 设备描述符请求失败 怎么处理?
1339 浏览 0 评论
1632 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-8-18 06:20 , Processed in 0.582593 second(s), Total 62, Slave 50 queries .
Powered by 电子发烧友网
© 2015 www.ws-dc.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号