模块来源
采购链接:
https://item.taobao.com/item.htm?id=37849023766&_u=n1q56pn343e4
资料下载链接:
https://pan.baidu.com/s/1PUAFSSejSUb9ddEPrin_UA
资料提取码:g4xn
规格参数
工作电压:3.3V
工作电流:15MA
模块尺寸:27.3 x 27.8 MM
像素大小:128(H) x 64(V)RGB
驱动芯片:SSD1306
通信协议:SPI
管脚数量:7 Pin(2.54mm间距排针)
移植过程
引脚选择
该模块需要设置7个接口
模块为SPI通信协议的从机,D0为SPI信号线(SCK),D1为SPI输出线(MOSI),CS为SPI片选线(NSS)。
这里选择的引脚见引脚接线表
代码移植
下载为大家准备的驱动代码文件夹,复制到自己工程中\luban-lite\application\rt-thread\helloworld\user-bsp
文件夹下
提示
如果未找到 user-bsp
这个文件夹,说明你未进行模块移植的前置操作。请转移到手册使用必要操作(点击跳转)中进行必要的配置操作!!!
接下来打开自己的工程,开始修改Kconfig文件。
1、在 VSCode 中打开 application\rt-thread\helloworld\Kconfig 文件
2、在该文件的 #endif
前面添加该模块的 Kconfig路径语句
# 0.96寸SPI单色屏
source "application/rt-thread/helloworld/user-bsp/0-96-single-spi-screen/Kconfig"
2
添加完成之后:
menuconfig操作
1、我们 双击 luban-lite
文件夹下的 win_env.bat
脚本打开env工具:
2、输入以下命令列出所有可用的默认配置:
scons --list-def
3、选择 d13x_JLC_rt-thread_helloworld
这个配置!这个是我们衡山派开发板的默认配置!输入以下命令即可:
scons --apply-def=7
或者
scons --apply-def=d13x_JLC_rt-thread_helloworld_defconfig
这两个命令作用是一样的,一个是 文件名 ,一个是 编号 !!!
4、输入以下命令进入menuconfig菜单
scons --menuconfig
进入以下界面:
5、选中 Porting code using the LCKFB module
按 Y
键!
按
Y
选中按
N
取消选中方向键
左右
调整 最下面菜单的选项方向键
上下
调整 列表的选项
回车
执行最下面菜单的选项
6、回车进入 Porting code using the LCKFB module
菜单
7、按方向键 上下
选中 Use 0.96 inch SPI monochrome screen
后按 Y
键,看到前面括号中出现一个 *
号,就可以下一步了。
8、按方向键 左右
选中 <Save>
然后一路回车
,然后 退出
即可
编译
我们 保存并退出menuconfig菜单 之后,输入以下命令进行编译:
scons
或
scons -j16
-j 用来选择参与编译的核心数: 我这里是选择16
大家可以根据自己的电脑来选择
核心越多编译越快
如果写的数量高于电脑本身,那么就自动按照最高可用的来运行!
镜像烧录
编译完成之后会在 \luban-lite\output\d13x_JLC_rt-thread_helloworld\images
文件夹下生成一个 d13x_JLC_v1.0.0.img
镜像文件!
然后我们烧录镜像,具体的教程请查看:镜像烧录(点击跳转🚀)
到这里完成了,请移步到 最后一节 进行移植验证。
工程代码解析
oled.c
#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#define OLED_DEVICE_NAME "oled"
static struct rt_qspi_device *oled_dev;
static u8 OLED_GRAM[144][8];
void delay_ms(int ms)
{
rt_thread_mdelay(ms);
}
void delay_us(int us)
{
rt_thread_mdelay(us);
}
void OLED_GPIO_Init(void)
{
/* 查找设备并获取设备句柄 */
oled_dev = (struct rt_qspi_device *)rt_device_find(OLED_DEVICE_NAME);
if (!oled_dev)
{
LOG_E("Qspi sample run failed! can't find %s device!\n", OLED_DEVICE_NAME);
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
}
rt_pin_mode(OLED_RES, PIN_MODE_OUTPUT); //配置引脚为输出模式
rt_pin_mode(OLED_DC, PIN_MODE_OUTPUT); //配置引脚为输出模式
rt_pin_mode(OLED_CS, PIN_MODE_OUTPUT); //配置引脚为输出模式
OLED_RES_Set();
OLED_DC_Set();
OLED_CS_Set();
rt_kprintf("OLED_GPIO_Init end!!\n");
}
//反显函数
void OLED_ColorTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
}
if(i==1)
{
OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
}
}
//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{
if(i==0)
{
OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
OLED_WR_Byte(0xA1,OLED_CMD);
}
if(i==1)
{
OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
OLED_WR_Byte(0xA0,OLED_CMD);
}
}
void OLED_WR_Byte(u8 dat,u8 cmd)
{
u8 count = 0;
struct rt_qspi_message msg;
rt_memset(&msg, 0, sizeof(msg));
msg.instruction.content = 0; /* 指令内容 */
msg.instruction.qspi_lines = 0; /* 指令模式,单线模式 1 位、双线模式 2 位,4 线模式 4 位 */
msg.alternate_bytes.content = 0; /* 地址/交替字节 内容 */
msg.alternate_bytes.size = 0; /* 地址/交替字节 长度 */
msg.alternate_bytes.qspi_lines = 0; /* 地址/交替字节 模式,单线模式 1 位、双线模式 2 位,4 线模式 4 位 */
msg.dummy_cycles = 0; /* 空指令周期阶段 */
msg.qspi_data_lines = 1; /* QSPI 总线位宽 */
// 传输一条消息,开始发送数据时片选选中,函数返回时释放片选。
msg.parent.send_buf = &dat; /* 发送缓冲区指针 */
msg.parent.recv_buf = RT_NULL; /* 接收缓冲区指针 */
msg.parent.length = 1; /* 发送 / 接收 数据字节数 */
msg.parent.next = RT_NULL; /* 指向继续发送的下一条消息的指针 */
msg.parent.cs_take = 1; /* 片选选中 */
msg.parent.cs_release = 1; /* 释放片选 */
if(cmd)
{
OLED_DC_Set(); // 写数据
}
else
{
OLED_DC_Clr(); // 写命令
}
rt_spi_take_bus((struct rt_spi_device *)oled_dev);
OLED_CS_Clr();
int ret = rt_qspi_transfer_message(oled_dev, &msg);;
if(ret != 1)
{
LOG_E("rt_qspi_transfer_message failed!!");
}
OLED_CS_Set();
rt_spi_release_bus((struct rt_spi_device *)oled_dev);
OLED_DC_Set();
}
//开启OLED显示
void OLED_DisPlay_On(void)
{
OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}
//关闭OLED显示
void OLED_DisPlay_Off(void)
{
OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}
//更新显存到OLED
void OLED_Refresh(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
OLED_WR_Byte(0x00,OLED_CMD); //设置低列起始地址
OLED_WR_Byte(0x10,OLED_CMD); //设置高列起始地址
for(n=0;n<128;n++)
OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);
}
}
//清屏函数
void OLED_Clear(void)
{
u8 i,n;
for(i=0;i<8;i++)
{
for(n=0;n<128;n++)
{
OLED_GRAM[n][i]=0;//清除所有数据
}
}
OLED_Refresh();//更新显示
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
void OLED_DrawPoint(u8 x,u8 y,u8 t)
{
u8 i,m,n;
i=y/8;
m=y%8;
n=1<<m;
if(t){OLED_GRAM[x][i]|=n;}
else
{
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
OLED_GRAM[x][i]|=n;
OLED_GRAM[x][i]=~OLED_GRAM[x][i];
}
}
//画线
//x1,y1:起点坐标
//x2,y2:结束坐标
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode)
{
u16 t;
int xerr=0,yerr=0,delta_x,delta_y,distance;
int incx,incy,uRow,uCol;
delta_x=x2-x1; //计算坐标增量
delta_y=y2-y1;
uRow=x1;//画线起点坐标
uCol=y1;
if(delta_x>0)incx=1; //设置单步方向
else if (delta_x==0)incx=0;//垂直线
else {incx=-1;delta_x=-delta_x;}
if(delta_y>0)incy=1;
else if (delta_y==0)incy=0;//水平线
else {incy=-1;delta_y=-delta_x;}
if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
else distance=delta_y;
for(t=0;t<distance+1;t++)
{
OLED_DrawPoint(uRow,uCol,mode);//画点
xerr+=delta_x;
yerr+=delta_y;
if(xerr>distance)
{
xerr-=distance;
uRow+=incx;
}
if(yerr>distance)
{
yerr-=distance;
uCol+=incy;
}
}
}
//x,y:圆心坐标
//r:圆的半径
void OLED_DrawCircle(u8 x,u8 y,u8 r)
{
int a, b,num;
a = 0;
b = r;
while(2 * b * b >= r * r)
{
OLED_DrawPoint(x + a, y - b,1);
OLED_DrawPoint(x - a, y - b,1);
OLED_DrawPoint(x - a, y + b,1);
OLED_DrawPoint(x + a, y + b,1);
OLED_DrawPoint(x + b, y + a,1);
OLED_DrawPoint(x + b, y - a,1);
OLED_DrawPoint(x - b, y - a,1);
OLED_DrawPoint(x - b, y + a,1);
a++;
num = (a * a + b * b) - r*r;//计算画的点离圆心的距离
if(num > 0)
{
b--;
a--;
}
}
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//size1:选择字体 6x8/6x12/8x16/12x24
//mode:0,反色显示;1,正常显示
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode)
{
u8 i,m,temp,size2,chr1;
u8 x0=x,y0=y;
if(size1==8)size2=6;
else size2=(size1/8+((size1%8)?1:0))*(size1/2); //得到字体一个字符对应点阵集所占的字节数
chr1=chr-' '; //计算偏移后的值
for(i=0;i<size2;i++)
{
if(size1==8)
{temp=asc2_0806[chr1][i];} //调用0806字体
else if(size1==12)
{temp=asc2_1206[chr1][i];} //调用1206字体
else if(size1==16)
{temp=asc2_1608[chr1][i];} //调用1608字体
else if(size1==24)
{temp=asc2_2412[chr1][i];} //调用2412字体
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((size1!=8)&&((x-x0)==size1/2))
{x=x0;y0=y0+8;}
y=y0;
}
}
//显示字符串
//x,y:起点坐标
//size1:字体大小
//*chr:字符串起始地址
//mode:0,反色显示;1,正常显示
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode)
{
while((*chr>=' ')&&(*chr<='~'))//判断是不是非法字符!
{
OLED_ShowChar(x,y,*chr,size1,mode);
if(size1==8)x+=6;
else x+=size1/2;
chr++;
}
}
//m^n
u32 OLED_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)
{
result*=m;
}
return result;
}
//显示数字
//x,y :起点坐标
//num :要显示的数字
//len :数字的位数
//size:字体大小
//mode:0,反色显示;1,正常显示
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode)
{
u8 t,temp,m=0;
if(size1==8)m=2;
for(t=0;t<len;t++)
{
temp=(num/OLED_Pow(10,len-t-1))%10;
if(temp==0)
{
OLED_ShowChar(x+(size1/2+m)*t,y,'0',size1,mode);
}
else
{
OLED_ShowChar(x+(size1/2+m)*t,y,temp+'0',size1,mode);
}
}
}
//显示汉字
//x,y:起点坐标
//num:汉字对应的序号
//mode:0,反色显示;1,正常显示
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode)
{
u8 m,temp;
u8 x0=x,y0=y;
u16 i,size3=(size1/8+((size1%8)?1:0))*size1; //得到字体一个字符对应点阵集所占的字节数
for(i=0;i<size3;i++)
{
if(size1==16)
{temp=Hzk1[num][i];}//调用16*16字体
else if(size1==24)
{temp=Hzk2[num][i];}//调用24*24字体
else if(size1==32)
{temp=Hzk3[num][i];}//调用32*32字体
else if(size1==64)
{temp=Hzk4[num][i];}//调用64*64字体
else return;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==size1)
{x=x0;y0=y0+8;}
y=y0;
}
}
//num 显示汉字的个数
//space 每一遍显示的间隔
//mode:0,反色显示;1,正常显示
void OLED_ScrollDisplay(u8 num,u8 space,u8 mode)
{
u8 i,n,t=0,m=0,r;
while(1)
{
if(m==0)
{
OLED_ShowChinese(128,24,t,16,mode); //写入一个汉字保存在OLED_GRAM[][]数组中
t++;
}
if(t==num)
{
for(r=0;r<16*space;r++) //显示间隔
{
for(i=1;i<144;i++)
{
for(n=0;n<8;n++)
{
OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
}
}
OLED_Refresh();
}
t=0;
}
m++;
if(m==16){m=0;}
for(i=1;i<144;i++) //实现左移
{
for(n=0;n<8;n++)
{
OLED_GRAM[i-1][n]=OLED_GRAM[i][n];
}
}
OLED_Refresh();
}
}
//x,y:起点坐标
//sizex,sizey,图片长宽
//BMP[]:要写入的图片数组
//mode:0,反色显示;1,正常显示
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode)
{
u16 j=0;
u8 i,n,temp,m;
u8 x0=x,y0=y;
sizey=sizey/8+((sizey%8)?1:0);
for(n=0;n<sizey;n++)
{
for(i=0;i<sizex;i++)
{
temp=BMP[j];
j++;
for(m=0;m<8;m++)
{
if(temp&0x01)OLED_DrawPoint(x,y,mode);
else OLED_DrawPoint(x,y,!mode);
temp>>=1;
y++;
}
x++;
if((x-x0)==sizex)
{
x=x0;
y0=y0+8;
}
y=y0;
}
}
}
//OLED的初始化
void OLED_Init(void)
{
OLED_GPIO_Init();
OLED_RES_Clr();
delay_ms(200);
OLED_RES_Set();
OLED_WR_Byte(0xAE,OLED_CMD);//--turn off oled panel
OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
OLED_WR_Byte(0x40,OLED_CMD);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
OLED_WR_Byte(0x81,OLED_CMD);//--set contrast control register
OLED_WR_Byte(0xCF,OLED_CMD);// Set SEG Output Current Brightness
OLED_WR_Byte(0xA1,OLED_CMD);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
OLED_WR_Byte(0xC8,OLED_CMD);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
OLED_WR_Byte(0xA6,OLED_CMD);//--set normal display
OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
OLED_WR_Byte(0x3f,OLED_CMD);//--1/64 duty
OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
OLED_WR_Byte(0x00,OLED_CMD);//-not offset
OLED_WR_Byte(0xd5,OLED_CMD);//--set display clock divide ratio/oscillator frequency
OLED_WR_Byte(0x80,OLED_CMD);//--set divide ratio, Set Clock as 100 Frames/Sec
OLED_WR_Byte(0xD9,OLED_CMD);//--set pre-charge period
OLED_WR_Byte(0xF1,OLED_CMD);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
OLED_WR_Byte(0xDA,OLED_CMD);//--set com pins hardware configuration
OLED_WR_Byte(0x12,OLED_CMD);
OLED_WR_Byte(0xDB,OLED_CMD);//--set vcomh
OLED_WR_Byte(0x40,OLED_CMD);//Set VCOM Deselect Level
OLED_WR_Byte(0x20,OLED_CMD);//-Set Page Addressing Mode (0x00/0x01/0x02)
OLED_WR_Byte(0x02,OLED_CMD);//
OLED_WR_Byte(0x8D,OLED_CMD);//--set Charge Pump enable/disable
OLED_WR_Byte(0x14,OLED_CMD);//--set(0x10) disable
OLED_WR_Byte(0xA4,OLED_CMD);// Disable Entire Display On (0xa4/0xa5)
OLED_WR_Byte(0xA6,OLED_CMD);// Disable Inverse Display On (0xa6/a7)
OLED_Clear();
OLED_WR_Byte(0xAF,OLED_CMD);
}
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
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
oled.h
#ifndef __OLED_H
#define __OLED_H
#include <stdio.h>
#include <inttypes.h>
#include <getopt.h>
#include <sys/time.h>
#include <rtthread.h>
#include "rtdevice.h"
#include "aic_core.h"
#include "aic_hal_gpio.h"
#ifndef u8
#define u8 uint8_t
#endif
#ifndef u16
#define u16 uint16_t
#endif
#ifndef u32
#define u32 uint32_t
#endif
//-----------------OLED端口移植----------------
#define OLED_RES rt_pin_get("PC.7")
#define OLED_DC rt_pin_get("PE.16")
#define OLED_CS rt_pin_get("PC.9")
//-----------------OLED端口定义----------------
#define OLED_RES_Clr() rt_pin_write(OLED_RES, 0)//RES
#define OLED_RES_Set() rt_pin_write(OLED_RES, 1)
#define OLED_DC_Clr() rt_pin_write(OLED_DC, 0)//DC
#define OLED_DC_Set() rt_pin_write(OLED_DC, 1)
#define OLED_CS_Clr() rt_pin_write(OLED_CS, 0)//CS
#define OLED_CS_Set() rt_pin_write(OLED_CS, 1)
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
void delay_us(int us);
void delay_ms(int ms);
void OLED_ClearPoint(u8 x,u8 y);
void OLED_ColorTurn(u8 i);
void OLED_DisplayTurn(u8 i);
void OLED_WR_Byte(u8 dat,u8 mode);
void OLED_DisPlay_On(void);
void OLED_DisPlay_Off(void);
void OLED_Refresh(void);
void OLED_Clear(void);
void OLED_DrawPoint(u8 x,u8 y,u8 t);
void OLED_DrawLine(u8 x1,u8 y1,u8 x2,u8 y2,u8 mode);
void OLED_DrawCircle(u8 x,u8 y,u8 r);
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size1,u8 mode);
void OLED_ShowChar6x8(u8 x,u8 y,u8 chr,u8 mode);
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size1,u8 mode);
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size1,u8 mode);
void OLED_ShowChinese(u8 x,u8 y,u8 num,u8 size1,u8 mode);
void OLED_ScrollDisplay(u8 num,u8 space,u8 mode);
void OLED_ShowPicture(u8 x,u8 y,u8 sizex,u8 sizey,u8 BMP[],u8 mode);
void OLED_Init(void);
#endif
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
Kconfig
这个是一个menuconfig中的选项,如果在菜单中选中该选项,就会在rtconfig.h
中定义一个语句,用来if判断条件编译之类的。
config LCKFB_0_96_SINGLE_SPI_SCREEN
bool "Use 0.96 inch SPI monochrome screen"
select AIC_USING_QSPI3
default n
help
More information is available at: https://wiki.lckfb.com/
2
3
4
5
6
7
SConscript
自动化构建文件,如果定义了 LCKFB_0_96_SINGLE_SPI_SCREEN
和 USING_LCKFB_TRANSPLANT_CODE
就自动编译当前目录下的文件!!
Import('RTT_ROOT')
Import('rtconfig')
import rtconfig
from building import *
cwd = GetCurrentDir()
CPPPATH = [cwd]
src = []
if GetDepend('LCKFB_0_96_SINGLE_SPI_SCREEN') and GetDepend('USING_LCKFB_TRANSPLANT_CODE'):
src = Glob(os.path.join(cwd, '*.c'))
group = DefineGroup('lckfb-0-96-single-spi-screen', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test_0_96_single_spi_screen.c
这个文件定义了一个用于控制0.96寸SPI接口的单色OLED屏幕显示的线程,并设置了线程的优先级、栈大小和时间片。同时,它还包含了QSPI接口的初始化和OLED设备挂载的函数。
以下是文件中定义的主要功能:
oled_qspi_attach
函数:用于挂载QSPI的OLED设备,为QSPI设备结构体分配内存,并将其附加到QSPI总线上。oled_qspi_init
函数:用于配置QSPI接口进行初始化,设置QSPI的工作模式和参数,如总线位宽、模式、数据位宽和最大频率。oled_thread_entry
函数:这是线程的入口函数,用于初始化OLED屏幕,清除屏幕内容,并在屏幕上显示固定的文本和动态变化的数字。test_0_96_single_spi_screen
函数:这是主测试函数,它调用上述两个初始化函数,并创建并启动OLED显示线程。如果初始化或线程创建失败,将打印错误信息。
线程入口函数的逻辑如下:
- 初始化OLED屏幕并清除屏幕。
- 在一个无限循环中,显示不同大小的英文字符串“ABC”。
- 显示一个动态增加的数字,该数字会在达到99后重置为0。
- 刷新OLED屏幕以显示更改。
- 每次循环结束时,线程会挂起一段时间,这里是500毫秒。
在代码的最后,MSH_CMD_EXPORT
宏导出了test_0_96_single_spi_screen
函数,使其可以通过命令行接口访问。这样用户就可以通过输入命令来启动OLED屏幕的测试线程。
#include <stdio.h>
#include <inttypes.h>
#include <string.h>
#include <finsh.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <drv_qspi.h>
#include "aic_core.h"
#include "aic_hal_gpio.h"
#include "oled.h"
#define THREAD_PRIORITY 25 // 线程优先级
#define THREAD_STACK_SIZE 4096 // 线程大小
#define THREAD_TIMESLICE 10 // 时间片
#define QPSI_BUS_NANE "qspi3" // qspi总线名称
#define QPSI_DEVICE_NAME "oled" // qspi设备名称
static struct rt_qspi_device *qspi_device = RT_NULL; // qspi设备结构体
static rt_thread_t lcd_thread = RT_NULL; // 线程控制块
/**********************************************************
* 函 数 名 称:oled_qspi_attach
* 函 数 功 能:挂载qspi的oled设备
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:LP
**********************************************************/
static int oled_qspi_attach(void)
{
// 为spi结构体申请一片空间
qspi_device = (struct rt_qspi_device *)rt_malloc(sizeof(struct rt_qspi_device));
if(RT_NULL == qspi_device)
{
LOG_E("Failed to malloc the qspi device.");
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return -RT_ENOMEM;
}
rt_kprintf("malloc the qspi succeed.\r\n");
qspi_device->enter_qspi_mode = RT_NULL;
qspi_device->exit_qspi_mode = RT_NULL;
qspi_device->config.qspi_dl_width = 1;
int ret = rt_spi_bus_attach_device(&qspi_device->parent, QPSI_DEVICE_NAME, QPSI_BUS_NANE, RT_NULL);
if(ret != RT_EOK)
{
LOG_E("Failed to rt_spi_bus_attach_device.");
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return ret;
}
return RT_EOK;
}
/**********************************************************
* 函 数 名 称:oled_qspi_init
* 函 数 功 能:配置qspi进行初始化
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:LP
**********************************************************/
static int oled_qspi_init(void)
{
struct rt_qspi_device *g_qspi;
struct rt_qspi_configuration qspi_cfg;
struct rt_device *dev;
char *name;
int ret = 0;
name = QPSI_DEVICE_NAME;
g_qspi = (struct rt_qspi_device *)rt_device_find(name);
if (!g_qspi)
{
LOG_E("Failed to get device in name %s\n", name);
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return -1;
}
dev = (struct rt_device *)g_qspi;
if (dev->type != RT_Device_Class_SPIDevice)
{
g_qspi = NULL;
LOG_E("%s is not SPI device.\n", name);
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return -1;
}
rt_memset(&qspi_cfg, 0, sizeof(qspi_cfg));
qspi_cfg.qspi_dl_width = 1; // QSPI 总线位宽,单线模式 1 位、双线模式 2 位,4 线模式 4 位
qspi_cfg.parent.mode = RT_SPI_MASTER | RT_SPI_MODE_3 | RT_SPI_MSB;
qspi_cfg.parent.data_width = 8;
qspi_cfg.parent.max_hz = 20 * 1000 * 1000; // 20M
ret = rt_qspi_configure(g_qspi, &qspi_cfg);
if (ret < 0)
{
LOG_E("qspi configure failure.");
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return ret;
}
return RT_EOK;
}
// 线程入口函数
static void oled_thread_entry(void *param)
{
int t = 0;
OLED_Init(); //初始化OLED
OLED_Clear();
while(1)
{
if(t >= 99)
t = 0;
OLED_ShowString(0,0,(uint8_t *)"ABC",8,1);//6*8 “ABC”
OLED_ShowString(0,8,(uint8_t *)"ABC",12,1);//6*12 “ABC”
OLED_ShowString(0,20,(uint8_t *)"ABC",16,1);//8*16 “ABC”
OLED_ShowString(0,36,(uint8_t *)"ABC",24,1);//12*24 “ABC”
OLED_ShowNum(100, 20, t, 2, 24, 1);
t++;
OLED_Refresh();
rt_thread_mdelay(500);
}
}
/**********************************************************
* 函 数 名 称:test_0_96_single_spi_screen
* 函 数 功 能:0.96寸SPI单色屏测试程序
* 传 入 参 数:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:LP
**********************************************************/
static int test_0_96_single_spi_screen(void)
{
int ret = 0;
ret = oled_qspi_attach();
if(ret != RT_EOK)
{
LOG_E("[ oled_qspi_attach ] failure.");
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return RT_ERROR;
}
rt_kprintf("[ oled_qspi_attach ] succeed.\r\n");
ret = oled_qspi_init();
if(ret != RT_EOK)
{
LOG_E("[ oled_qspi_init ] failure.");
LOG_E("file: %s",__FILE__);
LOG_E("line: %d",__LINE__);
return RT_ERROR;
}
rt_kprintf("[ oled_qspi_init ] succeed.\r\n");
/* 创建线程,名称是 oled_thread,入口是 oled_thread_entry */
lcd_thread = rt_thread_create("oled_thread",
oled_thread_entry, RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY, THREAD_TIMESLICE);
/* 如果获得线程控制块,启动这个线程 */
if (lcd_thread != RT_NULL)
rt_thread_startup(lcd_thread);
return RT_EOK;
}
MSH_CMD_EXPORT(test_0_96_single_spi_screen, 0.96 single spi screen test);
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
移植验证
我们使用串口调试,将 USB转TTL模块 连接到衡山派开发板上面!!
具体的教程查看:串口调试(点击跳转🚀)
串口波特率默认为
115200
我们在输入下面的命令运行该模块的线程:
输入的时候按下
TAB键
会进行命令补全!!
test_0_96_single_spi_screen
上电效果: