由于中景园电子给出的例程不够全面,因此特地花时间重新整理了一下代码,并加上了其他的功能。本文记录了使用模拟四线 SPI 协议驱动 OLED 的代码。

使用软件:IAR FOR STM8

编程方式:固件库

硬件配套:STM8S105C6T6实验板

字模软件:PCtoLCD2002

图片转位图(bmp)格式软件:image2lcd

1 oled.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef __OLED_SPI_H
#define __OLED_SPI_H

/*******************模拟四线 SPI 驱动 0.96寸OLED(128x64)**********************/

/* Includes ------------------------------------------------------------------*/

#include "stm8s.h"
#include "oled_font.h"

/* Enum ----------------------------------------------------------------------*/

enum page_num {PAGE0 = 0, PAGE1, PAGE2, PAGE3, PAGE4, PAGE5, PAGE6, PAGE7};
enum roll_frame {FRAME0 = 0, FRAME1, FRAME2, FRAME3, FRAME4, FRAME5, FRAME6, FRAME7};

/* Defines -------------------------------------------------------------------*/

#define OLED_CMD 0u /* 命令模式 */
#define OLED_DATA 1u /* 数据模式 */

#define OLED_CATHODE 0u /* 阴码 */
#define OLED_ANODE 1u /* 阳码 */

#define OLED_FONT_SIZE_12 12
#define OLED_FONT_SIZE_16 16

#define OLED_SCROLL_RIGHT 0u
#define OLED_SCROLL_LEFT 1u

#define OLED_SCK_PORT (GPIOB)
#define OLED_SCK_PIN (GPIO_PIN_5) /* PB5 (OLED_D0) */

#define OLED_SDA_PORT (GPIOB)
#define OLED_SDA_PIN (GPIO_PIN_4) /* PB4 (OLED_D1) */

#define OLED_RES_PORT (GPIOD)
#define OLED_RES_PIN (GPIO_PIN_0) /* PD0 (OLED_RES) */

#define OLED_DC_PORT (GPIOG)
#define OLED_DC_PIN (GPIO_PIN_1) /* PG1 (OLED_DC) */

#define OLED_CS_PORT (GPIOC)
#define OLED_CS_PIN (GPIO_PIN_6) /* PC6 (OLED_CS) */

#define OLED_SCK_LOW() GPIO_WriteLow (OLED_SCK_PORT, OLED_SCK_PIN)
#define OLED_SCK_HIGH() GPIO_WriteHigh(OLED_SCK_PORT, OLED_SCK_PIN)

#define OLED_SDA_LOW() GPIO_WriteLow (OLED_SDA_PORT, OLED_SDA_PIN)
#define OLED_SDA_HIGH() GPIO_WriteHigh(OLED_SDA_PORT, OLED_SDA_PIN)

#define OLED_RES_LOW() GPIO_WriteLow (OLED_RES_PORT, OLED_RES_PIN)
#define OLED_RES_HIGH() GPIO_WriteHigh(OLED_RES_PORT, OLED_RES_PIN)

#define OLED_DC_CMD() GPIO_WriteLow (OLED_DC_PORT, OLED_DC_PIN)
#define OLED_DC_DATA() GPIO_WriteHigh(OLED_DC_PORT, OLED_DC_PIN)

#define OLED_CS_LOW() GPIO_WriteLow (OLED_CS_PORT, OLED_CS_PIN)
#define OLED_CS_HIGH() GPIO_WriteHigh(OLED_CS_PORT, OLED_CS_PIN)

/* Functions -----------------------------------------------------------------*/

static void OLED_DLY_ms (uint32_t ms);

static void OLED_SPI_WriteByte (uint8_t mode, uint8_t data);
void OLED_SPI_WriteCmd (uint8_t cmd);
void OLED_SPI_WriteData (uint8_t data);
static void OLED_SPI_GPIO_Init (void);
void OLED_SPI_Init (void);

void OLED_ON (void);
void OLED_OFF (void);

void OLED_Refresh_Gram (void);
void OLED_Clear (void);

static void OLED_DrawPoint (uint8_t x, uint8_t y, uint8_t mode);
static void OLED_Fill (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode);

static void OLED_ShowChar (uint8_t x, uint8_t y, uint8_t ch, uint8_t size, uint8_t mode);
void OLED_ShowString (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size);

static void OLED_ShowChar_CH (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t mode);
void OLED_ShowChinese (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t num);

void OLED_ShowPic (uint8_t x, uint8_t y, const uint8_t *pic, uint8_t width, uint8_t height, uint8_t mode);

void OLED_VerHorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t scroll_offset, uint8_t dir);
void OLED_HorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t dir);

#endif /* __OLED_SPI_H */

2 oled.c

根据不同函数的功能,分为以下几类:

2.1 与初始化相关的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "oled_spi.h"

uint8_t OLED_GRAM[128][8];

/*************************************************************************
OLED 专用软件延时函数
--------------------------------------------------------------------------
ms:软件延时长度
*************************************************************************/
static void OLED_DLY_ms (uint32_t ms)
{
uint32_t a;

while (ms)
{
a = 200;
while (a--);
ms--;
}
}

/*************************************************************************
往 OLED 中写入一字节数据
--------------------------------------------------------------------------
mode:传输模式 data:一字节数据
*************************************************************************/
static void OLED_SPI_WriteByte (uint8_t mode, uint8_t data)
{
BitStatus bit;
uint8_t i;

if (mode == OLED_CMD)
{
OLED_DC_CMD();
}
else
{
OLED_DC_DATA();
}

OLED_SCK_LOW();

for (i = 0; i < 8; i++)
{
OLED_SCK_LOW();
bit = (BitStatus)(data & 0x80);

if (bit == RESET)
{
OLED_SDA_LOW();
}
else
{
OLED_SDA_HIGH();
}

OLED_SCK_HIGH();
data <<= 1;
}

OLED_SCK_HIGH();
OLED_DC_DATA();
}

/*************************************************************************
往 OLED 写入命令字
--------------------------------------------------------------------------
cmd:命令字
*************************************************************************/
void OLED_SPI_WriteCmd (uint8_t cmd)
{
OLED_SPI_WriteByte(OLED_CMD, cmd);
}

/*************************************************************************
往 OLED 写入数据字
--------------------------------------------------------------------------
data:数据字
*************************************************************************/
void OLED_SPI_WriteData (uint8_t data)
{
OLED_SPI_WriteByte(OLED_DATA, data);
}

/*************************************************************************
初始化 OLED 引脚
--------------------------------------------------------------------------
无参数
*************************************************************************/
static void OLED_SPI_GPIO_Init (void)
{
GPIO_Init(OLED_SCK_PORT, OLED_SCK_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(OLED_SDA_PORT, OLED_SDA_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(OLED_RES_PORT, OLED_RES_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(OLED_DC_PORT, OLED_DC_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
GPIO_Init(OLED_CS_PORT, OLED_CS_PIN, GPIO_MODE_OUT_PP_HIGH_FAST);
}

/*************************************************************************
初始化 OLED
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_SPI_Init (void)
{
OLED_SPI_GPIO_Init();
OLED_CS_LOW();

OLED_SCK_HIGH();
OLED_RES_LOW();
OLED_DLY_ms (100);
OLED_RES_HIGH();

OLED_SPI_WriteCmd(0xAE); // Display Off (0x00)
OLED_SPI_WriteCmd(0xD5);
OLED_SPI_WriteCmd(0x80); // Set Clock as 100 Frames/Sec
OLED_SPI_WriteCmd(0xA8);
OLED_SPI_WriteCmd(0x3F); // 1/64 Duty (0x0F~0x3F)
OLED_SPI_WriteCmd(0xD3);
OLED_SPI_WriteCmd(0x00); // Shift Mapping RAM Counter (0x00~0x3F)
OLED_SPI_WriteCmd(0x40 | 0x00); // Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_SPI_WriteCmd(0x8D);
OLED_SPI_WriteCmd(0x10 | 0x04); // Enable Embedded DC/DC Converter (0x00/0x04)
OLED_SPI_WriteCmd(0x20);
OLED_SPI_WriteCmd(0x02); // Set Page Addressing Mode (0x00/0x01/0x02)
OLED_SPI_WriteCmd(0xA0 | 0x01); // Set SEG/Column Mapping
OLED_SPI_WriteCmd(0xC0); // Set COM/x Scan Direction
OLED_SPI_WriteCmd(0xDA);
OLED_SPI_WriteCmd(0x02 | 0x10); // Set Sequential Configuration (0x00/0x10)
OLED_SPI_WriteCmd(0x81);
OLED_SPI_WriteCmd(0xCF); // Set SEG Output Current
OLED_SPI_WriteCmd(0xD9);
OLED_SPI_WriteCmd(0xF1); // Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_SPI_WriteCmd(0xDB);
OLED_SPI_WriteCmd(0x40); // Set VCOM Deselect Level
OLED_SPI_WriteCmd(0xA4 | 0x00); // Disable Entire Display On (0x00/0x01)
OLED_SPI_WriteCmd(0xA6 | 0x00); // Disable Inverse Display On (0x00/0x01)
OLED_SPI_WriteCmd(0xAE | 0x01); // Display On (0x01)

OLED_Clear(); // 清屏
}

初始化 OLED 只需调用:

1
OLED_SPI_Init();

2.2 唤醒和休眠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*************************************************************************
唤醒 OLED
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_ON (void)
{
OLED_SPI_WriteCmd(0X8D); // 设置电荷泵
OLED_SPI_WriteCmd(0X14); // 开启电荷泵
OLED_SPI_WriteCmd(0XAF); // OLED唤醒
}

/*************************************************************************
休眠 OLED
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_OFF (void)
{
OLED_SPI_WriteCmd(0X8D); // 设置电荷泵
OLED_SPI_WriteCmd(0X10); // 关闭电荷泵
OLED_SPI_WriteCmd(0XAE); // OLED休眠
}

2.3 与显示相关的函数

指定位置刷新显示的功能实现有待进一步研究。

注意:不要频繁调用清屏函数 OLED_Clear(),这会导致屏幕刷新过慢或出现重影现象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
/*************************************************************************
OLED 刷新显示
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_Refresh_Gram (void)
{
uint8_t i, j;

for(i = 0; i < 8; i++)
{
OLED_SPI_WriteCmd(0xB0 + i); // 设置页地址(0~7)
OLED_SPI_WriteCmd(0x00); // 设置显示位置—列低地址
OLED_SPI_WriteCmd(0x10); // 设置显示位置—列高地址

for(j = 0; j < 128; j++)
{
OLED_SPI_WriteData(OLED_GRAM[j][i]);
}
}

}

/*************************************************************************
OLED 清屏
--------------------------------------------------------------------------
无参数
*************************************************************************/
void OLED_Clear (void)
{
uint8_t i, j;

for(i = 0; i < 8; i++)
{
for(j = 0; j < 128; j++)
{
OLED_GRAM[j][i] = 0X00;
}
}

OLED_Refresh_Gram(); // 更新显示
}

/*************************************************************************
OLED 画点
--------------------------------------------------------------------------
x,y:坐标 mode:阳码/阴码填充
*************************************************************************/
static void OLED_DrawPoint (uint8_t x, uint8_t y, uint8_t mode)
{
uint8_t pos, bx;
uint8_t temp = 0;

if (x > 127|| y > 63) // 超出范围
{
return;
}

pos = 7 - y / 8;
bx = y % 8;
temp= 1 << (7 - bx);

if (mode == OLED_ANODE)
{
OLED_GRAM[x][pos] |= temp;
}
else
{
OLED_GRAM[x][pos] &= ~temp;
}
}

/*************************************************************************
OLED 方块填充
--------------------------------------------------------------------------
x1,y1:左上角坐标 x2,y2:右下角坐标 mode:阳码/阴码填充
*************************************************************************/
static void OLED_Fill (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t mode)
{
uint8_t x, y;

for (x = x1; x <= x2; x++)
{
for (y = y1; y <= y2; y++)
{
OLED_DrawPoint (x, y, mode);
}
}

OLED_Refresh_Gram(); // 更新显示
}

需要刷新屏幕时,调用:

1
OLED_Refresh_Gram ();

需要清屏时,调用:

1
OLED_Clear ();

2.4 显示 ASCII 字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*************************************************************************
OLED 打印一个字符
--------------------------------------------------------------------------
x,y:坐标 ch:字符 size:字符大小 mode:阳码/阴码
*************************************************************************/
static void OLED_ShowChar (uint8_t x, uint8_t y, uint8_t ch, uint8_t size, uint8_t mode)
{
uint8_t temp;
uint8_t i, j;
uint8_t y0;
uint8_t csize;

y0 = y;
ch = ch - ' ';
csize = (size / 8 + ((size % 8) ? 1 : 0) ) * (size / 2); //得到字体一个字符对应点阵集所占的字节数

for(i = 0; i < csize; i++)
{
switch (size)
{
case OLED_FONT_SIZE_12:
temp = ascii_1206[ch][i];
break;
case OLED_FONT_SIZE_16:
temp = ascii_1608[ch][i];
break;
default:
return;
}

for(j = 0; j < 8; j++)
{
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; // 退出循环
}

}
}
}

/*************************************************************************
OLED 打印一个字符串
--------------------------------------------------------------------------
x,y:坐标 str:字符串 size:字符大小
*************************************************************************/
void OLED_ShowString (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size)
{
while( (*str <= '~') && (*str >= ' ') ) //判断是不是非法字符!
{
if ( x > (128 - (size / 2)) )
{
x = 0;
y += size;
}

if ( y > (64 - size) )
{
x = 0;
y = 0;
OLED_Clear();
}

OLED_ShowChar (x, y, *str, size, OLED_ANODE);

x += size / 2;
str++;
}
}

使用示例:

1
OLED_ShowString (0, 0, "Welcome To", OLED_FONT_SIZE_16);

2.5 显示中文字符串

注意:传入的参数必须是一个数组的地址,而不是一个中文字符串。这个数组必须存储中文的点阵数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*************************************************************************
OLED 打印一个中文字
--------------------------------------------------------------------------
x,y:坐标 *str:中文数组首地址 size:字符大小 mode:阳码/阴码
*************************************************************************/
static void OLED_ShowChar_CH (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t mode)
{
uint8_t temp;
uint8_t i, j;
uint8_t y0;
uint8_t csize;

y0 = y;
csize = (size / 8 + ((size % 8) ? 1 : 0) ) * (size / 2); //得到字体一个字符对应点阵集所占的字节数

for(i = 0; i < csize; i++)
{
temp = *(str + i);

for(j = 0; j < 8; j++)
{
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; // 退出循环
}

}
}
}

/*************************************************************************
OLED 打印一行中文字
--------------------------------------------------------------------------
x,y:坐标 *str:中文数组首地址 size:字符大小 num:多少字 mode:阳码/阴码
*************************************************************************/
void OLED_ShowChinese (uint8_t x, uint8_t y, const uint8_t *str, uint8_t size, uint8_t num)
{
uint16_t i;

for (i = 0; i < num * 2; i++)
{
if ( x > (128 - (size / 2)) )
{
x = 0;
y += size;
}

if ( y > (64 - size) )
{
x = 0;
y = 0;
OLED_Clear();
}

OLED_ShowChar_CH (x, y, str, size, OLED_ANODE);

x += size / 2;
str += size;
}
}

使用示例:

1
OLED_ShowChinese (20, 20, &chinese1_1616[0][0], OLED_FONT_SIZE_16, 4);

2.6 显示图片

注意:传入的参数必须是一个数组的地址。这个数组必须存储 BMP 图片的点阵数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/*************************************************************************
OLED 打印 BMP 图片
--------------------------------------------------------------------------
x,y:左上角坐标 *bmp:BMP数组首地址 width,height:图片尺寸大小
*************************************************************************/
void OLED_ShowPic (uint8_t x, uint8_t y, const uint8_t *pic, uint8_t width, uint8_t height, uint8_t mode)
{
uint16_t i, j, size;
uint8_t y0;
uint8_t temp;

if ((x + width > 128) || (y + height > 64))
return;

size = (uint16_t)( height / 8 + ((height % 8)? 1 : 0) ) * width;
y0 = y;

for (i = 0; i < size; i++)
{
temp = *(pic + i);

for (j = 0; j < 8; j++)
{
if (temp & 0x80)
{
OLED_DrawPoint (x, y, mode);
}
else
{
OLED_DrawPoint (x, y, !mode);
}

temp <<= 1;
y++;

if (y - y0 == height)
{
y = y0;
x++;
break;
}

}
}
}

使用示例:

1
OLED_ShowPic (0, 0, &bmp1[0][0], 114, 64, OLED_CATHODE);

2.7 垂直及水平滚动

注意:

  • 这些函数需要在OLED_Refresh_Gram()后调用,且不能放在 while 循环体内。
  • 由于硬件设计原因,OLED 不能直接做到完全垂直滚动,只能做到垂直+水平滚动的效果。完全垂直滚动的实现有待本人进一步研究。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*************************************************************************
OLED 垂直+水平滚动显示
--------------------------------------------------------------------------
start_page,end_page:起始/终止页地址 frame:滚动步长时间间隔,帧为单位
scroll_offset:垂直滚动偏移(0-63) dir:滚动方向
--------------------------------------------------------------------------
注意:该函数需要在 OLED_Refresh_Gram 后调用
*************************************************************************/
void OLED_VerHorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t scroll_offset, uint8_t dir)
{
OLED_SPI_WriteCmd (0x2E); //关闭滚动
OLED_SPI_WriteCmd (0x29 + dir); //水平垂直和水平滚动左右 29/2a
OLED_SPI_WriteCmd (0x00); //虚拟字节
OLED_SPI_WriteCmd (start_page); //起始页
OLED_SPI_WriteCmd (frame); //滚动时间间隔
OLED_SPI_WriteCmd (end_page); //终止页
OLED_SPI_WriteCmd (scroll_offset); //垂直滚动偏移量
OLED_SPI_WriteCmd (0x2F);
}

/*************************************************************************
OLED 水平滚动显示
--------------------------------------------------------------------------
start_page,end_page:起始/终止页地址 frame:滚动步长时间间隔,帧为单位
dir:滚动方向
--------------------------------------------------------------------------
注意:该函数需要在 OLED_Refresh_Gram 后调用
*************************************************************************/
void OLED_HorScroll (enum page_num start_page, enum page_num end_page, enum roll_frame frame, uint8_t dir)
{
OLED_SPI_WriteCmd (0x2E); //关闭滚动
OLED_SPI_WriteCmd (0x26 + dir); //水平向左或者右滚动 26/27
OLED_SPI_WriteCmd (0x00); //虚拟字节
OLED_SPI_WriteCmd (start_page); //起始页
OLED_SPI_WriteCmd (frame); //滚动时间间隔
OLED_SPI_WriteCmd (end_page); //终止页
OLED_SPI_WriteCmd (0x00); //虚拟字节(必须加上)
OLED_SPI_WriteCmd (0xFF); //虚拟字节(必须加上)
OLED_SPI_WriteCmd (0x2F); //开启滚动
}

使用示例(要放在 while 外面):

1
2
3
4
// 实现图片的垂直+水平滚动
OLED_ShowPic (0, 0, &bmp1[0][0], 114, 64, OLED_CATHODE);
OLED_Refresh_Gram ();
OLED_VerHorScroll (PAGE2, PAGE7, FRAME7, 0, OLED_SCROLL_LEFT);

3 字模和图片的相关文件

3.1 oled_font.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef __OLED_FONT_H
#define __OLED_FONT_H

#include "stm8s.h"

extern const uint8_t ascii_1206[][12];
extern const uint8_t ascii_1608[][16];

extern const uint8_t chinese1_1616[][16];
extern const uint8_t chinese2_1616[][16];

extern const uint8_t bmp1[][16];
extern const uint8_t bmp2[][16];
extern const uint8_t bmp3[][16];

#endif /* __OLED_FONT_H */

3.2 oled_font.c

存储 ASCII 字符,仅展示一部分代码(12x6 的 ASCII 字符):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "oled_font.h"

/*********点阵格式:阴码 取模方式:逐列式 取模走向:顺向(高位在前)*********/

const uint8_t ascii_1206[95][12]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0x00,0x3F,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",1*/
{0x00,0x00,0x30,0x00,0x40,0x00,0x30,0x00,0x40,0x00,0x00,0x00},/*""",2*/
{0x09,0x00,0x0B,0xC0,0x3D,0x00,0x0B,0xC0,0x3D,0x00,0x09,0x00},/*"#",3*/
{0x18,0xC0,0x24,0x40,0x7F,0xE0,0x22,0x40,0x31,0x80,0x00,0x00},/*"$",4*/
{0x18,0x00,0x24,0xC0,0x1B,0x00,0x0D,0x80,0x32,0x40,0x01,0x80},/*"%",5*/
{0x03,0x80,0x1C,0x40,0x27,0x40,0x1C,0x80,0x07,0x40,0x00,0x40},/*"&",6*/
{0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x20,0x40,0x40,0x20},/*"(",8*/
{0x00,0x00,0x40,0x20,0x20,0x40,0x1F,0x80,0x00,0x00,0x00,0x00},/*")",9*/
{0x09,0x00,0x06,0x00,0x1F,0x80,0x06,0x00,0x09,0x00,0x00,0x00},/*"*",10*/
{0x04,0x00,0x04,0x00,0x3F,0x80,0x04,0x00,0x04,0x00,0x00,0x00},/*"+",11*/
{0x00,0x10,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x00,0x00},/*"-",13*/
{0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x20,0x01,0xC0,0x06,0x00,0x38,0x00,0x40,0x00,0x00,0x00},/*"/",15*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"0",16*/
{0x00,0x00,0x10,0x40,0x3F,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"1",17*/
{0x18,0xC0,0x21,0x40,0x22,0x40,0x24,0x40,0x18,0x40,0x00,0x00},/*"2",18*/
{0x10,0x80,0x20,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"3",19*/
{0x02,0x00,0x0D,0x00,0x11,0x00,0x3F,0xC0,0x01,0x40,0x00,0x00},/*"4",20*/
{0x3C,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x23,0x80,0x00,0x00},/*"5",21*/
{0x1F,0x80,0x24,0x40,0x24,0x40,0x34,0x40,0x03,0x80,0x00,0x00},/*"6",22*/
{0x30,0x00,0x20,0x00,0x27,0xC0,0x38,0x00,0x20,0x00,0x00,0x00},/*"7",23*/
{0x1B,0x80,0x24,0x40,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"8",24*/
{0x1C,0x00,0x22,0xC0,0x22,0x40,0x22,0x40,0x1F,0x80,0x00,0x00},/*"9",25*/
{0x00,0x00,0x00,0x00,0x08,0x40,0x00,0x00,0x00,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x04,0x00,0x0A,0x00,0x11,0x00,0x20,0x80,0x40,0x40},/*"<",28*/
{0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x00,0x00},/*"=",29*/
{0x00,0x00,0x40,0x40,0x20,0x80,0x11,0x00,0x0A,0x00,0x04,0x00},/*">",30*/
{0x18,0x00,0x20,0x00,0x23,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"?",31*/
{0x1F,0x80,0x20,0x40,0x27,0x40,0x29,0x40,0x1F,0x40,0x00,0x00},/*"@",32*/
{0x00,0x40,0x07,0xC0,0x39,0x00,0x0F,0x00,0x01,0xC0,0x00,0x40},/*"A",33*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x40,0x1B,0x80,0x00,0x00},/*"B",34*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x30,0x80,0x00,0x00},/*"C",35*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"D",36*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x40,0x30,0xC0,0x00,0x00},/*"E",37*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x2E,0x00,0x30,0x00,0x00,0x00},/*"F",38*/
{0x0F,0x00,0x10,0x80,0x20,0x40,0x22,0x40,0x33,0x80,0x02,0x00},/*"G",39*/
{0x20,0x40,0x3F,0xC0,0x04,0x00,0x04,0x00,0x3F,0xC0,0x20,0x40},/*"H",40*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x20,0x40,0x20,0x40,0x00,0x00},/*"I",41*/
{0x00,0x60,0x20,0x20,0x20,0x20,0x3F,0xC0,0x20,0x00,0x20,0x00},/*"J",42*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x0B,0x00,0x30,0xC0,0x20,0x40},/*"K",43*/
{0x20,0x40,0x3F,0xC0,0x20,0x40,0x00,0x40,0x00,0x40,0x00,0xC0},/*"L",44*/
{0x3F,0xC0,0x3C,0x00,0x03,0xC0,0x3C,0x00,0x3F,0xC0,0x00,0x00},/*"M",45*/
{0x20,0x40,0x3F,0xC0,0x0C,0x40,0x23,0x00,0x3F,0xC0,0x20,0x00},/*"N",46*/
{0x1F,0x80,0x20,0x40,0x20,0x40,0x20,0x40,0x1F,0x80,0x00,0x00},/*"O",47*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x24,0x00,0x18,0x00,0x00,0x00},/*"P",48*/
{0x1F,0x80,0x21,0x40,0x21,0x40,0x20,0xE0,0x1F,0xA0,0x00,0x00},/*"Q",49*/
{0x20,0x40,0x3F,0xC0,0x24,0x40,0x26,0x00,0x19,0xC0,0x00,0x40},/*"R",50*/
{0x18,0xC0,0x24,0x40,0x24,0x40,0x22,0x40,0x31,0x80,0x00,0x00},/*"S",51*/
{0x30,0x00,0x20,0x40,0x3F,0xC0,0x20,0x40,0x30,0x00,0x00,0x00},/*"T",52*/
{0x20,0x00,0x3F,0x80,0x00,0x40,0x00,0x40,0x3F,0x80,0x20,0x00},/*"U",53*/
{0x20,0x00,0x3E,0x00,0x01,0xC0,0x07,0x00,0x38,0x00,0x20,0x00},/*"V",54*/
{0x38,0x00,0x07,0xC0,0x3C,0x00,0x07,0xC0,0x38,0x00,0x00,0x00},/*"W",55*/
{0x20,0x40,0x39,0xC0,0x06,0x00,0x39,0xC0,0x20,0x40,0x00,0x00},/*"X",56*/
{0x20,0x00,0x38,0x40,0x07,0xC0,0x38,0x40,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x30,0x40,0x21,0xC0,0x26,0x40,0x38,0x40,0x20,0xC0,0x00,0x00},/*"Z",58*/
{0x00,0x00,0x00,0x00,0x7F,0xE0,0x40,0x20,0x40,0x20,0x00,0x00},/*"[",59*/
{0x00,0x00,0x70,0x00,0x0C,0x00,0x03,0x80,0x00,0x40,0x00,0x00},/*"\",60*/
{0x00,0x00,0x40,0x20,0x40,0x20,0x7F,0xE0,0x00,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x20,0x00,0x40,0x00,0x20,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10},/*"_",63*/
{0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x02,0x80,0x05,0x40,0x05,0x40,0x03,0xC0,0x00,0x40},/*"a",65*/
{0x20,0x00,0x3F,0xC0,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"b",66*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x06,0x40,0x00,0x00},/*"c",67*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x24,0x40,0x3F,0xC0,0x00,0x40},/*"d",68*/
{0x00,0x00,0x03,0x80,0x05,0x40,0x05,0x40,0x03,0x40,0x00,0x00},/*"e",69*/
{0x00,0x00,0x04,0x40,0x1F,0xC0,0x24,0x40,0x24,0x40,0x20,0x00},/*"f",70*/
{0x00,0x00,0x02,0xE0,0x05,0x50,0x05,0x50,0x06,0x50,0x04,0x20},/*"g",71*/
{0x20,0x40,0x3F,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"h",72*/
{0x00,0x00,0x04,0x40,0x27,0xC0,0x00,0x40,0x00,0x00,0x00,0x00},/*"i",73*/
{0x00,0x10,0x00,0x10,0x04,0x10,0x27,0xE0,0x00,0x00,0x00,0x00},/*"j",74*/
{0x20,0x40,0x3F,0xC0,0x01,0x40,0x07,0x00,0x04,0xC0,0x04,0x40},/*"k",75*/
{0x20,0x40,0x20,0x40,0x3F,0xC0,0x00,0x40,0x00,0x40,0x00,0x00},/*"l",76*/
{0x07,0xC0,0x04,0x00,0x07,0xC0,0x04,0x00,0x03,0xC0,0x00,0x00},/*"m",77*/
{0x04,0x40,0x07,0xC0,0x04,0x40,0x04,0x00,0x03,0xC0,0x00,0x40},/*"n",78*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x40,0x03,0x80,0x00,0x00},/*"o",79*/
{0x04,0x10,0x07,0xF0,0x04,0x50,0x04,0x40,0x03,0x80,0x00,0x00},/*"p",80*/
{0x00,0x00,0x03,0x80,0x04,0x40,0x04,0x50,0x07,0xF0,0x00,0x10},/*"q",81*/
{0x04,0x40,0x07,0xC0,0x02,0x40,0x04,0x00,0x04,0x00,0x00,0x00},/*"r",82*/
{0x00,0x00,0x06,0x40,0x05,0x40,0x05,0x40,0x04,0xC0,0x00,0x00},/*"s",83*/
{0x00,0x00,0x04,0x00,0x1F,0x80,0x04,0x40,0x00,0x40,0x00,0x00},/*"t",84*/
{0x04,0x00,0x07,0x80,0x00,0x40,0x04,0x40,0x07,0xC0,0x00,0x40},/*"u",85*/
{0x04,0x00,0x07,0x00,0x04,0xC0,0x01,0x80,0x06,0x00,0x04,0x00},/*"v",86*/
{0x06,0x00,0x01,0xC0,0x07,0x00,0x01,0xC0,0x06,0x00,0x00,0x00},/*"w",87*/
{0x04,0x40,0x06,0xC0,0x01,0x00,0x06,0xC0,0x04,0x40,0x00,0x00},/*"x",88*/
{0x04,0x10,0x07,0x10,0x04,0xE0,0x01,0x80,0x06,0x00,0x04,0x00},/*"y",89*/
{0x00,0x00,0x04,0x40,0x05,0xC0,0x06,0x40,0x04,0x40,0x00,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x7B,0xE0,0x40,0x20,0x00,0x00},/*"{",91*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00},/*"|",92*/
{0x00,0x00,0x40,0x20,0x7B,0xE0,0x04,0x00,0x00,0x00,0x00,0x00},/*"}",93*/
{0x40,0x00,0x80,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x40,0x00},/*"~",94*/
};

3.3 oled_font_ch.c

存储中文字符,仅展示 12x12 的中文字符“当前温度 ”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "oled_font.h"

/*********点阵格式:阴码 取模方式:逐列式 取模走向:顺向(高位在前)*********/

// chinese1 = "当前温度"
const uint8_t chinese1_1616[4*2][16] = {
{0x00,0x00,0x02,0x02,0x42,0x22,0x22,0x22,0x1A,0x22,0x02,0x22,0x02,0x22,0xFE,0x22},
{0x02,0x22,0x02,0x22,0x0A,0x22,0x12,0x22,0x63,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"当",0*/

{0x10,0x00,0x10,0x00,0x17,0xFF,0x94,0x90,0x74,0x92,0x14,0x91,0x17,0xFE,0x10,0x00},
{0x10,0x00,0x13,0xF0,0x30,0x02,0xD0,0x01,0x17,0xFE,0x10,0x00,0x10,0x00,0x00,0x00},/*"前",1*/

{0x08,0x20,0x06,0x20,0x40,0x7E,0x31,0x80,0x00,0x02,0x00,0x7E,0x7F,0x42,0x49,0x42},
{0x49,0x7E,0x49,0x42,0x49,0x7E,0x49,0x42,0x7F,0x42,0x00,0x7E,0x00,0x02,0x00,0x00},/*"温",2*/

{0x00,0x02,0x00,0x0C,0x3F,0xF1,0x24,0x01,0x24,0x21,0x24,0x32,0x3F,0xAA,0xA4,0xA4},
{0x64,0xA4,0x24,0xA4,0x3F,0xAA,0x24,0x32,0x24,0x01,0x24,0x01,0x20,0x01,0x00,0x00},/*"度",3*/
};

3.4 oled_bmp.c

该文件用于存储图片数据。需要在软件 image2LCD 中将图片转换为 bmp 格式,再用软件 PCtoLCD2002 将其转换为字模数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "oled_font.h"

// 64x64
const uint8_t bmp2[][16] = {
{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,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x00,0x00,0x30,0x40,0x00,0x00,0x00,0x00,0x00},
{0x00,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0x00},
{0x07,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x00,0x00,0x07,0xC0,0x00,0x00,0x00},
{0x1E,0x00,0x00,0x07,0x90,0x00,0x00,0x00,0x3E,0x00,0x00,0x07,0xF4,0x00,0x00,0x00},
{0x7E,0x00,0x00,0x07,0x98,0x00,0x00,0x00,0x7E,0x00,0x00,0x07,0xE4,0x00,0x00,0x03},
{0xFE,0x00,0x00,0x07,0xFC,0x00,0x00,0x0F,0xFE,0x00,0x00,0x07,0x7E,0x00,0x00,0x1F},
{0xFE,0x00,0x00,0x0F,0x8B,0x00,0x00,0x3F,0xFE,0x00,0x00,0x03,0x02,0x80,0x07,0xFF},
{0xFE,0x00,0x00,0x1C,0x11,0x00,0x1F,0xFF,0xFE,0x00,0x00,0x30,0x00,0x20,0x3F,0xFF},
{0xFE,0x00,0x00,0x04,0x00,0x40,0x7F,0xFF,0xFE,0x00,0x00,0x10,0x00,0x00,0x7F,0xFF},
{0xFE,0x00,0x00,0xC0,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x01,0xE0,0x00,0x00,0xFF,0xFF},
{0xFF,0x00,0x03,0x80,0x00,0x00,0xC7,0xFF,0xFF,0x00,0x06,0x80,0x00,0x00,0x00,0x3F},
{0xFF,0xC0,0x07,0xF0,0x00,0x00,0x80,0x3F,0xFF,0xF0,0x0D,0xF0,0x00,0x00,0x00,0x1F},
{0xFF,0xFC,0x1F,0xE0,0x00,0x01,0x00,0x1F,0xFF,0xFF,0xC1,0xC8,0x01,0x00,0x00,0x3F},
{0xFF,0xFF,0xFF,0x80,0x02,0x00,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x0C,0xE4,0x00,0x3F},
{0xFF,0xFF,0xFB,0xFC,0x71,0x88,0x00,0x7F,0xFF,0xFF,0xE0,0x7F,0x83,0x00,0x00,0xFF},
{0xFF,0xFF,0xF0,0xFE,0x04,0x00,0x00,0xFF,0xFF,0xFF,0xFB,0x80,0x00,0x00,0x01,0xFF},
{0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x03,0x8F},
{0xFF,0xFF,0xFC,0x08,0x00,0x00,0x07,0x87,0x7F,0xFE,0xFC,0x03,0xA0,0x00,0x1F,0x8F},
{0x1F,0xFE,0xFE,0x0C,0x40,0x00,0x5F,0xDF,0x0F,0xFF,0xFF,0xF8,0x40,0x00,0x7F,0xFF},
{0x1F,0xFC,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0x1F,0x3E,0xFF,0x40,0x00,0x01,0xFF,0xFF},
{0x1F,0x82,0x63,0x00,0x00,0x03,0xFF,0xFF,0x0F,0x80,0x00,0x00,0x00,0x03,0xFF,0xFF},
{0x03,0x80,0x00,0x00,0x00,0x07,0xFF,0xFF,0x03,0xC0,0x00,0x00,0x00,0x0F,0xFF,0xFF},
{0x01,0xE0,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x01,0xB0,0x00,0x00,0x00,0x1F,0xFF,0xFF},
{0x01,0x8C,0x00,0x00,0x00,0x0F,0xFF,0xFF,0x01,0x80,0x00,0x00,0x00,0x0F,0xFF,0xFF},
{0x00,0x80,0x00,0x00,0x00,0x07,0xFF,0xFC,0x01,0xC0,0x00,0x00,0x00,0x07,0xFF,0xF8},
{0x00,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x58,0x00,0x00,0x00,0x01,0xCF,0xF0},
{0x00,0x20,0x00,0x00,0x00,0x00,0xF7,0xE0,0x00,0x00,0x80,0x00,0x00,0x00,0x3F,0xF0},
{0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF},
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"E:\STM8_Project\555.bmp",0*/
};
---EOF---