0.96英寸OLED显示屏(I2C接口)
在当前的嵌入式市场上,有一种0.96英寸的OLED显示屏非常流行,这里就来讨论一下如何通过LPC824驱动它。目前该OLED屏流行两种接口,一种是SPI接口,另一种是I2C接口。这里仅讨论I2C接口的,其外形如下图所示。

该屏为128X64的点阵屏,横向有128个像数点,纵向有64个像数点。目前市场上有白色、蓝色和黄蓝双色等显示颜色可选。
该OLED屏所使用的驱动芯片型号为SSD1306,其显示原理如下所示。

首先通过通信接口(比如I2C)接收来自单片机的一个字节数据, 然后通过判断数据的D/C#位来确定是命令还是数据。命令用于控制显示的地址等等,数据则存入GDDRAM中去屏幕上显示。显示屏上横向的X坐标是以像数作为单位的,从左到右分别是0~127。但纵向则不同,纵向的Y坐标是以页(Page)为单位的,从上到下分别是0~7。其中,每页用8位二进制数来表征该页中某一列上显示的像数,从下往上排列,即高位在下低位在上。值为1时点亮该像数,为0时熄灭。通常在显示ASCII码时,每个字符需要用6列8行来显示,即需要连续接收6字节显示数据才能显示一个ASCII码字符(如上图中的字符A,就使用了6个字节进行显示)。
下面来看I2C接口的通信时序,如下图所示。

需要注意的是,其I2C传输数据的格式有两种。一种是控制字节与数据字节交替传输,另一种是先发一个控制字节,后面跟着连续的数据字节。这两种模式的选择由控制字节中的Co位来确定,其值为1时表示交替传输,为0时表示连续传输。通常情况下会选择连续传输方式(即Co值为0)。同时,D/C#位紧跟在Co位后面发,值为0时表示后面收到的字节是控制命令,为1时是数据。命令字节只包含Co位和D/C#位,其余位全部为0(见上图中的Contol byte)。此外,该显示模块的器件地址为011110+SA0,其中的SA0为外部引脚,通过接高电平或地的方式进行选择(即在I2C总线上最多可挂两块屏)。其他的就跟传统I2C传输格式一样了。
接下来根据前面的要求封装出两个函数。一个是写命令函数,如下。
void oled_writeCmd(uint8_t cmd) { while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x78; //要写入的器件地址(写方向) LPC_I2C0->MSTCTL = 1<<1; //启动传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x00; //将要写入的是命令 LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = cmd; //要写入的命令(1字节) LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTCTL = 1<<2; //停止传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 }
一个是写数据函数,如下。
void oled_writeData(uint8_t data) { while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x78; //要写入的器件地址(写方向) LPC_I2C0->MSTCTL = 1<<1; //启动传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x40; //将要写入的是数据 LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = data; //要写入的数据(1字节) LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTCTL = 1<<2; //停止传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 }
下面是官方手册给出的显示屏初始化过程(内部自举方式),只需要按步骤进行相应的控制命令写入就可以了。

结合上面的初始化过程,下面给出其对应的初始化函数。
void oled_init(void) { delay_ms(100); //Delay 100ms(Recommended) oled_writeCmd(0xAE); //Set Display Off oled_writeCmd(0xD5); oled_writeCmd(0x80); //Set Display Clock Divide Ratio/Oscillator Frequency oled_writeCmd(0xA8); oled_writeCmd(0x3F); //Set Multiplex Ratio oled_writeCmd(0xD3); oled_writeCmd(0x00); //Set Display Offset oled_writeCmd(0x40); //Set Display Start Line oled_writeCmd(0xA1); //Set Segment Re-Map oled_writeCmd(0xC8); //Set COM Output Scan Direction oled_writeCmd(0xDA); oled_writeCmd(0x12); //Set COM Pins Hardware Configuration oled_writeCmd(0x81); oled_writeCmd(0xCF); //Set Contrast Control oled_writeCmd(0xD9); oled_writeCmd(0xF1); //Set Pre-Charge Period oled_writeCmd(0xDB); oled_writeCmd(0x30); //Set VCOMH Deselect Level oled_writeCmd(0xA4); //Set Entire Display On/Off oled_writeCmd(0xA6); //Set Normal/Inverse Display oled_writeCmd(0x8D); oled_writeCmd(0x14); //Set Charge Pump oled_writeCmd(0xAF); //Set Display On delay_ms(100); //Delay 100ms(Recommended) }
完成初始化后,就可以对显示屏发送显示坐标和显示数据了。在设置显示位置时,需要分横坐标和页坐标来进行,其中横坐标需要分高低四位进行两次写入。下表是官方手册中给出的显示坐标设置要求。

结合上述要求,下面给出一个设置显示位置的函数。
void oled_setLocation(uint8_t x, uint8_t page) { oled_writeCmd(0x00 | (x & 0x0F)); //写入x坐标的低四位值 oled_writeCmd(0x10 | ((x & 0xF0) >> 4)); //写入x坐标的高四位值 oled_writeCmd(0xB0 | page); //写入页坐标的值 }
下面来看一个实际的例子,通过LPC824驱动OLED模拟显示一个手机屏幕,其中有图像、数字、英文字符和中文字符。完整代码如下。
#include <LPC82x.h> #include <stdlib.h> #define nor 6 #define lar 8 //****************ASCII码(宽6像素,高8像素)************************* const uint8_t oled_6x8[][6] = { 0x00,0x00,0x00,0x00,0x00,0x00,// 0 0x00,0x00,0x00,0x2F,0x00,0x00,// ! 1 0x00,0x00,0x07,0x00,0x07,0x00,// " 2 0x00,0x14,0x7F,0x14,0x7F,0x14,// # 3 0x00,0x24,0x2A,0x7F,0x2A,0x12,// $ 4 0x00,0x23,0x13,0x08,0x64,0x62,// % 5 0x00,0x36,0x49,0x55,0x22,0x50,// & 6 0x00,0x00,0x00,0x07,0x00,0x00,// ' 7 0x00,0x00,0x1C,0x22,0x41,0x00,// ( 8 0x00,0x00,0x41,0x22,0x1C,0x00,// ) 9 0x00,0x14,0x08,0x3E,0x08,0x14,// * 10 0x00,0x08,0x08,0x3E,0x08,0x08,// + 11 0x00,0x00,0x00,0xA0,0x60,0x00,// , 12 0x00,0x08,0x08,0x08,0x08,0x08,// - 13 0x00,0x00,0x60,0x60,0x00,0x00,// . 14 0x00,0x20,0x10,0x08,0x04,0x02,// / 15 0x00,0x3E,0x51,0x49,0x45,0x3E,// 0 16 0x00,0x00,0x42,0x7F,0x40,0x00,// 1 17 0x00,0x42,0x61,0x51,0x49,0x46,// 2 18 0x00,0x21,0x41,0x45,0x4B,0x31,// 3 19 0x00,0x18,0x14,0x12,0x7F,0x10,// 4 20 0x00,0x27,0x45,0x45,0x45,0x39,// 5 21 0x00,0x3C,0x4A,0x49,0x49,0x30,// 6 22 0x00,0x01,0x71,0x09,0x05,0x03,// 7 23 0x00,0x36,0x49,0x49,0x49,0x36,// 8 24 0x00,0x06,0x49,0x49,0x29,0x1E,// 9 25 0x00,0x00,0x36,0x36,0x00,0x00,// : 26 0x00,0x00,0x56,0x36,0x00,0x00,// ; 27 0x00,0x08,0x14,0x22,0x41,0x00,// < 28 0x00,0x14,0x14,0x14,0x14,0x14,// = 29 0x00,0x00,0x41,0x22,0x14,0x08,// > 30 0x00,0x02,0x01,0x51,0x09,0x06,// ? 31 0x00,0x3E,0x49,0x55,0x59,0x2E,// @ 32 0x00,0x7C,0x12,0x11,0x12,0x7C,// A 33 0x00,0x7F,0x49,0x49,0x49,0x36,// B 34 0x00,0x3E,0x41,0x41,0x41,0x22,// C 35 0x00,0x7F,0x41,0x41,0x22,0x1C,// D 36 0x00,0x7F,0x49,0x49,0x49,0x41,// E 37 0x00,0x7F,0x09,0x09,0x09,0x01,// F 38 0x00,0x3E,0x41,0x49,0x49,0x7A,// G 39 0x00,0x7F,0x08,0x08,0x08,0x7F,// H 40 0x00,0x00,0x41,0x7F,0x41,0x00,// I 41 0x00,0x20,0x40,0x41,0x3F,0x01,// J 42 0x00,0x7F,0x08,0x14,0x22,0x41,// K 43 0x00,0x7F,0x40,0x40,0x40,0x40,// L 44 0x00,0x7F,0x02,0x0C,0x02,0x7F,// M 45 0x00,0x7F,0x04,0x08,0x10,0x7F,// N 46 0x00,0x3E,0x41,0x41,0x41,0x3E,// O 47 0x00,0x7F,0x09,0x09,0x09,0x06,// P 48 0x00,0x3E,0x41,0x51,0x21,0x5E,// Q 49 0x00,0x7F,0x09,0x19,0x29,0x46,// R 50 0x00,0x46,0x49,0x49,0x49,0x31,// S 51 0x00,0x01,0x01,0x7F,0x01,0x01,// T 52 0x00,0x3F,0x40,0x40,0x40,0x3F,// U 53 0x00,0x1F,0x20,0x40,0x20,0x1F,// V 54 0x00,0x3F,0x40,0x38,0x40,0x3F,// W 55 0x00,0x63,0x14,0x08,0x14,0x63,// X 56 0x00,0x07,0x08,0x70,0x08,0x07,// Y 57 0x00,0x61,0x51,0x49,0x45,0x43,// Z 58 0x00,0x00,0x7F,0x41,0x41,0x00,// [ 59 0x00,0x02,0x04,0x08,0x10,0x20,// \ 60 0x00,0x00,0x41,0x41,0x7F,0x00,// ] 61 0x00,0x04,0x02,0x01,0x02,0x04,// ^ 62 0x00,0x40,0x40,0x40,0x40,0x40,// _ 63 0x00,0x00,0x01,0x02,0x04,0x00,// ` 64 0x00,0x20,0x54,0x54,0x54,0x78,// a 65 0x00,0x7F,0x48,0x44,0x44,0x38,// b 66 0x00,0x38,0x44,0x44,0x44,0x20,// c 67 0x00,0x38,0x44,0x44,0x48,0x7F,// d 68 0x00,0x38,0x54,0x54,0x54,0x18,// e 69 0x00,0x08,0x7E,0x09,0x01,0x02,// f 70 0x00,0x18,0xA4,0xA4,0xA4,0x7C,// g 71 0x00,0x7F,0x08,0x04,0x04,0x78,// h 72 0x00,0x00,0x44,0x7D,0x40,0x00,// i 73 0x00,0x40,0x80,0x84,0x7D,0x00,// j 74 0x00,0x7F,0x10,0x28,0x44,0x00,// k 75 0x00,0x00,0x41,0x7F,0x40,0x00,// l 76 0x00,0x7C,0x04,0x18,0x04,0x78,// m 77 0x00,0x7C,0x08,0x04,0x04,0x78,// n 78 0x00,0x38,0x44,0x44,0x44,0x38,// o 79 0x00,0xFC,0x24,0x24,0x24,0x18,// p 80 0x00,0x18,0x24,0x24,0x18,0xFC,// q 81 0x00,0x7C,0x08,0x04,0x04,0x08,// r 82 0x00,0x48,0x54,0x54,0x54,0x20,// s 83 0x00,0x04,0x3F,0x44,0x40,0x20,// t 84 0x00,0x3C,0x40,0x40,0x20,0x7C,// u 85 0x00,0x1C,0x20,0x40,0x20,0x1C,// v 86 0x00,0x3C,0x40,0x30,0x40,0x3C,// w 87 0x00,0x44,0x28,0x10,0x28,0x44,// x 88 0x00,0x1C,0xA0,0xA0,0xA0,0x7C,// y 89 0x00,0x44,0x64,0x54,0x4C,0x44,// z 90 0x00,0x00,0x08,0x7F,0x41,0x00,// { 91 0x00,0x00,0x00,0x7F,0x00,0x00,// | 92 0x00,0x00,0x41,0x7F,0x08,0x00,// } 93 0x00,0x08,0x04,0x08,0x10,0x08,// ~ 94 }; //****************ASCII码(宽8像素,高16像素)************************* const uint8_t oled_8x16[][16] = { 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,0x16,0x0E,0x00,0x16,0x0E,0x00,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 0x00,0x00,0x00,0x16,0x0E,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, 0x00,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,0xC0,0xC0,0x00,0x00,0x00, 0x00,0x00,0x80,0xB0,0x70,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,0x20,0x10,0x08,0x04,0x08,0x10,0x20, 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,0x04,0x08,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 0x00,0x80,0x80,0x00,0x80,0x80,0x00,0x00, 0x00,0x20,0x3F,0x21,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,0x80,0x40,0x40,0x80,0x00,0x00,0x80, 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,// ~ 94 }; //****************天线信号(宽6像素,高8像素)************************* const uint8_t ANT_6x8[] = { 0x00,0xC0,0xE0,0x00,0xE0,0xF0,0x00,0xF0,0xF8,0x00,0xF8,0xFC,0x00,0xFC,0xFE,0x00,0xFF,0xFF, }; //****************电池图标(宽6像素,高8像素)************************* const uint8_t BAT_6x8[] = { 0x00,0x00,0x3C,0x3C,0xFF,0x81,0x81,0xBD,0xBD,0xBD,0x81,0xBD, \ 0xBD,0xBD,0x81,0xBD,0xBD,0xBD,0x81,0xBD,0xBD,0xBD,0x81,0xFF, }; //****************四个汉字(宽16像素,高16像素)************************* const uint8_t chr[][32] = { 0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00, 0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00,/*"中",0*/ 0x00,0xFE,0x02,0x12,0x92,0x92,0x92,0xF2,0x92,0x92,0x92,0x12,0x02,0xFE,0x00,0x00, 0x00,0xFF,0x40,0x48,0x48,0x48,0x48,0x4F,0x48,0x4A,0x4C,0x48,0x40,0xFF,0x00,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*/ 0x00,0x80,0x60,0xF8,0x07,0x00,0x04,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x04,0x00, 0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0xF9,0x49,0x49,0x49,0x49,0x49,0xF9,0x00,0x00,/*"信",3*/ }; //*************************I2C初始化********************************** void i2c_init() { LPC_SYSCON->SYSAHBCLKCTRL |= 1<<7; //开启SWM时钟 LPC_SWM->PINENABLE0 &= ~(0x3<<11); //使能I2C0引脚 LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<7); //关闭SWM时钟 LPC_IOCON->PIO0_10 = 0x80; //配置I2C0的SCL引脚为标准/快速模式(默认值 ) LPC_IOCON->PIO0_11 = 0x80; //配置I2C0的SDA引脚为标准/快速模式(默认值 ) LPC_SYSCON->SYSAHBCLKCTRL |= 1<<5; //开启I2C0时钟 LPC_SYSCON->PRESETCTRL &= ~(1<<6); //开启I2C0外设复位 LPC_SYSCON->PRESETCTRL |= 1<<6; //关闭I2C0外设复位 LPC_I2C0->CLKDIV = 0x09; //配置SCL时钟为系统时钟的10分频 LPC_I2C0->MSTTIME = 0x00; //将每个SCL高位和低位时间都设为2个时钟周期(默认值 ) LPC_I2C0->CFG |= 1<<0; //使能主机模式 } //***************************写命令************************************ void oled_writeCmd(uint8_t cmd) { while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x78; //要写入的器件地址(写方向) LPC_I2C0->MSTCTL = 1<<1; //启动传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x00; //将要写入的是命令 LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = cmd; //要写入的命令(1字节) LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTCTL = 1<<2; //停止传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 } //***************************写数据************************************ void oled_writeData(uint8_t data) { while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x78; //要写入的器件地址(写方向) LPC_I2C0->MSTCTL = 1<<1; //启动传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = 0x40; //将要写入的是数据 LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTDAT = data; //要写入的数据(1字节) LPC_I2C0->MSTCTL = 1<<0; //启动重新传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x4)abort(); //若返回的状态不为空闲则终止 LPC_I2C0->MSTCTL = 1<<2; //停止传输 while(!(LPC_I2C0->STAT & 0x01)); //等待I2C的状态就绪 if((LPC_I2C0->STAT & 0xE) != 0x0)abort(); //若返回的状态不为空闲则终止 } //***************************延时函数************************************ void delay_ms(uint32_t ms) { SysTick->LOAD = (((12000)*ms)-1); //载入初始值 SysTick->VAL = 0; //写当前值寄存器使其清零 SysTick->CTRL |= (1<<0); //启动定时器,选择半系统时钟 while(!(SysTick->CTRL & 0x10000)); //循环查询,等待定时时间到 SysTick->CTRL &= ~(1<<0); //关闭定时器 } //************************oled初始化*********************************** void oled_init(void) { delay_ms(100); //Delay 100ms(Recommended) oled_writeCmd(0xAE); //Set Display Off oled_writeCmd(0xD5); oled_writeCmd(0x80); //Set Display Clock Divide Ratio/Oscillator Frequency oled_writeCmd(0xA8); oled_writeCmd(0x3F); //Set Multiplex Ratio oled_writeCmd(0xD3); oled_writeCmd(0x00); //Set Display Offset oled_writeCmd(0x40); //Set Display Start Line oled_writeCmd(0xA1); //Set Segment Re-Map oled_writeCmd(0xC8); //Set COM Output Scan Direction oled_writeCmd(0xDA); oled_writeCmd(0x12); //Set COM Pins Hardware Configuration oled_writeCmd(0x81); oled_writeCmd(0xCF); //Set Contrast Control oled_writeCmd(0xD9); oled_writeCmd(0xF1); //Set Pre-Charge Period oled_writeCmd(0xDB); oled_writeCmd(0x30); //Set VCOMH Deselect Level oled_writeCmd(0xA4); //Set Entire Display On/Off oled_writeCmd(0xA6); //Set Normal/Inverse Display oled_writeCmd(0x8D); oled_writeCmd(0x14); //Set Charge Pump oled_writeCmd(0xAF); //Set Display On delay_ms(100); //Delay 100ms(Recommended) } //*************************设置显示坐标******************************** void oled_setLocation(uint8_t x, uint8_t page) { oled_writeCmd(0x00 | (x & 0x0F)); //写入x坐标的低四位值 oled_writeCmd(0x10 | ((x & 0xF0) >> 4)); //写入x坐标的高四位值 oled_writeCmd(0xB0 | page); //写入页坐标的值 } //***************************清屏函数********************************** void oled_clear(void) { uint8_t i,j; for(j=0; j<8; j++) //循环写入一共8页 { oled_setLocation(0, j); //写完一行页自动加1 for(i=0; i<128; i++) oled_writeData(0x0); //循环写入每行128个数据0 } } //*************************显示一个字符******************************** void oled_showChar(int8_t x, int8_t page, uint8_t chr, uint8_t size) { uint8_t i; if (size == lar) //大字体,一个字符占两页 { oled_setLocation(x, page); //设置显示坐标位置 for(i=0; i<8; i++) oled_writeData(oled_8x16[chr-0x20][i]); //循环写入第一页显示数据 oled_setLocation(x, page+1); //设置第二页显示 for(i=0; i<8; i++) oled_writeData(oled_8x16[chr-0x20][i+8]);//循环写入第二页显示数据 } else if(size == nor) //常规字体,一个字符占一页 { oled_setLocation(x, page); //设置显示坐标位置 for(i=0; i<6; i++) oled_writeData(oled_6x8[chr-0x20][i]); //循环写入显示数据 } } //**************************显示字符串********************************* void oled_showString(uint8_t x, uint8_t page, char *str, uint8_t size) { uint8_t i; for(i=0; str[i] != '\0'; i++) //在未检测到字符串结尾时循环写入显示数据 oled_showChar(x + i*size, page, str[i], size); } //***************************显示汉字********************************** void oled_showChinese(uint8_t x, uint8_t page, const uint8_t *chr) { uint8_t i,j; for(j=0; j<2; j++) //一个汉字字符占两页 { oled_setLocation(x, page + j); //设置显示坐标位置 for(i=0; i<16; i++) oled_writeData(chr[16*j+i]); //循环写入2X16个显示数据 } } //*************************显示天线信号******************************** void oled_showANT(void) { uint8_t i; oled_setLocation(0, 0); //设置显示坐标 for(i=0; i<18; i++) oled_writeData(ANT_6x8[i]); //写入显示天线信号数据 } //*************************显示电池图标******************************** void oled_showBAT(void) { uint8_t i; oled_setLocation(103, 0); //设置显示坐标 for(i=0; i<24; i++) oled_writeData(BAT_6x8[i]); //写入显示电池图标数据 } //***************************主函数************************************ int main(void) { i2c_init(); //调用I2C初始化函数 oled_init(); //调用OLED初始化函数 oled_clear(); //调用清屏函数 oled_showANT(); //调用天线信号显示 oled_showBAT(); //调用电池图标显示 oled_showChinese(25, 2, chr[0]); //调用显示“中” oled_showChinese(45, 2, chr[1]); //调用显示“国” oled_showChinese(65, 2, chr[2]); //调用显示“电” oled_showChinese(85, 2, chr[3]); //调用显示“信” oled_showString(33, 5, "2026-05-24", nor);//调用显示日期,常规大小 oled_showString(0, 6, "MENU", lar); //调用显示“MENU”,大字体 oled_showString(103, 6, "MSN", lar); //调用显示“MSN”,大字体 while(1); //无限循环 }
最终的显示效果如下图所示。

上述代码中的所有字符数据,都是通过取模软件获取的。取模软件网上有很多,常见的有“字模提取”、“牧码字模”、“PCtoLCD2002”等。使用时需要注意设置成"列行模式"(即纵向取模),数据为“逆向方式”(即低位在上),并注意选择合适的分辨率。

浙公网安备 33010602011771号