基于STM32的温湿度传感器(DHT11)-OLED屏显示-超详细

一、前期准备

(一)软件环境准备

编译工具为Keil5,对应芯片为:STM32F103C8T6

(二)硬件准备

  1. STM32模块

  1. OLED显示屏

  1. 温湿度传感器(DHT11)

  1. ST-Link V2(USB口)仿真器

  1. 适量杜邦线

大约11根母对母杜邦线


二、接线图表

STM32 ST-Link OLED屏 DHT11
3V3 3.3V
SWO SWDIO
SWCLK SWCLK
GND GND
PB9 SDA
PB8 SCL
3.3 VCC
G GND
3.3 +
PB11 out
G -

三、温湿度传感器(DHT11)驱动

(一)原理

​ DHT11工作原理是基于内部的湿度传感器和温度传感器,通过检测这两个传感器的信号变化,将湿度和温度转换为数字信号输出。它采用简单的串行通信协议(后面补充)与外部设备通信,发送包含温湿度数据的数据帧,用户则获取数据帧进行相关的处理使用。

经典应用电路图如图1所示

图1

​ DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:

​ 一次完整的数据传输为40bit,高位先出。

​ 数据格式:

​ 8bit湿度整数数据+8bit湿度小数数据

​ +8bi温度整数数据+8bit温度小数数据

​ +8bit校验和数据传送正确时校验和

​ 数据等于“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。

通讯过程如图2所示

图2

​ 总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。

图3

​ 总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据,每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。格式见下面图示。如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。

数字0信号表示方法如图4所示

图4

数字1信号表示方法.如图5所示

图5

补充内容:

串行通信协议是一种在数据传输中将信息逐位发送的通信方式。对于DHT11传感器而言,它使用的是一种简单的串行通信协议,通常是通过单个数据线与外部设备进行通信。具体来说,DHT11使用串行通信协议与外部设备通信的过程包括以下几个步骤:
启动信号: 外部设备发送一个启动信号给DHT11传感器,以指示开始通信的准备阶段。
数据传输: DHT11传感器根据约定的协议,将温湿度数据以串行的形式发送给外部设备。这些数据以特定的格式组织,例如先发送湿度值,然后发送温度值,或者相反。
校验: 在数据传输完成后,外部设备可能会对接收到的数据进行校验,以确保数据的完整性和准确性。通常使用校验和或循环冗余校验(CRC)等技术来实现校验。
应答: 在数据传输完成后,DHT11可能会发送一个应答信号给外部设备,以表示数据传输的成功或失败状态。

(二)代码解析

1. void DHT_Init_InPut(void)函数

函数介绍:

这个函数用于将连接到DHT11传感器的GPIO引脚配置为浮空输入模式。
使用了STM32的GPIO初始化结构体(GPIO_InitStructure)来配置GPIO的模式、引脚、速度等参数。

代码:

1
2
3
4
5
6
7
8
9
10
void DHT_Init_InPut(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

2. void DHT_Init_OutPut(void)函数

函数介绍:

这个函数将连接到DHT11传感器的GPIO引脚配置为推挽输出模式。
同样使用了GPIO初始化结构体进行配置。

代码:

1
2
3
4
5
6
7
8
9
10
void DHT_Init_OutPut(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

3. void DHT_Start(void)函数

函数介绍:

这个函数用于启动与DHT11传感器的通信。
首先调用了DHT_Init_OutPut()将引脚配置为输出模式,然后拉低总线一段时间(19ms),再拉高总线(20us),最后将引脚配置为输入模式。

代码:

1
2
3
4
5
6
7
8
9
void DHT_Start(void)
{
DHT_Init_OutPut();
GPIO_ResetBits(GPIOB, GPIO_Pin_11); // 拉低总线
Delay_us(19000);
GPIO_SetBits(GPIOB, GPIO_Pin_11); // 拉高总线
Delay_us(20);
DHT_Init_InPut();
}

4. uint16_t DHT_Scan(void)函数

函数介绍:

这个函数用于读取连接到DHT11传感器的GPIO引脚的当前状态,即读取传感器的响应状态。

代码:

1
2
3
4
uint16_t DHT_Scan(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); // 返回读取数据
}

5. uint16_t DHT_ReadBit(void)函数

函数介绍:

这个函数用于从DHT11传感器读取单个位。
它会等待传感器将数据线拉高,然后延时一段时间后再读取数据线的状态,以确定位值。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint16_t DHT_ReadBit(void)
{
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == RESET);
Delay_us(40);
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET)
{
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET);
return 1;
}
else
{
return 0;
}
}

6. uint16_t DHT_ReadByte(void)函数

函数介绍:

这个函数用于从DHT11传感器读取一个字节(8位)的数据。
它通过调用DHT_ReadBit()函数8次,将每一位数据组装成一个完整的字节。

代码:

1
2
3
4
5
6
7
8
9
10
uint16_t DHT_ReadByte(void)
{
uint16_t i, data = 0;
for(i = 0; i < 8; i++)
{
data <<= 1; // 向左进一位
data |= DHT_ReadBit();
}
return data;
}

7. uint16_t DHT_ReadData(uint8_t buffer[5])函数

函数介绍:

这个函数用于从DHT11传感器读取5个字节的数据,并进行校验。
它首先调用DHT_Start()启动通信,然后读取传感器发送的数据,并对数据进行校验,确保数据的准确性。

代码:

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
uint16_t DHT_ReadData(uint8_t buffer[5])
{
uint16_t i =0;

DHT_Start();
if(DHT_Scan() == RESET)
{
while(DHT_Scan() == RESET);
while(DHT_Scan() == SET);
for(i = 0; i < 5; i++)
{
buffer[i] = DHT_ReadByte();
}
// DHT11输出的40位数据
while(DHT_Scan() == RESET);
DHT_Init_OutPut();
GPIO_SetBits(GPIOB, GPIO_Pin_11);

uint8_t check = buffer[0] + buffer[1] + buffer[2] + buffer[3];
if(check != buffer[4])
{
return 1; // 数据出错
}
}
return 0;
}

四、OLED显示屏驱动(主要函数、I2C协议)

1. OLED_ShowChar函数

函数介绍:

功能:在指定的行和列位置显示一个字符。
参数:

​ Line:行位置,范围为1到4。
​ Column:列位置,范围为1到16。
​ Char:要显示的字符,范围为ASCII可见字符。
这个函数首先根据行和列位置设置光标的位置,然后根据字符的ASCII码在字库中查找对应的字形数据,并将上半部分和下半部分的数据分别写入OLED屏幕的两个页面,以完成字符的显示。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}

2. OLED_ShowString函数

函数介绍:

功能:在指定的行和列位置显示一个字符串。
参数:

​ Line:起始行位置,范围为1到4。
​ Column:起始列位置,范围为1到16。
​ String:要显示的字符串,范围为ASCII可见字符。

这个函数通过循环调用OLED_ShowChar()函数,逐个显示字符串中的字符。

代码:

1
2
3
4
5
6
7
8
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}

3. OLED_Pow函数

函数介绍:

功能:计算X的Y次方。
返回值:返回值等于X的Y次方。

这个函数实现了简单的幂函数计算,用于数字显示的处理。

代码:

1
2
3
4
5
6
7
8
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}

4. OLED_ShowNum函数

函数介绍:

功能:在指定的行和列位置显示一个十进制的正整数。
参数:

​ Line:起始行位置,范围为1到4。
​ Column:起始列位置,范围为1到16。
​ Number:要显示的数字,范围为0到4294967295。
​ Length:要显示数字的长度,范围为1到10。

这个函数将数字按位数拆分,并逐个调用OLED_ShowChar()函数来显示每一位数字。

代码:

1
2
3
4
5
6
7
8
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}

5. OLED_ShowFNum函数

函数介绍:

功能:在指定的行和列位置显示一个带小数点的十进制数。
参数:

​ Line:起始行位置,范围为1到4。
​ Column:起始列位置,范围为1到16。
​ Number:要显示的数字。
​ Length:要显示数字的长度,范围为1到10。
​ FLength:要显示的小数点后几位。
这个函数首先判断数字的正负,然后将数字分为整数部分和小数部分,并调用OLED_ShowChar()函数逐个显示每一位数字。

代码:

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
void OLED_ShowFNum(uint8_t Line, uint8_t Column, float Number, uint8_t Length, uint8_t FLength)
{
uint8_t i;
uint8_t flag = 1; // 标志是否为小数部分
float Number1;
uint32_t Number2;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
Number2 = (int)(Number1*OLED_Pow(10, FLength)); // 小数转换成整数
for(i = Length; i > 0; i--)
{
if(i == Length - FLength)
{
OLED_ShowChar(Line, Column + i + flag, '.');
flag = 0;
}
OLED_ShowChar(Line, Column + i + flag, Number2/OLED_Pow(10, Length-i)%10+'0');
}
}

6. OLED_ShowCC_F16x16函数

函数介绍:

功能:在指定的行和列位置显示一个汉字(16x16像素)。
参数:

​ Line:行位置,范围为1到4。
​ Column:列位置,范围为1到16。
​ num:要显示的汉字在字库中的索引。
这个函数类似于OLED_ShowChar(),但是专门用于显示汉字,字库中每个汉字占16个字节,前8个字节表示汉字的上半部分,后8个字节表示下半部分。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void OLED_ShowCC_F16x16(uint8_t Line, uint8_t Column, uint8_t num)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 16; i++)
{
OLED_WriteData(CC_F16x16[num*2][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 16; i++)
{
OLED_WriteData(CC_F16x16[num*2][i + 16]); //显示下半部分内容
}
}

五、效果展示

基于STM32的温湿度传感器+OLED屏显示的测试视频(有杂音,耳机党请注意)


六、总结

本文章主要讲的是通过使用STM32实现了对DHT11温湿度传感器的数据采集和显示。通过对GPIO的配置和延时函数的使用,我们成功地与DHT11传感器进行了通信,并读取了温度和湿度数据。在软件开发方面,我们编写了针对DHT11传感器的初始化、数据读取和校验的函数,并成功地将获取到的数据显示在OLED屏幕上,使用户能够直观地了解当前环境的温度和湿度情况。


七、完整代码

压缩包连接:https://download.csdn.net/download/D102428/89078308

main.c

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
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "DHT11.h"

int main()
{
OLED_Init();

uint8_t buffer[5];
float h, t;

OLED_ShowCC_F16x16(2, 1, 2); // 温
OLED_ShowCC_F16x16(2, 3, 4); // 度
OLED_ShowChar(2, 5, ':');

OLED_ShowCC_F16x16(3, 1, 3); // 湿
OLED_ShowCC_F16x16(3, 3, 4); // 度
OLED_ShowChar(3, 5, ':');

while(1)
{
if(DHT_ReadData(buffer) == 0)
{
h = buffer[0] + buffer[1] / 10.0;
t = buffer[2] + buffer[3] / 10.0;

OLED_ShowFNum(2, 6, t, 3, 1);
OLED_ShowCC_F16x16(2, 11, 0); // ℃

OLED_ShowFNum(3, 6, h, 3, 1);
OLED_ShowCC_F16x16(3, 11, 1); // %
}
else
{
OLED_Clear();
OLED_ShowString(2, 6, "ERROR");
}
}
}

DHT11.h

1
2
3
4
5
6
7
8
9
10
11
12
#ifndef _DHT11_H
#define _DHT11_H

void DHT_Init_InPut(void);
void DHT_Init_OutPut(void);
void DHT_Start(void);
uint16_t DHT_Scan(void);
uint16_t DHT_ReadBit(void);
uint16_t DHT_ReadByte(void);
uint16_t DHT_ReadData(uint8_t buffer[5]);

#endif

DHT11.c

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
#include "stm32f10x.h"                  // Device header
#include "Delay.h"


void DHT_Init_InPut(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void DHT_Init_OutPut(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void DHT_Start(void)
{
DHT_Init_OutPut();
GPIO_ResetBits(GPIOB, GPIO_Pin_11); // 拉低总线
Delay_us(19000);
GPIO_SetBits(GPIOB, GPIO_Pin_11); // 拉高总线
Delay_us(20);
DHT_Init_InPut();
}

uint16_t DHT_Scan(void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11); // 返回读取数据
}

uint16_t DHT_ReadBit(void)
{
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == RESET);
Delay_us(40);
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET)
{
while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == SET);
return 1;
}
else
{
return 0;
}
}

uint16_t DHT_ReadByte(void)
{
uint16_t i, data = 0;
for(i = 0; i < 8; i++)
{
data <<= 1; // 向左进一位
data |= DHT_ReadBit();
}
return data;
}

uint16_t DHT_ReadData(uint8_t buffer[5])
{
uint16_t i =0;

DHT_Start();
if(DHT_Scan() == RESET)
{
while(DHT_Scan() == RESET);
while(DHT_Scan() == SET);
for(i = 0; i < 5; i++)
{
buffer[i] = DHT_ReadByte();
}
// DHT11输出的40位数据
while(DHT_Scan() == RESET);
DHT_Init_OutPut();
GPIO_SetBits(GPIOB, GPIO_Pin_11);

uint8_t check = buffer[0] + buffer[1] + buffer[2] + buffer[3];
if(check != buffer[4])
{
return 1; // 数据出错
}
}
return 0;
}

OLED_Font.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
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#ifndef __OLED_FONT_H
#define __OLED_FONT_H

/*OLED字模库,宽8像素,高16像素*/
const uint8_t OLED_F8x16[][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,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 uint8_t CC_F16x16[][16] = { // Custom Characters 自定义字符
0x06,0x09,0x09,0xE6,0xF8,0x0C,0x04,0x02,0x02,0x02,0x02,0x02,0x04,0x1E,0x00,0x00,
0x00,0x00,0x00,0x07,0x1F,0x30,0x20,0x40,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00,/* "℃",0 */

0x60,0xF0,0x08,0x08,0x08,0xF8,0xF0,0x00,0x80,0x40,0x30,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x21,0x11,0x0C,0x02,0x01,0x00,0x1E,0x21,0x21,0x21,0x33,0x1E,0x00,/* " %",1 */

0x10,0x60,0x02,0x8C,0x00,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x40,0x7E,0x42,0x42,0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,/* "温",2 */

0x10,0x60,0x02,0x8C,0x00,0xFE,0x92,0x92,0x92,0x92,0x92,0x92,0xFE,0x00,0x00,0x00,
0x04,0x04,0x7E,0x01,0x44,0x48,0x50,0x7F,0x40,0x40,0x7F,0x50,0x48,0x44,0x40,0x00,/* "湿",3 */

0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0x25,0x26,0x24,0xFC,0x24,0x24,0x24,0x04,0x00,
0x40,0x30,0x8F,0x80,0x84,0x4C,0x55,0x25,0x25,0x25,0x55,0x4C,0x80,0x80,0x80,0x00,/* "度",4 */

0x00,0x00,0x40,0x40,0x40,0x40,0x40,0xFF,0x40,0x40,0x40,0x40,0x40,0x00,0x00,0x00,
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,/* "土",5 */

0x10,0x10,0xFF,0x10,0x00,0x82,0xBA,0xEA,0xBA,0x83,0xBA,0xEA,0xBA,0x82,0x00,0x00,
0x08,0x18,0x0F,0x04,0x48,0x4A,0x2A,0xFF,0x8A,0x4A,0x1A,0x2F,0x5A,0x8A,0x88,0x00,/* "壤",6 */

};

#endif

OLED.h

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

void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowFNum(uint8_t Line, uint8_t Column, float Number, uint8_t Length, uint8_t FLength);
void OLED_ShowCC_F16x16(uint8_t Line, uint8_t Column, uint8_t num);

#endif

OLED.c

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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#include "stm32f10x.h"
#include "OLED_Font.h"

/*引脚配置*/
#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))
#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))

/*引脚初始化*/
void OLED_I2C_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOB, &GPIO_InitStructure);

OLED_W_SCL(1);
OLED_W_SDA(1);
}

/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void OLED_I2C_Start(void)
{
OLED_W_SDA(1);
OLED_W_SCL(1);
OLED_W_SDA(0);
OLED_W_SCL(0);
}

/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void OLED_I2C_Stop(void)
{
OLED_W_SDA(0);
OLED_W_SCL(1);
OLED_W_SDA(1);
}

/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_SDA(Byte & (0x80 >> i));
OLED_W_SCL(1);
OLED_W_SCL(0);
}
OLED_W_SCL(1); //额外的一个时钟,不处理应答信号
OLED_W_SCL(0);
}

/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCommand(uint8_t Command)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x00); //写命令
OLED_I2C_SendByte(Command);
OLED_I2C_Stop();
}

/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x40); //写数据
OLED_I2C_SendByte(Data);
OLED_I2C_Stop();
}

/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点,向下方向的坐标,范围:0~7
* @param X 以左上角为原点,向右方向的坐标,范围:0~127
* @retval 无
*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
OLED_WriteCommand(0xB0 | Y); //设置Y位置
OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}

/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
void OLED_Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}

/**
* @brief OLED显示一个字符
* @param Line 行位置,范围:1~4
* @param Column 列位置,范围:1~16
* @param Char 要显示的一个字符,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}

/**
* @brief OLED显示字符串
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}

/**
* @brief OLED次方函数
* @retval 返回值等于X的Y次方
*/
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}

/**
* @brief OLED显示数字(十进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~4294967295
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}

/**
* @brief OLED显示数字(十进制,带符号数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-2147483648~2147483647
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}

/**
* @brief OLED显示数字(十六进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFFFFFF
* @param Length 要显示数字的长度,范围:1~8
* @retval 无
*/
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i, SingleNumber;
for (i = 0; i < Length; i++)
{
SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
OLED_ShowChar(Line, Column + i, SingleNumber + '0');
}
else
{
OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
}
}
}

/**
* @brief OLED显示数字(二进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
}
}

/**
* @brief OLED显示小数(十进制,带符号数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字
* @param Length 要显示数字的长度,范围:1~10
* @param FLength 要显示的小数点后几位
* @retval 无
*/
void OLED_ShowFNum(uint8_t Line, uint8_t Column, float Number, uint8_t Length, uint8_t FLength)
{
uint8_t i;
uint8_t flag = 1; // 标志是否为小数部分
float Number1;
uint32_t Number2;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
Number2 = (int)(Number1*OLED_Pow(10, FLength)); // 小数转换成整数
for(i = Length; i > 0; i--)
{
if(i == Length - FLength)
{
OLED_ShowChar(Line, Column + i + flag, '.');
flag = 0;
}
OLED_ShowChar(Line, Column + i + flag, Number2/OLED_Pow(10, Length-i)%10+'0');
}
}

void OLED_ShowCC_F16x16(uint8_t Line, uint8_t Column, uint8_t num)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 16; i++)
{
OLED_WriteData(CC_F16x16[num*2][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 16; i++)
{
OLED_WriteData(CC_F16x16[num*2][i + 16]); //显示下半部分内容
}
}

/**
* @brief OLED初始化
* @param 无
* @retval 无
*/
void OLED_Init(void)
{
uint32_t i, j;

for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}

OLED_I2C_Init(); //端口初始化

OLED_WriteCommand(0xAE); //关闭显示

OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCommand(0x80);

OLED_WriteCommand(0xA8); //设置多路复用率
OLED_WriteCommand(0x3F);

OLED_WriteCommand(0xD3); //设置显示偏移
OLED_WriteCommand(0x00);

OLED_WriteCommand(0x40); //设置显示开始行

OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置

OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置

OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
OLED_WriteCommand(0x12);

OLED_WriteCommand(0x81); //设置对比度控制
OLED_WriteCommand(0xCF);

OLED_WriteCommand(0xD9); //设置预充电周期
OLED_WriteCommand(0xF1);

OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
OLED_WriteCommand(0x30);

OLED_WriteCommand(0xA4); //设置整个显示打开/关闭

OLED_WriteCommand(0xA6); //设置正常/倒转显示

OLED_WriteCommand(0x8D); //设置充电泵
OLED_WriteCommand(0x14);

OLED_WriteCommand(0xAF); //开启显示

OLED_Clear(); //OLED清屏
}
-------------本文结束!感谢您的阅读-------------