1 Gui移植结果 一些演示效果:) e( g* `6 L. m# ]' c' q, a- B5 |
2 GuiLite介绍
1 c% D( U- d; z2 F h% g3 A* e GuiLite是一个开源的图形用户界面框架,只依赖于一个单一的头文件库(GuiLite.h),不需要很复杂的文件管理,代码量平易近人。+ n( ~. {+ u. b
GuiLite由4千行C++代码编写,单片机上也能流畅运行,其最低的硬件运行要求如下:: w: K) t( E! s+ O5 m$ i& n
5 X C3 q2 j- Q- a* K
$ q4 M. j' C" L+ d
B. }3 a5 s+ D; H( \
0 f1 |5 `% W" F6 |GuiLite具有很强的跨平台特性:- 支持的操作系统:iOS/macOS/WatchOS,Android,Linux(ARM/x86-64),Windows(包含VR),RTOS… 甚至无操作系统的单片机
- 支持的开发语言:C/C++, Swift, Java, Javascript, C#, Golang…
- 支持的第3方库:Qt, MFC, Winforms, CoCoa…
$ O' u6 I8 m! E - & ]% t. d# u' e9 i/ q( ?, A
, J/ Z2 f1 f3 c" O GuiLite 提供一系列辅助开发工具:- 完美的“云” + “物联网”解决方案:让你轻松驾驭全球IoT业务
- 支持多语言,采用 UTF-8 编码;
- 资源制作工具为你定制自己的字体/图片资源
- 所见即所得的GUI布局工具
- 编译活跃度统计,及实时分析
- 支持3D & Web
- 支持Docker,一条命令启动。
9 q# Q; v+ C7 z# X6 ~9 g + H, v+ J: Z, y* D- r
3 GuiLite移植2.1 所需硬件$ U! v' H1 V$ w
% v# [0 z; ]' ]5 O( y
2 g. J; Z' r- h1 V
$ _+ B" s5 ], C; W2 C! v+ X. e7 p4 y. d. ^/ M6 G
( M+ k7 S8 w( }- N8 ?: A$ {( J1 ASTM32F407开发板
3 K% G4 p; S2 S3 W8 `. t! J1 B7 ~ |1 ~
0 l/ _% v$ ]( e8 Q; N7 n
- X: \! B3 v0 A/ S2 ^) s: {& W
6 Z" l9 j0 X; A( r% m7 s
/ R+ K' ]/ |3 `' } b, N5 O( X
OLED屏幕! j6 |, G5 J' X) I( x
q- _& C- N$ i2 C9 d4 @# J- b* E/ q- |+ f' t5 T ~1 ^( _( w p. d( ]
2.2 驱动准备9 K: R& B( O7 b, a. k/ W
这里我使用STM32CubeMX 对开发板进行外设配置,开启STM32的硬件IIC,这里我用CubeMX开启后如下:
7 V& F' a! b5 V. c/ D! u
7 _" `4 m9 O0 G; k, R: {7 B$ P: _0 c7 O/ `$ y+ k0 q& Z/ y
* S- f2 m5 w4 p4 s- }" _
' a' @9 ^& ~* ], a
5 p% {* f+ V( f6 d 配置完成生成代码,同时将分配的堆空间增大:
( [2 l6 \% }/ T% K! Q8 [1 x. }
5 Q$ y; D/ _: Z. G; U7 i- W( n5 y0 n) b& j( a" P0 W
* J2 `. ]1 f& G& S" A3 I, ~" j1 [# P
: b' u6 R3 d- T* v- K% r
代码生成后,我们复制正点原子的OLED驱动工程代码到Hardware硬件目录下,自己创建一个该目录。4 {. r! g& T+ o8 N' ^4 ?$ X
- A u4 Q/ n3 J2 T1 x
8 w7 b7 b1 U1 q% s) ? ?2 V
" t' T. j2 N$ Z" a# Y( O
' s. `$ T, @% A: y3 @( c1 I/ D5 F4 L8 q
$ w6 Q2 O8 \- v+ [7 I( f 在MDK里面添加文件,然后我们进行修改,注释掉头文件里面关于端口的定义,同时添加三个类型宏定义。8 n1 L" R8 ~, T! l
+ H% @3 a- ?! k: W$ r- z2 s5 |
& ~) V, _. ^1 T8 h$ z5 E9 d
* w. l' X H) `" V3 B$ c+ Q6 W) t* X* o! {6 q( q( x+ u
然后我们进入oled.c文件,将void OLED_WR_Byte(u8 dat,u8 cmd)和 void OLED_Init(void)函数分别替换为下面的内容:
" ]3 f% I; V: d5 W4 `# ^& nOLED_WR_Byte:
' H( ^& b. O n# S7 Z- void OLED_WR_Byte(u8 dat,u8 cmd)0 U4 A Q6 D7 A" m; R6 r
- {
* z- g, Q9 Z9 r9 \9 D - if(cmd) t3 D8 u$ z. J7 z
- HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);
6 ~" z0 m q: I9 Y# u' a - else( ~- O e2 N7 Z" y. s; b7 F
- HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);
2 C2 J0 z3 S5 m# F! X - }
复制代码
/ [. ^2 F# z+ V. d# V* I# X5 T. Q; ^( Q2 @
( j3 W5 w s& Z7 `" _* _# G* q0 e. @9 [9 ^( j: W8 Q
OLED_Init:" a7 ?+ V* V6 |. w, A; X
- //初始化SSD1306 ( m8 s( w( ]% ^) A5 Z+ i
- void OLED_Init(void)
) T# z1 h; M8 \' W4 H4 P - {
' w" T; ~; Q `. R' w - OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示
7 U4 ?" `& {9 l( w - OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
- l8 l' ?0 d% B4 b! y' z/ S - OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率5 z( ~+ _2 F8 r7 j# t
- OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数7 w! B8 c/ t7 \7 z2 Q
- OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) " W% w, g2 A5 Y* l7 P+ N
- OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
, |3 Z( l7 s3 R% u7 r0 p/ K6 w - OLED_WR_Byte(0X00,OLED_CMD); //默认为05 I8 X$ A. r* ?1 E" ?
- ; c: o9 `' e1 {
- OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.
9 L0 \+ e7 N4 ?7 W. `) D - : V1 G1 K1 N0 b0 M
- OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置
# i2 b1 E# J' L# K$ V* @0 p8 Q - OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭
+ s: S6 v( S' Y6 _) j8 Y - OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式# U* u# _, O& [9 }7 q6 Q* V% e& I4 a [
- OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;4 R" f( ~1 @1 T& g
- OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
, ~* E5 {9 x0 x2 ` _% c1 s - OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数; v0 J' _4 z# A: F3 _3 @
- OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置$ N I1 S/ _: I i
- OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置! h' F' s* F& k/ D) ~# M" Z- M
- . q. {6 {9 [7 p" z- }# B
- OLED_WR_Byte(0x81,OLED_CMD); //对比度设置
6 e/ b/ X5 Y5 U; E - OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮). H+ G- i! i& u' j2 h
- OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期, }$ w$ _1 A" h* _
- OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;0 l, s: n3 o/ u; S- D
- OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率* d) Y4 {# M3 r6 B
- OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;. i2 w2 q3 [& z, i' p0 l
- " }, m% ]! t6 [- [" l0 r. o
- OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)+ j" l% V1 T0 R; m( l* G
- OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 - ~' ]4 e- x' o* @; ?
- OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 % H% j$ d: w/ z) j
- OLED_Clear();! ~& s4 A7 E- v2 ?7 `2 @3 x. E
- }
复制代码
$ y; `) T% b( r) [- x- d) J3 I( O, c2 |0 ?2 t0 c' I
然后在main.c文件如下位置添加oled测试代码,记得添加头文件和头文件路径。
# I( n( p& a8 @2 `+ q$ n r. Y7 q4 H1 c/ A
! b) N" r, q1 t2 v* w! c
. T- T: @. c% d
/ _" |# s" e/ v6 h9 g, S% k. n4 ?
下载程序,观看现象:: W# X N. t' s$ X
4 A' r7 m, n! `& H o$ N3 d+ R! g! u
: A7 m3 \- b8 @9 F# Z! ^
5 D) R* F2 v0 W6 p- {& ^0 k, a8 H2 v0 l- j
此 OLED 驱动的准备已经完成,下一步就是移植 GuiLite。: t: Y: E8 x7 j+ j7 }' r/ Q& N
# a9 m$ o# s2 H5 @8 H( G
4 Q) n1 D E# H6 N
2.3 例程移植
4 s; O+ B; k7 m# c6 W' I2 O, S8 x$ ^ 首先,我们上GuiLite的例程展示官网:GuiLiteDemo,选择Hello例程,将其中的 UI_Code文件夹复制到 Hardware 下:
& { u3 I% ]1 o2 z& l5 C9 B% e8 G* t9 u% V2 e) n+ t' R" X
4 @0 x% O" E& E- x- L
8 n0 R8 t0 V) N; A* s- Q# _2 `8 Z. V \* V. M. m% G
' i( M1 G# ]$ H; L' l* i- O, P 在 MDK 工程里面导入UICode下的GuiLite.h和UIcode.cpp文件。
: n8 x, |2 r2 C" o6 [, B4 G& H A0 a; g) U9 i$ l
]) h+ X* v5 w8 B9 ?* l2 D) w
! _0 b4 m: c9 j# F, m* ~3 h3 R- b8 g
) [( R' Y: z/ ^9 ^4 I- s+ |; S( v
8 y! l# e, X3 q$ V0 j 我们在 main.c 文件开头添加 GuiLite 接口代码,接口代码如下:, M$ v8 Y L) L3 \7 x, _( M5 [
- //画点函数接口
0 V" P8 n4 C# N - void gfx_draw_pixel(int x, int y, unsigned int rgb)
: ?: z$ D* L5 ~2 j - {: m% E0 e/ D# _: [. e2 \' }; V z
- OLED_DrawPoint(x,y,rgb);
4 F+ f0 R+ j7 F5 ~+ c - }
: S8 Z( A' a" ^0 }- @0 V - //画面函数(未使用)
5 x( r$ J/ @. f+ h, x - void gfx_draw_fill(int x, int y,int w, int q, unsigned int rgb)
c6 O L1 `8 Y( L* a+ d L" ~ - { , U: q/ X- _( p8 @- m
- }
: M# N4 H8 u0 N6 e - //创建一个函数指针结构体
& b1 q2 _% Z' }6 Y - struct EXTERNAL_GFX_OP- {+ u6 p' G0 }: f* Y" S5 s, x
- {* M* L% B: b6 X; C3 E5 D- b2 }: h
- void (*draw_pixel)(int x, int y, unsigned int rgb);4 g7 _. |0 o2 w
- void (*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb);
. B7 W% T$ i+ B+ j - } my_gfx_op;
0 ?" k' M( V# X% H! ?; |) w - extern void startHelloCircle(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op);8 w7 R: ^2 f. S& H: j
' }4 I, F3 C# S, N- //设定延时函数接口' [& }: v& J( Z
- void delay_ms(int milli_seconds)6 w$ b1 m1 F. L$ z" k6 p, X
- {) l: \7 \( `: Z& P5 ~9 Y7 w; r
- HAL_Delay(milli_seconds);* F+ h7 c0 n' e# `3 @/ V/ Z9 G
- }
复制代码 - K3 H W1 M& l. a2 H. U2 j5 L
' T, N3 z6 I! }1 S) V% ~/ m" ?
7 K1 k* u/ L. H
之后在main函数中添加如下代码: B! r' j2 _+ q% C% C
- //传递函数指针
5 n: [$ |/ h9 Z* t* D' i' L - my_gfx_op.draw_pixel = gfx_draw_pixel;8 E7 |6 D: Q& L: N" d% U1 S
- my_gfx_op.fill_rect = NULL;//gfx_fill_rect;
9 W: t* A% i& V2 @: b1 |( u* E - //启动画圆
i" E2 ?; j- ?8 Y. q - startHelloCircle(NULL, 128, 64, 1, &my_gfx_op);
复制代码
* L I8 L' O2 z" o& ]5 ]
, I& P% f. o: `* |' _/ U 然后我们修改UIcode.cpp文件中的代码,添加OLED头文件,以及在UI执行函数界面处添加OLED刷新函数。: Q- u3 P( q/ h
" |% b7 T& Q% u& I5 _
7 q$ f% t: ]& U, Z G4 E- ~" |* K
^5 O* r. k4 B3 n- p
! z+ a! D- f3 h( B% Y1 A) @+ r0 b. l) B0 F3 E% a; E) V
之后在UIcode的第8行修改3D圆的参数,因为OLED大小128x64 ,所以我的配置如下:$ W* }! z1 z3 c. _/ ?
( e$ u6 m+ _5 O: E1 G; ^
/ P9 ? K( {6 C+ t% J
( e1 ~; ^5 I N T Z! s# W( S7 ?
/ ~! h/ ^" j4 B. i
. f$ \5 M7 Y: S2 \ 配置完成后,我们关闭Use MicroLIB选项,编译代码:
2 u7 J! r$ L8 J( U- o# n5 a
: |* X) o! x; q' e8 [- \2 T6 r- ?
) \1 t' [6 o# t5 o
1 N6 z! N2 w- h( C6 |1 p
$ Z* X: ~) K4 f3 }2 ^* G 编译成功,下载代码。
7 v- [$ Y( J. p& W5 _" a2 b7 |+ l4 k8 E6 n
& B& w4 o3 t3 X6 x% @0 z5 `
/ k2 a# ~% v/ v0 X4 h0 M
( E7 \# E3 d; I. g/ g/ Y0 z0 v- W* @8 m5 j
下载完成后程序复位,可以在OLED上看到Demo的示例动画。
6 A/ S B6 c' o! r: @$ g& {8 f0 q& K- |* \% V& t4 f
- P8 b3 x- ]0 d, c
u- p, L$ t. Y5 M( L( o: }( Z! R% i2 z
转载自:[url=]芯片之家[/url]
" w' t/ C; ^' I: e! b1 h& F3 m) O/ I
9 l2 q! I8 O4 I |