1 Gui移植结果 一些演示效果:; M" K0 w; v* }; \4 r
2 GuiLite介绍0 c$ i+ D( u6 K5 F& X
GuiLite是一个开源的图形用户界面框架,只依赖于一个单一的头文件库(GuiLite.h),不需要很复杂的文件管理,代码量平易近人。 M1 N0 { e7 {1 n. ^
GuiLite由4千行C++代码编写,单片机上也能流畅运行,其最低的硬件运行要求如下:* F! ~2 V" G# I4 H& {" o3 V
! l- Z% {+ P) i5 W1 ^- a }+ q K1 |, N# V1 \3 D
5 [6 d& v6 Z, V
5 [+ \8 }, f# T d- e1 ZGuiLite具有很强的跨平台特性:- 支持的操作系统:iOS/macOS/WatchOS,Android,Linux(ARM/x86-64),Windows(包含VR),RTOS… 甚至无操作系统的单片机
- 支持的开发语言:C/C++, Swift, Java, Javascript, C#, Golang…
- 支持的第3方库:Qt, MFC, Winforms, CoCoa…
( G& F/ R# T" D# A& p - / |5 ^2 v% t K, B7 Z
0 C) X8 C. x2 m GuiLite 提供一系列辅助开发工具:- 完美的“云” + “物联网”解决方案:让你轻松驾驭全球IoT业务
- 支持多语言,采用 UTF-8 编码;
- 资源制作工具为你定制自己的字体/图片资源
- 所见即所得的GUI布局工具
- 编译活跃度统计,及实时分析
- 支持3D & Web
- 支持Docker,一条命令启动。
5 D( S- K3 d/ N. i# K4 N
9 K0 a; x. V* N, r* d G) [3 GuiLite移植2.1 所需硬件
- ]: N1 w* O; E
7 t5 a. }, ^" P- ~, y. C3 a* j5 u6 ~( {
/ Q( I/ \7 z3 [7 V8 ~0 j: ]* C) _7 ]; D
* n8 H- _) U. n) {
, W! M V' e) l/ q: A. qSTM32F407开发板) q* i& M8 _' ^' U4 B
$ a Q7 G ~ M
; `" D$ Z# [8 o# W Z% r. J7 }
! \/ n# B7 H7 b$ W
" |( l3 a, D8 `, N) F/ `3 z* X, o
OLED屏幕
3 Q, Z8 i1 w/ x g
0 V* v# N U, y9 t* j4 \9 N8 g$ Q0 v$ o, G# f3 P) K
2.2 驱动准备
$ {, F2 [/ ~$ r/ i; Y4 k 这里我使用STM32CubeMX 对开发板进行外设配置,开启STM32的硬件IIC,这里我用CubeMX开启后如下:
9 \$ M, v, s F6 t, I0 o4 F* m6 {" @- G( W0 Q
7 m( P+ p( d l/ c. J
5 w9 T: Z: c/ f
% B! U4 {1 v0 Y) [/ u+ g* L
7 {/ @; H0 P+ N) o( {6 h 配置完成生成代码,同时将分配的堆空间增大:$ C& d3 S& Z. R+ O
* Y1 @3 _+ y! B, o! e/ y2 ^
- k( [. {( H$ [0 c4 j
! N" o, e+ J; R, F
+ p t" u2 O' e ]8 M" y8 W3 L4 m, ~4 l% E, T. q
代码生成后,我们复制正点原子的OLED驱动工程代码到Hardware硬件目录下,自己创建一个该目录。
5 Z. w" N% z1 z5 w' Z* y
1 B5 B1 m$ m- g$ n/ g8 j' }
0 Z4 Z( {/ r/ y: g+ V3 q
8 c% U8 |8 n3 z! l* ]8 U$ C1 _& h+ U) j4 ` L
5 O& }. f j, C1 g3 I 在MDK里面添加文件,然后我们进行修改,注释掉头文件里面关于端口的定义,同时添加三个类型宏定义。& ]6 N1 s- O7 h. F& p
# l" j, M, c _! b0 v \; i! U
( E) e% I6 P# Z# H H& h; |9 I8 F: V1 D3 S }$ V5 |
) ^* y$ x3 m9 `$ x( {/ \ 然后我们进入oled.c文件,将void OLED_WR_Byte(u8 dat,u8 cmd)和 void OLED_Init(void)函数分别替换为下面的内容:
" ?2 v: f- ~$ D) W& COLED_WR_Byte:
. {! e8 |5 e" X+ ~2 J( f1 v- void OLED_WR_Byte(u8 dat,u8 cmd)
@) N! ^5 I/ R0 Z v - { ' F" |& ]/ Q6 Q. t3 g* ]9 R: u
- if(cmd)
, _4 L* C; g% _$ }$ s2 R4 h - HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);0 K3 T8 M2 Z0 Z" K/ {$ R
- else
# X* J5 u% S) ]1 H - HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);
- N$ |$ i B P7 I) j. V - }
复制代码
) @8 T6 D- O( G& F) @5 E6 ~
: k4 {9 S# C8 }2 z: Y9 t- L2 j! y) q9 b4 A& ~9 L
OLED_Init:
$ W; L' P# q( t$ g9 K& q% e8 e+ ?- //初始化SSD1306 5 V. @5 U1 K+ c- M, K- E9 T
- void OLED_Init(void)' ?/ [" T" ^ Q f: i& h
- {
5 e. m7 l; j/ \! Y - OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示& f: h' k/ j7 k# e' X4 c
- OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率" a. j2 l0 k% Q2 x0 |; E' x7 V
- OLED_WR_Byte(80,OLED_CMD); //[3:0],分频因子;[7:4],震荡频率
4 T& A( {# @/ K' e# l+ r, ~$ Y3 r6 n - OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数0 r' H' h# j, Q. ?
- OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64)
/ _7 q/ v6 ~0 E; }' h B - OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移
2 _# a) f9 P- u - OLED_WR_Byte(0X00,OLED_CMD); //默认为0
, m6 a; B6 n/ g* k! L6 r1 B
* h8 X& ?, ?4 W7 ?- OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.
9 M% ^; Y8 `: a2 g - ( M3 Z) s* u6 i& x/ z, Z
- OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置
5 U* c9 f; L- n! i1 [' u - OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭: i. O+ ~! k( l) }4 R
- OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式
7 R' L9 n% N. \3 P o+ }2 ^ - OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;$ @: {* a, r" n1 h: f9 y c
- OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
+ ~* i0 Q6 }3 e5 A1 ~- s - OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数4 l: E5 o5 e" [7 k m8 H
- OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置
9 m' n! ^+ @# \+ B: w8 x9 k3 O - OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置) }+ k* _1 o) {8 p$ P. |& Y6 l, H
- " x0 ~) v+ p9 @$ N1 R, ?9 v, ~0 ]
- OLED_WR_Byte(0x81,OLED_CMD); //对比度设置* I5 J7 X" |4 D
- OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)
' Q, z9 _9 K2 z7 W+ j8 y - OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期% \3 D; K5 k) x) \
- OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;: J* [7 m- j6 l2 D7 c: [9 b) N
- OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
% a- M0 C8 F' B - OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;' K5 @0 a" ^" a& X
- 7 u( D7 r/ e* d, K* i& _
- OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
" F+ x2 z# E* R& l9 ^ - OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示 - L2 |. O+ P: @+ a6 d6 e
- OLED_WR_Byte(0xAF,OLED_CMD); //开启显示 3 v0 D# k5 t* ~/ t6 B/ {
- OLED_Clear();/ m1 a$ n5 ~4 E( Y& t! w- N
- }
复制代码 5 x. X; f( U h$ J5 |$ H
+ z9 a! l9 a& d2 p. X7 J然后在main.c文件如下位置添加oled测试代码,记得添加头文件和头文件路径。8 g. f( C9 s0 r7 z& A; m$ l7 Z
% o1 j" s/ e; c; u, [1 [* ]; q5 Z/ a9 _
3 B4 ]! e0 ]- u9 q& J, g
9 I$ b5 O. z; _7 s! T" e# R/ O0 ~ ^8 i
下载程序,观看现象:# b4 c6 O9 s5 f5 Q7 K: M
! e: Y+ G* D+ G# D' @8 V+ E8 d
: ?4 D7 V; b E) ~ w7 n! z0 p
+ v# v$ C; q* B% u
0 l, t2 d8 E* i
3 H6 n+ N1 N2 F5 p; S( w0 ] 此 OLED 驱动的准备已经完成,下一步就是移植 GuiLite。# E- B+ E7 g, j2 i1 u& \
. p5 |% ~1 Z) w! ^
# G l/ R* Z T5 u& E2.3 例程移植: M. f6 k2 u4 v: T/ w
首先,我们上GuiLite的例程展示官网:GuiLiteDemo,选择Hello例程,将其中的 UI_Code文件夹复制到 Hardware 下:
8 X5 S, A, x$ Q3 Y, t1 ~- n! ^8 Z7 c, Z( a" z5 [, C5 U+ {/ A
* a4 ~2 k8 I" u8 R
' A: E3 n! z" B/ T, ]- z: Z! y5 P+ W" J- @
f( D. F! `2 t0 p& v 在 MDK 工程里面导入UICode下的GuiLite.h和UIcode.cpp文件。
1 z8 L$ Y e7 F0 f0 E4 P8 r9 U
2 z. T! S- B0 Q& Q8 J7 @
5 S/ U }8 O0 u; S2 _# D
2 b* I+ I2 X8 e) c" { L5 |9 D: @! k9 b% J
/ J q# v4 b6 Y) K
我们在 main.c 文件开头添加 GuiLite 接口代码,接口代码如下:
% ^0 @8 L( ?" @) y; }$ d- //画点函数接口
# y1 L) D) ] {/ C \ - void gfx_draw_pixel(int x, int y, unsigned int rgb)
$ Q1 j/ j' B' ^3 z7 G0 ^; K9 J - {7 w) d' g; U+ ?. W% |
- OLED_DrawPoint(x,y,rgb);
% }- I* Q% K- l7 W - }; f0 S1 B. n/ \& D3 _
- //画面函数(未使用)
/ Q+ e& ^3 q! d3 @1 P0 Q1 `& X - void gfx_draw_fill(int x, int y,int w, int q, unsigned int rgb)4 q; S, R2 ? p* G
- { 4 d2 O$ Z d, L8 j- {
- }- Z! N. D6 z* j' I9 o
- //创建一个函数指针结构体% C, ~* f+ d+ Z N! }1 E
- struct EXTERNAL_GFX_OP1 e* n j' s! o: [6 h, p
- {
! o+ |' b2 V2 c! a$ \ - void (*draw_pixel)(int x, int y, unsigned int rgb);
4 C, z& u. J2 M5 m2 A7 { - void (*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb);
. J, o3 c! _- ^ _3 ^ - } my_gfx_op;
: V5 U2 x! ^- X ^- L$ F - extern void startHelloCircle(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op);
2 Y5 E' v* |! } H( y% P/ C - ! @# j4 z0 K) T
- //设定延时函数接口' X( A8 D }& ~: d: j0 j
- void delay_ms(int milli_seconds)5 r/ B- o# J. [' v9 g5 H1 @
- {. H0 T# }5 Y# |' q- y
- HAL_Delay(milli_seconds);3 d5 k" I+ d7 L8 ?5 C8 ?& i/ O
- }
复制代码
1 U5 f/ H( {! c, y% k0 |0 ?3 K: r( t& ?
" T* T! n0 h/ P
之后在main函数中添加如下代码:! F. C( y1 O h( W. d
- //传递函数指针/ k% ^0 ^9 e4 ?5 L
- my_gfx_op.draw_pixel = gfx_draw_pixel;; _5 @+ e7 n9 e& m
- my_gfx_op.fill_rect = NULL;//gfx_fill_rect;
- o$ Y$ d5 j$ I/ Z2 e - //启动画圆
: _9 M; j! i' H3 I- {/ ?' e - startHelloCircle(NULL, 128, 64, 1, &my_gfx_op);
复制代码 % _6 g) L' ?% l7 q A1 a
5 S6 L: S4 m9 S: D
然后我们修改UIcode.cpp文件中的代码,添加OLED头文件,以及在UI执行函数界面处添加OLED刷新函数。! f* V; `& `( Q8 {
7 P( W. q$ f& [/ i; m; s2 D
6 V) F1 |! Q: ^7 b" j) s0 i
) h @9 t) P3 |# X( B" b
) Y4 w3 C$ l8 \/ M# i A7 ]. @
9 y8 A+ U ]' O# G/ U! K- s! K9 F 之后在UIcode的第8行修改3D圆的参数,因为OLED大小128x64 ,所以我的配置如下:2 I' f4 i; U- X# j: K$ u# V3 `1 a
- D% m% ?' I6 ]- d' o' A
' |% t3 G: N3 }, K$ ^. x( g! G
' C5 B# C0 Z- a3 y x
+ J+ B/ E, _$ V! r4 V) S3 }6 e. t$ G. l+ ?3 E& E0 f3 r4 O
配置完成后,我们关闭Use MicroLIB选项,编译代码:
& B; v, }5 f- V6 [
$ _' k3 q4 `) C/ N4 V' z
' s4 f* y3 m' @; C' s8 B
" o9 b* h2 G6 e- z0 K; ~# H: |2 d& j% ]! _
) b+ X1 O1 v# n+ Q1 H, R 编译成功,下载代码。
7 H' h7 O' m, ?5 g' o
6 g+ |! Z: R8 E; z8 R' @. Y# g/ ?+ \& \2 W; P% f6 T* G* R, z
* l. v# |, S8 h. q m" J
# |. M# z" X1 g2 d; \ y' L4 X0 {% Y
0 j' i! N: O/ k0 T# H5 E* k
下载完成后程序复位,可以在OLED上看到Demo的示例动画。
/ f* D4 b5 b; Y& {2 ^( @5 `8 w& k3 o
( _( q ]" o0 R9 z! E n8 S6 Y* k! u
9 h# p: z+ V5 ^6 v3 s2 z; m% Y
2 X& J* m; A1 \$ h
转载自:[url=]芯片之家[/url]# l4 g. c0 ^% u. L2 M6 m
: r: ?* Y1 N+ ^0 b; H" _
1 i# w4 B8 B+ C7 w8 Z+ e. ^: O% v |