23. SPI——OLED屏幕显示¶
RA芯片的SPI分为简单SPI和普通SPI,简单SPI就是SCI模块(Serial Communications Interface)中的SPI模式,它是使用串行总线来模拟SPI,而我们本章我们所要学习的是普通的SPI,是全功能的SPI,它在RA芯片内部实际存在的一个硬件SPI控制器模块。
23.1. SPI协议¶
SPI协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设备接口,是一种高速全双工的通信总线。它被广泛地使用在ADC、LCD等设备与MCU间,要求通讯速率较高的场合。
在瑞萨RA6M5芯片中,SPI外设可用作通讯的主机及从机,数据传输可达到最大的50Mbps速率,信号允许通过SPI操作(4线方法)或时钟同步操作(3-线方法),支持事件链接功能,并具有数据校验功能。
下面我们分别对SPI协议的物理层及协议层进行讲解。
23.1.1. SPI物理层¶
SPI通讯设备之间的常用连接方式见下图。
SPI通讯使用3条总线及片选线,3条总线分别为SCK、MOSI、MISO,片选线,它们的作用介绍如下:
从设备选择信号线 ( Slave Select):常称为片选信号线,也称为NSS、CS,以下用 NSS表示。当有多个SPI从设备与SPI主机相连时,设备的其它信号线SCK、MOSI及MIS O同时并联到相同的SPI总线上,当主机要选择从设备时,把该从设备的NSS信号线设置为低电平,该从设备即被选中, 即片选有效,接着主机开始与被选中的从设备进行SPI通讯。 所以SPI通讯以NSS线置低电平为开始信号,以NSS线被拉高作为结束信号。
SCK (Serial Clock):时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了 通讯的速率,不同的设备支持的最高时钟频率不一样,如RA6M5的SPI时钟 频率最大为fpclkA/2,两个设备之间通讯时,通讯速率受限于低速设备。
MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。主机的数据从这条 信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。
MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。主机从这条信 线读入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。
23.1.2. 协议层¶
23.1.2.1. SPI基本通讯过程¶
SPI通讯的通讯时序,见下图:
这是一个主机的通讯时序。NSS、SCK、MOSI信号都由主机控制产生,而MISO的信号由从机产生,主机通过该信号线读取从机的数据。 MOSI与MISO的信号只在NSS为低电平的时候才有效,在SCK的每个时钟周期MOSI和MISO传输一位数据。
以上通讯流程中包含的各个信号分解如下:
23.1.2.2. 通讯的起始和停止信号¶
在上图 SPI通讯时序 中的标号 1 处,NSS信号线由高变低,是SPI通讯的起始信号。 NSS是每个从机各自独占的信号线,当从机在自己的NSS线检测到起始信号后,就知道自己被主机选中了,开始准备与主机通讯。 在标号 6 处,NSS信号由低变高,是SPI通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。
23.1.2.3. 数据有效性¶
SPI使用MOSI及MISO信号线来传输数据,使用SCK信号线进行数据同步。MOSI及MISO数据线在SCK的每个时钟周期传输一位数据, 且数据输入输出是同时进行的。数据传输时,MSB先行或LSB先行并没有作硬性规定,但要保证两个SPI通讯设备之间使用同样的协定, 一般都会采用图 SPI通讯时序 中的MSB先行模式。
观察图中的标号处,MOSI及MISO的数据在SCK的上升沿期间变化输出,在SCK的下降沿时被采样。即在SCK的下降沿时刻, MOSI及MISO的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI及MISO为下一次表示数据做准备。
SPI每次数据传输可以8位或16位为单位,每次传输的单位数不受限制
23.1.2.4. CPOL/CPHA及通讯模式¶
SPI一共有四种通讯模式,它们的主要区别是总线空闲时SCK的时钟状态以及数据采样时刻,它们由CPOL与CPHA来决定。
时钟极性CPOL是指SPI通讯设备处于空闲状态时,SCK信号线的电平信号(即SPI通讯开始前、 NSS线为高电平时SCK的状态)。CPOL=0时, SCK在空闲状态时为低电平,CPOL=1时,则相反。
时钟相位CPHA是指数据的采样的时刻,当CPHA=0时,MOSI或 MISO数据线上的信号将会在SCK时钟线的“奇数边沿”被采样。 当CPHA=1时,数据线在SCK的“偶数边沿”采样。
见下图 CPHA=0时的SPI通讯模式:
我们来分析这个CPHA=0的时序图。首先,根据SCK在空闲状态时的电平,分为两种情况。SCK信号线在空闲状态为低电平时,CPOL=0;空闲状态为高电平时,CPOL=1。
无论CPOL=0还是=1,因为我们配置的时钟相位CPHA=0,在图中可以看到,采样时刻都是在SCK的奇数边沿。注意当CPOL=0的时候,时钟的奇数边沿是上升沿,而CPOL=1的时候,时钟的奇数边沿是下降沿。所以SPI的采样时刻不是由上升/下降沿决定的。MOSI和MISO数据线的有效信号在SCK的奇数边沿保持不变,数据信号将在SCK奇数边沿时被采样,在非采样时刻,MOSI和MISO的有效信号才发生切换。
类似地,当CPHA=1时,不受CPOL的影响,数据信号在SCK的偶数边沿被采样,
见下图 CPHA=1时的SPI通讯模式:
由CPOL及CPHA的不同状态,SPI分成了四种模式,见下表:
SPI的四种模式
SPI模式 |
CPOL |
CPHA |
空闲时SCK时钟 |
采样时刻 |
数据发送 |
0 |
0 |
0 |
低电平 |
上升沿 |
下降沿 |
1 |
0 |
1 |
低电平 |
下降沿 |
上升沿 |
2 |
1 |
0 |
高电平 |
下降沿 |
上升沿 |
3 |
1 |
1 |
高电平 |
上升沿 |
下降沿 |
主机与从机需要工作在相同的模式下才可以正常通讯,上图 SPI通讯时序 就是采用的模式1,而我们本次OLED的SPI通讯实验就是采用的是模式3。
23.2. 瑞萨SPI功能框图¶
以 RA6M5 为例,SPI的功能结构框图如下图所示。接下来我们大致地研究一下它的结构和功能。
见图注1,瑞萨RA6M5有两个SPI外设,分别是SPI0,SPI1,每个SPI都有2~3组,下面是关于SPI各引脚的说明,以SPI0_A为例,见下表,其中值得一提的是, 当MCU作为主机时,有多个从机时,从机可通过SSLA0~SSLA3作为片选信号线来连接主机,而当MCU作为从机时, 则通过SSLA0作为片选线连接主机。
SPI_0的IO引脚描述
引脚名称 |
I/O |
Description |
---|---|---|
RSPCKA |
I/O |
时钟输入输出引脚 |
MOSIA |
I/O |
主机发送数据输入输出 |
MISOA |
I/O |
从机发送数据输入输出 |
SSLA0 |
I/O |
从机选择输入输出 |
SSLA1~SSLA3 |
Output |
从机选择输出 |
注解
SPI0的引脚名称表示为“…A”或“…An”,SPI1的引脚名称表示为“…B”或“…Bn”(n=0、1、2或3)。
见图注2,其中:
Master:主机通讯模式
Slave:从机通讯模式
Normal:正常通讯模式
Loopback:环回模式1(接受数据=反转发送数据)
Loopback:环回模式2(接受数据=发送数据)
见图注3,其中:
SPTX:发送缓冲器
SPRX:接受缓冲器
见图注4,对于瑞萨RA6M5的SPI外设的寄存器介绍,见下表:
SPI的寄存器
SPCR |
SPI控制寄存器 |
SSLP |
SPI从机选择极性寄存器 |
SPPCR |
SPI引脚控制寄存器 |
SPSR |
SPI状态寄存器 |
SPDR/SPDR_HA/SPDR_BY |
SPI数据寄存器 |
SPSCR |
SPI序列控制寄存器 |
SPSSR |
SPI序列状态寄存器 |
SPBR |
SPI比特率寄存器 |
SPDCR |
SPI数据控制寄存器 |
SPCKD |
SPI时钟延迟寄存器 |
SSLND |
SPI从机选择否定延迟寄存器 |
SPND |
SPI下一次访问延迟寄存器 |
SPCR2 |
SPI控制寄存器2 |
SPCMDm |
SPI命令寄存器m(m=0到7) |
SPDCR2 |
SPI数据控制寄存器2 |
SPCR3 |
SPI控制寄存器3 |
注解
我们这里主要介绍的是瑞萨的fsp库的使用,所以在这里寄存器我们在这里做一些简单的介绍
见图注5,SPI波特率设置由寄存器SPBR与SPMDm.BRDV[1:0]设置的组合在主模式下设置。 当SPI处于从机模式时,比特率取决于输入时钟PCLKA的比特率,与SPBR和SPMDm.BRDV[1:0]位(比特率分频设置)的 设置无关。
见图注6,其中:
SPIi_SPRI:接收缓冲区满事件输出。
SPIi_SPTI:发送缓冲区空事件输出。
SPIi_SPEI:模式故障、欠载、溢出或奇偶校验错误事件输出。
SPIi_SPII:SPI空闲事件输出。
SPIi_SPCEND:传输完成事件输出。
23.3. OLED相关¶
OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display,OELD)。OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。 OLED 显示技术具有自发光的特性,采用非常薄的有机材料涂层和玻璃基板,当有电流通过时,这些有机材料就会发光,而且 OLED 显示屏幕可视角度大,并且能够节省电能。
本文使用是0.96 寸的 OLED 显示模块(蓝色)作为实验模块,详细资料可以在野火电子官网找到。实物如下所示:
分辨率为 128*64
驱动IC芯片为SSD1306
4线SPI总线通信方式
原理图如下:
23.3.1. 接口协议¶
对于4线制SPI接口协议,其通信过程对于片选信号和数据/命令切换信号的要求如下图所示
通过设置CS引脚为低电平,我们可以确定器件为选中状态, 设置其DC引脚不同的电平状态,来控制输出的指令为地址指令还是数据指令。
SSD1306的4线制SPI通信的时序如下图所示:
我们可以看到,CS信号线由高变低,是SPI通讯的起始信号,MOSI信号线负责传输数据, MOSI的数据在SCLK的下升沿或低电平期间变化输出,在SCLK上降沿的时候,SDIN(MOSI)的数据有效,SDIN(MOSI)将数据锁存, 高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效。 SSD1306芯片则根据DC信号线的电平状态,来区分接受到的指令是地址指令还是数据指令, 最后,当数据/命令传输完毕后,CS信号线由低变高,解除对当前设备的选中状态,至此,一次数据传输完成。
23.3.2. 显存写入方式¶
SSD1306的显存写入方式有三种,分别是页地址模式,横向地址模式和纵向地址模式。 不同的地址模式下,把数据写入显存后,显存的地址变化方式是不一样的。 我们这里选择的是页地址模式,在页地址模式下,在发送完显示数据后,列地址指针将增加。 如果列地址指针到达列结束地址,则列地址指针为重置为列开始地址,而页地址指针不更改,需要用户设置新页面,并且 列地址为访问下一页显存。 页地址与列地址的移动顺序如下图所示:
23.3.3. 命令字¶
关于SSD1306的基本命令字及说明如下表:
属性 |
命令字 |
说明 |
---|---|---|
设置对比度 |
0x81 |
包含两个字节,第一个0X81为命令,随后发送的一个字节为要设置的对比度的值。 这个值设置得越大屏幕就越亮。 |
设置显示开关 |
0x8D |
0XAE为关闭显示命令;0XAF为开启显示命令 |
电荷泵设置 |
0x81 |
包含2个字节,第一个为命令字,第二个为设置值,其中低位第三位为1,则开启电荷泵,为0则关闭。 在模块初始化的时候,这个必须要开启,否则是看不到屏幕显示的。 |
设置页地址 |
0xB0~0xB7 |
用于设置页地址,其低三位的值对应着页地址。 |
设置列地址低4位 |
0X00~0X0F |
用于设置显示时的起始列地址低四位。 |
设置列地址高4位 |
0X10~0X1F |
用于设置显示时的起始列地址高四位。 |
更多关于SSD1306的命令字的描述,见 SSD1306(OLED驱动芯片)指令详解
23.4. SPI-OLED显示实验¶
野火启明6M5开发板的扩展 SPI 接口电路图如图所示:
因为野火启明4M2开发板的扩展 SPI 接口被下载调试引脚占用,故采用GPIO-软件SPI的方式来测试实验。
野火启明4M2开发板的扩展 OLED 6线接口电路图如图所示:
野火启明2L1开发板的扩展 SPI 接口电路图如图所示:
因为对于OLED模块,主机只需要发送显示数据,它也只需要接受显示数据,所以我们只需要连接MOSI这条线即可。
开发板 |
OLED模块引脚 |
---|---|
启明6M5 |
|
启明4M2 |
|
启明2L1 |
|
使用瑞萨官方提供的FPS库进行编程,瑞萨官方提供的FPS库具有方便、快捷、简洁的特性。
23.4.1. 新建工程¶
- 对于 e2 studio 开发环境:
拷贝一份我们之前的 e2s 工程模板 05_Template, 然后将工程文件夹重命名为 “SPI_OLED”,最后再将它导入到我们的 e2 studio 工作空间中。
- 对于 Keil 开发环境:
拷贝一份我们之前的 Keil 工程模板 05_Template, 然后将工程文件夹重命名为 “SPI_OLED”,并进入该文件夹里面双击 Keil 工程文件,打开该工程。
工程新建好之后,在工程根目录的 “src” 文件夹下面新建 “spi_oled” 文件夹, 再进入 “spi_oled” 文件夹里面新建源文件和头文件:“bsp_spi_oled.c” 和 “bsp_spi_oled.h”,并添加好字库文件 “codetab.h”,具体代码见下。
整个工程文件结构如下:
SPI_OLED
├─ ......
└─ src
├─ spi_oled
│ ├─ bsp_spi_oled.c
│ ├─ bsp_spi_oled.h
| └─ codetab.h
└─ hal_entry.c
/************************************************************************************
* Description:
* 1. 128*64点整OLED模块功能演示程序的字表;
* 2. 字表由打包资料中的“取字软件”计算得出;
* 3. 取字方式 -- 共阴、列行式、逆向输出
*
*
*************************************************************************************/
/***************************16*16的点阵字体取模方式:共阴——列行式——逆向输出*********/
#ifndef __CODETAB_H__
#define __CODRTAB_H__
const unsigned char F16x16[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0xFE,0x92,0x92,0xFE,0x92,0x92,0xFE,0x00,0x42,0x4A,0xD2,0x6A,0x46,0xC0,0x00,
0x40,0xC4,0x44,0x44,0x3F,0x24,0x24,0x24,0x00,0x40,0x80,0x7F,0x00,0x01,0x00,0x00,/*"野",0*/
0x00,0x00,0xC0,0x38,0x00,0x00,0x00,0xFF,0x00,0x00,0x40,0x20,0x18,0x00,0x00,0x00,
0x80,0x81,0x40,0x20,0x10,0x0C,0x03,0x00,0x03,0x0C,0x10,0x20,0x40,0x80,0x80,0x00,/*"火",1*/
0x24,0x24,0xA4,0xFE,0xA3,0x22,0x00,0x22,0xCC,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,
0x08,0x06,0x01,0xFF,0x00,0x01,0x04,0x04,0x04,0x04,0x04,0xFF,0x02,0x02,0x02,0x00,/*"科",2*/
0x10,0x10,0x10,0xFF,0x10,0x90,0x08,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x08,0x00,
0x04,0x44,0x82,0x7F,0x01,0x80,0x80,0x40,0x43,0x2C,0x10,0x28,0x46,0x81,0x80,0x00,/*"技",3*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",6*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",6*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",7*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",7*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",0*/
0x84,0x84,0xFC,0x84,0x84,0x40,0x5E,0x50,0x50,0x50,0xDF,0x50,0x50,0x50,0x5E,0x00,
0x10,0x30,0x1F,0x08,0x08,0x00,0xFE,0x02,0x02,0x7F,0x02,0x7E,0x02,0x82,0xFE,0x00,/*"瑞",0*/
0x04,0xE4,0x24,0x24,0xA4,0x6F,0x04,0x24,0x64,0xAF,0x34,0xA4,0x64,0x24,0x04,0x00,
0x00,0xFF,0x00,0x11,0x22,0x9C,0x40,0x3F,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,/*"萨",1*/
0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00,
0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,/*"电",2*/
0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"子",3*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",6*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",6*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",7*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*" ",7*/
};
/************************************6*8的点阵************************************/
const unsigned char F6x8[][6] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};
/****************************************8*16的点阵************************************/
const unsigned char F8X16[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93
0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};
const unsigned char BMP1[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,
0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0x70,0x70,0x70,0xE0,0xC0,0x80,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x78,0x78,0x78,0xF8,
0xF8,0xF8,0xF8,0x78,0x78,0x78,0xF8,0xF8,0xF8,0xF8,0x00,0xF8,0xF8,0x78,0x78,0x78,
0x78,0x78,0x78,0x78,0x78,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,
0xFE,0xFE,0xFE,0xFE,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0x80,
0x00,0x00,0x00,0x00,0x3E,0xFF,0xC1,0xFF,0x7F,0x1F,0x7F,0xE6,0xE3,0xFF,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xFE,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xF0,0xE0,0xE0,0xFF,
0xFF,0xFF,0xFF,0xE0,0xE0,0xE0,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x60,0xF8,0xF8,0xF8,
0xF8,0xE0,0xF8,0xFE,0xFF,0x7F,0x1F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0xFC,0xFC,0xFC,0xFC,0xFC,0x18,0x00,0x00,0x00,0x00,0xFF,
0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xFC,0xFF,0xFF,
0x00,0x00,0x00,0x80,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0x7F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xC0,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xC1,0xC1,0xFF,
0xFF,0xFF,0xFF,0xC1,0xC1,0xC1,0xFF,0xFF,0xFF,0xFF,0xF8,0xF8,0xF8,0xF8,0xF9,0xF1,
0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xF0,0xF0,0xF0,0xF8,0xF8,0x38,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0xFF,
0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xE0,0xC0,0xE0,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x80,0xF0,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x8F,
0xE7,0xF3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFE,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC7,0xC7,0xC7,0xC7,0x87,0x83,0x87,
0xFF,0xFF,0xFF,0x83,0x83,0x87,0x87,0xC7,0xC7,0xC7,0x05,0x01,0x01,0x01,0x00,0x00,
0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x78,0x7F,0x7F,0x7F,0x3F,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x0E,0x0F,0x0F,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0xC0,0xFC,0xFF,
0xFF,0xFF,0x3F,0xFF,0xFF,0xFE,0xE0,0x80,0x00,0x00,0x01,0x07,0x07,0x0F,0x0F,0x1F,
0x1F,0x1F,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xF8,0xFF,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x7C,0xFF,
0xFF,0xFF,0xF8,0xF0,0xE0,0xF0,0xF0,0xFC,0xFE,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0xFF,0xFF,0xFF,0x07,0x07,0x87,0x87,0x87,0xC7,0xC7,0xC0,0x00,0x00,0x00,0x00,0x00,
0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF8,0xFE,0xFF,0xFF,0x3F,
0x0F,0x01,0x00,0x03,0x1F,0x7F,0xFF,0xFF,0xFC,0xF8,0xE0,0xC0,0x80,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFE,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x3F,0x0F,0x03,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x7E,0x7E,0x7E,0x3E,0x3E,0x3E,0x3E,0x1E,
0x1F,0x1F,0x1F,0x1F,0x1F,0x0F,0x0F,0x0F,0x0F,0x0F,0x03,0x30,0xF0,0xF0,0xE0,0xE0,
0xF0,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,
0xC0,0xE0,0xF0,0xF0,0xF8,0xFC,0xFE,0xFE,0xFF,0x7F,0x1F,0x0F,0x07,0x03,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x1F,0x3F,0x7F,0x7F,0xFF,0xFE,0xFC,
0xFC,0xF8,0xF8,0xF0,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07,
0x03,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x03,0x07,0x07,0x07,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
0x03,0x07,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
#endif
23.4.2. FSP配置¶
因为启明6M5/2L1开发板采用硬件SPI的方式,而启明4M2开发板采用GPIO模拟SPI的方式进行实验,所以FPS的配置也是不同的。
注解
关于硬件SPI与软件SPI的区别:
软件SPI:软件SPI需要用IO口模拟时序,这个模拟过程全部由CPU完成,为了能稳定的存入数据,可能插入软件延时,这个时间在读取数据量小的情况下不明显, 但是基本上你在读取过程中其他非中断、非异常程序是无法得到执行的。
硬件SPI:硬件SPI数据存储过程是不需要CPU参与的,程序中配置好SPI的访问时序,开启中断,CPU就可以在中断函数中搬移数据,省下了软件模拟IO的存取时间。
下面以启明6M5开发板为例,进行FSP配置。
首先打开 “41_SPI_OLED” 项目的 FSP 配置界面进行配置。
先配置CS,D/C引脚,在 FSP 配置界面里面点开 “Pins”-> “Poets”-> “P3”-> “P301” ,然后配置CS对应的IO引脚的 “Mode” 属性配置为 “Output mode (Initial High)”, 表示该引脚默认输出高电平,其他的属性默认即可。 D/C引脚也是按照这样进行配置。 启明2L1开发板与其类似,只是需要配置的引脚号不一样。 配置步骤如下图所示:
配置SPI,在 FSP 配置界面里面点开 “Pins”-> “Peripherals”-> “Connectivity:SPI”-> “SPI0”,选择A组并使能, 启明2L1开发板与其类似,只是选择的SPI模块为SPI1,A组。 配置步骤如下图所示:
接着在 FSP 配置界面里面依次点击 “Stacks” -> “New Stack” -> “Connectivity” -> “SPI” 来添加SPI模块, 配置步骤如下图所示:
按照如下图所示对 SPI 模块属性进行配置
SPI 模块的属性介绍如下:
SPI属性 |
描述 |
---|---|
Name |
模块实例名。设置为g_spi0_flash |
Channel |
通道。这里选择spi0 |
Receive Interrupt Priority |
接收中断优先级 |
Transmit Buffer Empty Interrupt Priority |
发送缓存区空中断优先级 |
Transfer Complete Interrupt Priority |
发送完成中断优先级 |
Error Interrupt Priority |
错误中断优先级 |
Operating Mode |
操作模式。可选SPI主机或从机 |
Clock Phase |
SPI时钟相位(设置CPHA) |
Clock Polarity |
SPI时钟极性(设置CPOL) |
Mode Fault Error |
模式错误检测。检测主从模式冲突 |
Bit Order |
位时序。MSB或LSB |
Callback |
中断回调函数。设置为spi_flash_callback |
SPI Mode |
SPI 模式。设置为SPI Operation |
Full or Transmit Only Mode |
全双工或仅发送模式选择 |
Slave Select Polarity |
从机选择引脚极性。一般是低电平有效 |
Select SSL(Slave Select) |
从机选择信号 |
MOSI Idle State |
总线空闲时 MOSI 电平 |
Parity Mode |
极性模式 |
Byte Swapping |
字节交换模式 |
Bitrate |
比特率 |
Clock Delay |
时钟延迟 |
SSL Negation Delay |
SSL失效延迟 |
Next Access Delay |
下一次访问延迟 |
在 FSP 配置界面里面点开 “Pins”-> “Poets”-> “P0”-> “P007” ,然后配置IO引脚的 “Mode” 属性配置为 “Output mode (Initial High)”, 表示该引脚默认输出高电平,其他的属性默认即可。其他三个引脚也是按照这样进行配置。 配置步骤如下图所示:
配置完成之后可以按下快捷键“Ctrl + S”保存, 最后点右上角的 “Generate Project Content” 按钮,让软件自动生成配置代码即可。
23.4.3. 对于启明6M5/2L1开发板的 “41_SPI_OLED” 工程:¶
当使用SPI接口时,我们通过 R_SPI_Write 这个函数,可以直接给我们的OLED模块发送指令,进行相应的操作。 R_SPI_Write 的函数原型如下:
fsp_err_t R_SPI_Write (spi_ctrl_t * const p_api_ctrl,
void const * p_src,
uint32_t const length,
spi_bit_width_t const bit_width)
发送一个数组的数据,p_src 是指需要发送的数据,length 是指发送数据的个数,bit_width 是指每个要发送的数据的位宽。
中断回调函数的原型已经在hal_data.h中进行了声明,我们只需要对其进行定义即可。
/** Callback used by SPI Instance. */
#ifndef spi0_callback
void spi0_callback(spi_callback_args_t * p_args);
#endif
在本次实验中,在中断回调函数中,我们可以通过检测发送完成事件来判断SPI传输是否完成,并且还封装了一个发送超时等待函数。
/**
* @brief 中断回调函数
* @param SPI中断回调参数指针
* @retval 无
*/
void spi0_callback(spi_callback_args_t *p_args)
{
if(p_args->event == SPI_EVENT_TRANSFER_COMPLETE)
{
g_transfer_complete = true;
}
}
/**
* @brief 发送超时等待函数
* @param 无
* @retval 无
*/
static bool SPIWaitgtc(void)
{
unsigned short wTimeout = 100;
while(!g_transfer_complete && wTimeout)
{
R_BSP_SoftwareDelay(1u, BSP_DELAY_UNITS_MICROSECONDS);
wTimeout--;
}
g_transfer_complete = false;
if(g_transfer_complete==false && wTimeout==0)
return false;
return true;
}
当我们需要对OLED发送命令/数据时,通过将D/C引脚配置成低电平来确定发送的为命令指令,而需要发送数据时,将D/C引脚配置成高电平。
void OLED_WrCmd(unsigned char cmd)
{
OLED_DC_Clr();
R_SPI_Write(&g_spi0_ctrl,&cmd,1,SPI_BIT_WIDTH_8_BITS);
SPIWaitgtc();
}
void OLED_WrDat(unsigned char dat)
{
OLED_DC_Set();
R_SPI_Write(&g_spi0_ctrl,&dat,1,SPI_BIT_WIDTH_8_BITS);
SPIWaitgtc();
}
对于CS与D/C引脚的操作我们也是封装了宏
#define OLED_CS_Pin BSP_IO_PORT_03_PIN_01
#define OLED_CS_Clr() R_IOPORT_PinWrite(&g_ioport_ctrl, OLED_CS_Pin, BSP_IO_LEVEL_LOW)
#define OLED_CS_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, OLED_CS_Pin, BSP_IO_LEVEL_HIGH)
#define OLED_DC_Pin BSP_IO_PORT_03_PIN_02
#define OLED_DC_Clr() R_IOPORT_PinWrite(&g_ioport_ctrl, OLED_DC_Pin, BSP_IO_LEVEL_LOW)
#define OLED_DC_Set() R_IOPORT_PinWrite(&g_ioport_ctrl, OLED_DC_Pin, BSP_IO_LEVEL_HIGH)
最后我们来看一下OLED的初始化,开头是通过 R_SPI_Open 函数来启动SPI0,接着是对OLED的寄存器进行操作,这些参数不需要去了解,默认也不需要修改。
void OLED_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SPI_Open(&g_spi0_ctrl,&g_spi0_cfg);//打开SPI模块
assert(FSP_SUCCESS == err);
R_BSP_SoftwareDelay(500u, BSP_DELAY_UNITS_MILLISECONDS);//延时500ms
OLED_CS_Clr();
OLED_WrCmd(0xae);
OLED_WrCmd(0xae);//--turn off oled panel
OLED_WrCmd(0x00);//---set low column address
OLED_WrCmd(0x10);//---set high column address
OLED_WrCmd(0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WrCmd(0x81);//--set contrast control register
OLED_WrCmd(0xcf); // Set SEG Output Current Brightness
OLED_WrCmd(0xa1);//--Set SEG/Column Mapping 0xa0,0xa1
OLED_WrCmd(0xc8);//Set COM/Row Scan Direction 0xc0,0xc8
OLED_WrCmd(0xa6);//--set normal display
OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
OLED_WrCmd(0x3f);//--1/64 duty
OLED_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WrCmd(0x00);//-not offset
OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WrCmd(0xd9);//--set pre-charge period
OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WrCmd(0xda);//--set com pins hardware configuration
OLED_WrCmd(0x12);
OLED_WrCmd(0xdb);//--set vcomh
OLED_WrCmd(0x40);//Set VCOM Deselect Level
OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WrCmd(0x02);//
OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
OLED_WrCmd(0x14);//--set(0x10) disable
OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)
OLED_WrCmd(0xaf);//--turn on oled panel
OLED_Fill(0x00);//清屏
OLED_SetPos(0,0);
}
23.4.4. 对于启明4M2开发板的 “41_SPI_OLED” 工程:¶
对于四个要用来模拟SPI的引脚,我们也是封装了宏
#define SPI_SCK_Pin BSP_IO_PORT_06_PIN_01
#define SPI_SCK_LOW() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_SCK_Pin, BSP_IO_LEVEL_LOW)
#define SPI_SCK_HIGH() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_SCK_Pin, BSP_IO_LEVEL_HIGH)
#define SPI_MOSI_Pin BSP_IO_PORT_06_PIN_02
#define SPI_MOSI_LOW() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_MOSI_Pin, BSP_IO_LEVEL_LOW)
#define SPI_MOSI_HIGH() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_MOSI_Pin, BSP_IO_LEVEL_HIGH)
#define SPI_CS_Pin BSP_IO_PORT_00_PIN_07
#define SPI_CS_LOW() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_CS_Pin, BSP_IO_LEVEL_LOW)
#define SPI_CS_HIGH() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_CS_Pin, BSP_IO_LEVEL_HIGH)
#define SPI_DC_Pin BSP_IO_PORT_00_PIN_08
#define SPI_DC_LOW() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_DC_Pin, BSP_IO_LEVEL_LOW)
#define SPI_DC_HIGH() R_IOPORT_PinWrite(&g_ioport_ctrl, SPI_DC_Pin, BSP_IO_LEVEL_HIGH)
根据SSD1306的时序图,在SCLK信号为地电平的时候,改变MOSI的电平状态,输出完数据后将其拉高,延时一段时间后进行拉低SCLK,如此循环8次便可将一字节的数据传输出去。
/**
* @brief 模拟SPI发送数据函数
* @param data:待发送数据
* @retval 无
*/
void SPI_WriteByte(unsigned char data)
{
unsigned char i = 0;
unsigned char temp = 0;
for(i=0; i<8; i++)
{
temp = ((data&0x80)==0x80)? 1:0;
data = data<<1;
SPI_SCK_LOW();
if(temp)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
R_BSP_SoftwareDelay(1u, BSP_DELAY_UNITS_MICROSECONDS);
SPI_SCK_HIGH();
R_BSP_SoftwareDelay(1u, BSP_DELAY_UNITS_MICROSECONDS);
}
SPI_SCK_HIGH();
}
同样的,模拟的OLED发送指令/数据函数与 OLED发送指令数据函数 类似,如下
void OLED_WrCmd(unsigned char cmd)//写命令
{
SPI_DC_LOW();
SPI_WriteByte(cmd);
}
void OLED_WrDat(unsigned char dat)//写数据
{
SPI_DC_HIGH();
SPI_WriteByte(dat);
}
OLED的初始化,启明4M2开发板与启明6M5/2L1类似。
void OLED_Init(void)
{
SPI_CS_HIGH();
SPI_SCK_HIGH();
R_BSP_SoftwareDelay(100u, BSP_DELAY_UNITS_MICROSECONDS);
SPI_CS_LOW();//拉高CS后拉低CS,选中OLED
OLED_WrCmd(0xae);
OLED_WrCmd(0xae);//--turn off oled panel
OLED_WrCmd(0x00);//---set low column address
OLED_WrCmd(0x10);//---set high column address
OLED_WrCmd(0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WrCmd(0x81);//--set contrast control register
OLED_WrCmd(0xcf); // Set SEG Output Current Brightness
OLED_WrCmd(0xa1);//--Set SEG/Column Mapping 0xa0,0xa1
OLED_WrCmd(0xc8);//Set COM/Row Scan Direction 0xc0,0xc8
OLED_WrCmd(0xa6);//--set normal display
OLED_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
OLED_WrCmd(0x3f);//--1/64 duty
OLED_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WrCmd(0x00);//-not offset
OLED_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
OLED_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WrCmd(0xd9);//--set pre-charge period
OLED_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WrCmd(0xda);//--set com pins hardware configuration
OLED_WrCmd(0x12);
OLED_WrCmd(0xdb);//--set vcomh
OLED_WrCmd(0x40);//Set VCOM Deselect Level
OLED_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WrCmd(0x02);//
OLED_WrCmd(0x8d);//--set Charge Pump enable/disable
OLED_WrCmd(0x14);//--set(0x10) disable
OLED_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
OLED_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7)
OLED_WrCmd(0xaf);//--turn on oled panel
OLED_Fill(0x00);
OLED_SetPos(0,0);
}
23.4.5. hal_entry函数¶
在hal_entry函数中,初始化OLED。
void hal_entry(void)
{
/* TODO: add your own code here */
unsigned char i;
extern const unsigned char BMP1[];
OLED_Init();//初始化
while(1)
{
OLED_Fill(0xff);//填充屏幕
R_BSP_SoftwareDelay(2u, BSP_DELAY_UNITS_SECONDS);
OLED_CLS();//清屏
for(i=0; i<8; i++)//通过点阵显示汉字 -- i表示子表中汉字的位置
{
OLED_16x16CN(i*16,0,i);
OLED_16x16CN(i*16,4,i+8);
}
R_BSP_SoftwareDelay(2u, BSP_DELAY_UNITS_SECONDS);
OLED_CLS();
//显示不同字体大小的英文
OLED_6x8Str(0,1,(unsigned char *)"www.embedfire.com");
OLED_8x16Str(0,2,(unsigned char *)"Wildfire Tech");
OLED_8x16Str(10,4,(unsigned char *)"SPI-OLED");
R_BSP_SoftwareDelay(4u, BSP_DELAY_UNITS_SECONDS);
OLED_CLS();
//显示图片
OLED_BMP(0,0,128,8,(unsigned char *)BMP1);
R_BSP_SoftwareDelay(4u, BSP_DELAY_UNITS_SECONDS);
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
在循环中点亮屏幕,2秒后熄灭屏幕,然后使用 OLED_16x16CN 函数显示中文,使用 OLED_6x8Str 函数测试6*8字符,使用 OLED_8x16Str函数测试8*16字符,最后只用 OLED_BMP 函数测试BMP位图显示。
把代码下载后,可以看到OLED屏幕上由 清屏-> 显示中文 -> 显示英文 -> 显示图片 的顺序循环显示。
启明6M5/2L1开发板 SPI_OLED 实验现象:
启明4M2开发板 SPI_OLED 实验现象: