你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

4000行代码的开源GuiLite,并移植到STM32

[复制链接]
STMCU小助手 发布时间:2023-3-4 20:00
1 Gui移植结果
    一些演示效果:
24.gif 33.gif
21.gif 20.gif
19.gif 18.gif

  g7 i# b' k4 q 17.gif
16.gif

$ e- u$ P9 P# f# W
2 GuiLite介绍/ I& T0 {9 {# A% h3 Y2 q$ `
    GuiLite是一个开源的图形用户界面框架,只依赖于一个单一的头文件库(GuiLite.h),不需要很复杂的文件管理,代码量平易近人。
9 ~: G& @9 r2 y( R    GuiLite由4千行C++代码编写,单片机上也能流畅运行,其最低的硬件运行要求如下:
( B& B& P. [6 a  H& S+ q- B. |' U1 B

. M/ r( k; h% D) D# p" g4 f. _ 15.png
& s. [; U; V* c! S/ q$ l* D; Z6 N2 Z' _1 o: n  t1 n
GuiLite具有很强的跨平台特性:
  • 支持的操作系统:iOS/macOS/WatchOS,Android,Linux(ARM/x86-64),Windows(包含VR),RTOS… 甚至无操作系统的单片机
  • 支持的开发语言:C/C++, Swift, Java, Javascript, C#, Golang…
  • 支持的第3方库:Qt, MFC, Winforms, CoCoa…9 M: q- w, k1 ^8 l& E8 E
  • . P; r  U6 h8 ?. t. o
    . n( ]; E8 f. L7 ?" i' o
GuiLite 提供一系列辅助开发工具:
  • 完美的“云” + “物联网”解决方案:让你轻松驾驭全球IoT业务
  • 支持多语言,采用 UTF-8 编码;
  • 资源制作工具为你定制自己的字体/图片资源
  • 所见即所得的GUI布局工具
  • 编译活跃度统计,及实时分析
  • 支持3D & Web
  • 支持Docker,一条命令启动。" Q7 ?  q/ _1 A9 w, ^- E1 b

  t) T+ b6 {  ]3 GuiLite移植
2.1 所需硬件
# R" n/ W2 T/ O2 k9 B7 d# t0 p$ ?: i, Q7 ]) i( @* z; Q

% n6 b) W: R! e. J  Y 14.png
9 O, R! F' e4 U+ S( J$ T5 u" t( v0 U2 ?
2 p" [3 J. x' `' c; P1 N
, f$ `7 Q# J5 [+ |
STM32F407开发板* h: r  g2 W: W" ~
9 e5 b/ a$ w* D

. f' x6 z5 \- i9 l1 G9 J' J6 K$ v 13.png ; I; L  e; N9 h0 p% W4 B
( C3 d  h2 P7 B8 [% m; R

' b7 x. n7 r- _" y% pOLED屏幕: d) J1 K6 x9 l! K% l/ w3 F

" B4 G4 N+ v$ r( N! @7 t

4 n' A& S2 d1 X1 L* `2.2 驱动准备
) j& n% s9 R4 h& @    这里我使用STM32CubeMX 对开发板进行外设配置,开启STM32的硬件IIC,这里我用CubeMX开启后如下:$ t* Q( F( k& f6 H8 @* W

+ V0 k6 U. A+ q0 Y% @5 j( R
( p# ~) I5 i" \3 h: n, F8 k9 @
12.png 2 _2 ^- a" d6 x5 ?
6 k$ O& j/ L0 L. m- r

. [: F5 \" C( O5 r! p) v, |    配置完成生成代码,同时将分配的堆空间增大:
* D  T! X+ h, P9 {! ^3 n& ^1 k, \2 k% u' p/ O
. M8 Y7 o. r" ^; j. l6 ]; H) Q
11.png
: ?3 }6 R8 [( \3 P1 e- M7 `
. a7 P3 D5 V0 v, P' w# `

6 R  }9 J' A1 ^7 w    代码生成后,我们复制正点原子的OLED驱动工程代码到Hardware硬件目录下,自己创建一个该目录。6 R0 d: U% ]  i3 M& R

8 E1 E, o9 a; j5 q- r+ T  Q

& o6 h: B2 h4 ^2 q* B# A; \' f 微信图片_20230302201518.png
  u8 C7 Y* o* k$ D# B
4 L+ S3 `- S% L  D/ x6 }

* U) X0 z4 Q- e! @    在MDK里面添加文件,然后我们进行修改,注释掉头文件里面关于端口的定义,同时添加三个类型宏定义。
' q2 e5 o/ V( y( T+ n( S1 X3 H1 r$ C/ O7 s- p

$ N  o0 ^& p+ p3 O 10.png   N: O( }# P, B) L) S+ |
9 y9 C8 F! R/ P

6 S0 j/ Q3 f; O  M; y    然后我们进入oled.c文件,将void OLED_WR_Byte(u8 dat,u8 cmd)和 void OLED_Init(void)函数分别替换为下面的内容:7 _$ c8 `; q" Z- M2 M
OLED_WR_Byte:
, m2 u# Y& A6 K: W, M+ Q4 }& N
  1. void OLED_WR_Byte(u8 dat,u8 cmd)) l: p) \4 k4 o9 ~# o  q7 W/ ?( ^/ o! u
  2. { 8 J, x  U+ e6 F+ o- q4 D
  3. if(cmd)
    6 g% E" @4 _3 Y1 f8 j: N1 |
  4.   HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);
    & G$ [  a. h* v* q
  5. else+ w8 \& m7 h8 Z' f
  6.   HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&dat,1,0x100);
    # R& x: X9 @5 ^- ^5 V! z; G. `) G* F
  7. }
复制代码
1 p* u5 n. [. {9 @( J
; f5 X& |* ?: j5 L3 \( R0 }& n
* G0 w8 q5 Q1 F, ]  D5 j3 b
OLED_Init:) d1 f4 c1 {2 h, b% r: D9 U
  1. //初始化SSD1306         
    0 h( s3 `; M. J1 \
  2. void OLED_Init(void)
    . m( g1 g0 F6 }
  3. {        
    # l9 q) q5 e% @/ q3 h) Q6 e
  4. OLED_WR_Byte(0xAE,OLED_CMD); //关闭显示
    " n+ ]' b# M7 |
  5. OLED_WR_Byte(0xD5,OLED_CMD); //设置时钟分频因子,震荡频率
    , G* \" H" g8 N0 f4 O0 K8 U
  6. OLED_WR_Byte(80,OLED_CMD);   //[3:0],分频因子;[7:4],震荡频率
    : V4 `- q; m) H' m0 R" q
  7. OLED_WR_Byte(0xA8,OLED_CMD); //设置驱动路数$ ?0 x' i' J) a3 w8 e
  8. OLED_WR_Byte(0X3F,OLED_CMD); //默认0X3F(1/64) 2 T- L/ ?! h( h: a
  9. OLED_WR_Byte(0xD3,OLED_CMD); //设置显示偏移& @" D* T1 X% E9 I) j/ u$ D
  10. OLED_WR_Byte(0X00,OLED_CMD); //默认为00 ^6 U& B: @1 _. H7 E8 A3 M2 S
  11. " L$ ~  `9 O) H
  12. OLED_WR_Byte(0x40,OLED_CMD); //设置显示开始行 [5:0],行数.
    , H9 K& F! k5 A
  13. ' R) o  a5 N9 d8 a
  14. OLED_WR_Byte(0x8D,OLED_CMD); //电荷泵设置, b) z4 G7 ]# L0 ^
  15. OLED_WR_Byte(0x14,OLED_CMD); //bit2,开启/关闭
    0 c0 Q) C1 G! Q9 U
  16. OLED_WR_Byte(0x20,OLED_CMD); //设置内存地址模式
    2 [6 p$ V! V* H% z0 M
  17. OLED_WR_Byte(0x02,OLED_CMD); //[1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10;3 ], X6 D3 [% |5 |1 O2 J  D6 _
  18. OLED_WR_Byte(0xA1,OLED_CMD); //段重定义设置,bit0:0,0->0;1,0->127;
    3 w+ {* Q8 Q- H+ M2 E
  19. OLED_WR_Byte(0xC0,OLED_CMD); //设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数6 J/ \* P6 m! b8 k, A9 F
  20. OLED_WR_Byte(0xDA,OLED_CMD); //设置COM硬件引脚配置
    $ d" I  I5 s8 |1 _& Q
  21. OLED_WR_Byte(0x12,OLED_CMD); //[5:4]配置$ h" a9 K% v9 F7 n2 z0 s
  22. ' T, |& w( G* U& n
  23. OLED_WR_Byte(0x81,OLED_CMD); //对比度设置, J" S- B/ W$ R7 R
  24. OLED_WR_Byte(0xEF,OLED_CMD); //1~255;默认0X7F (亮度设置,越大越亮)& R. M6 h$ d9 _/ _( x, F
  25. OLED_WR_Byte(0xD9,OLED_CMD); //设置预充电周期: ^& m5 N8 J6 }# }/ o- s, _4 J
  26. OLED_WR_Byte(0xf1,OLED_CMD); //[3:0],PHASE 1;[7:4],PHASE 2;9 H% D3 }/ w0 K  p! n
  27. OLED_WR_Byte(0xDB,OLED_CMD); //设置VCOMH 电压倍率
    ( e3 T$ k& r% _) n2 e$ E& d
  28. OLED_WR_Byte(0x30,OLED_CMD); //[6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc;
    ! g0 H0 j+ u  x8 S

  29. / \6 v! H  p7 w) B) O; H8 m0 J
  30. OLED_WR_Byte(0xA4,OLED_CMD); //全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏)
    4 m" o: c/ N  a7 J) M( ^
  31. OLED_WR_Byte(0xA6,OLED_CMD); //设置显示方式;bit0:1,反相显示;0,正常显示              . V( \% e$ g# B8 v
  32. OLED_WR_Byte(0xAF,OLED_CMD); //开启显示  % U8 S2 P- ^9 y( [$ u
  33. OLED_Clear();
    ; D6 Z# ^  L+ w  @; o( l
  34. }  
复制代码

! J. ~/ V, f  z( H9 C( d4 ~3 A# f

9 H- ]) D# i  P* o# b然后在main.c文件如下位置添加oled测试代码,记得添加头文件和头文件路径。

" e# ^* |- B# A8 b6 q, E
7 A, i* s: S5 B, P8 S  w  }# E

0 E( W; r: j; K7 `) d' _# F 9.png
8 R$ L4 S- Y% D+ |! I! @9 t" I  u, _
; H+ s0 c' X2 N+ V
. v! p$ _7 |  o% u+ `6 c' U
    下载程序,观看现象:9 |$ U) X' }! {2 ~9 U8 w# j

, `" A2 v& c8 c' d5 a
9 m1 p# C& G9 l& k7 Q9 ]
8.png
, N* G) U# ^2 J# ?0 D; x' c
7 v# H5 e4 I+ r8 g' O
% B0 ^( n+ g# Q  w
    此 OLED 驱动的准备已经完成,下一步就是移植 GuiLite。
. J/ t6 J5 H$ D& t4 v! M, x6 G# V  o  d* N6 i% H' f- ?6 X) C& {( q
3 T% ^) I) P9 H
2.3 例程移植$ z/ a3 q  {4 Z& v% F  d
    首先,我们上GuiLite的例程展示官网:GuiLiteDemo,选择Hello例程,将其中的 UI_Code文件夹复制到 Hardware 下:
8 f- x0 g/ z4 q' y% T" r
4 [; h2 x% K4 x4 g1 x. P

0 \2 [* m# N! T7 y! b; \8 ^ 7.png ( s+ V8 Q9 j  v0 O! S: I

( H8 F5 p( B* a4 R- \

4 H# g: G# Q2 m4 `: j. Y    在 MDK 工程里面导入UICode下的GuiLite.h和UIcode.cpp文件。
9 g9 t  e4 _7 }6 Q6 T' d
0 F8 j; y$ C% I* {) x( W2 Q4 W
# U, o+ z( P9 T1 O2 d
6.png
# M# q: O3 h6 h- o& y. b
$ R+ y4 S$ r; C; T0 e! Y) B

# d$ U0 F( i/ m) k5 |5 h$ {    我们在 main.c 文件开头添加 GuiLite 接口代码,接口代码如下:
% W# _+ f! T- ]0 ~1 {
  1. //画点函数接口
    6 [) W+ f7 _' C1 W4 V# F
  2. void gfx_draw_pixel(int x, int y, unsigned int rgb): @+ h+ {; i4 q- e/ w/ S
  3. {
    : Y" t/ t  a8 a- K: H
  4.     OLED_DrawPoint(x,y,rgb);6 w9 d# W" F! Z# R' H+ k$ q. f
  5. }
    : }( Z/ M2 W) g( @
  6. //画面函数(未使用)/ L) `' x9 V, c+ ^! H  N  t, f% n
  7. void gfx_draw_fill(int x, int y,int w, int q, unsigned int rgb)  x3 r" S4 z( i7 E! H# U. H5 ?
  8. { ! `: T' y; U. C: x
  9. }2 c" Q! w8 d) b$ h8 z
  10. //创建一个函数指针结构体& U- r$ V% j$ n; U( T  i* R
  11. struct EXTERNAL_GFX_OP
    ! n7 v$ D: m' `  B9 M
  12. {9 z% H- O7 f9 [) G$ X: y
  13. void (*draw_pixel)(int x, int y, unsigned int rgb);" p1 h: f7 n" J+ e. k; z
  14. void (*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb);
    : Q% ^/ K$ @2 i0 ]. o+ ~8 w0 r  P
  15. } my_gfx_op;
    % H! T: V( O! N3 F2 U
  16. extern void startHelloCircle(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op);# B. |/ U) |+ ]8 f

  17. , L& p# V, [( i& b6 w& w
  18. //设定延时函数接口
    ) u0 H, j/ e. B5 T
  19. void delay_ms(int milli_seconds)
    % d4 l2 N$ M2 t. g6 s
  20. {
    . d( J0 T1 q  n* m3 K( _: p
  21. HAL_Delay(milli_seconds);
    + `) E) \# D  h, c4 G4 @/ x8 C
  22. }
复制代码

6 P) P& U6 H# P7 {& W5 n: ^
& Z2 a) V. j$ p% b; e5 y: S. ]
3 D  b; w& q* x% ?) z7 `+ S
之后在main函数中添加如下代码:: j& n5 T# k3 n* d( `7 L$ Q
  1. //传递函数指针
    . w  v- ^: c8 d7 Q0 X
  2. my_gfx_op.draw_pixel = gfx_draw_pixel;. T2 L/ V2 i( I! k. M2 c+ G0 r
  3. my_gfx_op.fill_rect = NULL;//gfx_fill_rect;4 z; c: N( J. x* D( J
  4. //启动画圆
    * f! @0 C+ E$ U: ]: r3 T
  5. startHelloCircle(NULL, 128, 64, 1, &my_gfx_op);
复制代码

- E/ _1 n3 ~! g1 r/ }1 Z2 f

9 [, X: z" {1 O4 H- D) p; W5 s2 a; M 然后我们修改UIcode.cpp文件中的代码,添加OLED头文件,以及在UI执行函数界面处添加OLED刷新函数。

8 U2 a! L  O( f& P" m" a2 n
! o  v; K2 Y3 B( I- p- W9 A
2 E3 u" U- }1 K. `% c/ z  S* Z7 v
5.png ( ?' M- b3 K! n  E/ H9 W

0 F5 g5 f$ X$ i( z2 g
4 r# H" K0 A- `" J' m# o) q, i5 z
    之后在UIcode的第8行修改3D圆的参数,因为OLED大小128x64 ,所以我的配置如下:0 L! c1 k& P5 q7 q4 k
7 {! l# i9 E* `6 J

# @# j3 t% s, f8 r" O" Y# x4 h# \ 4.png
7 K! M# G8 W# q6 b. N: w
: n) e9 X6 B; W% w/ f

+ W- P5 P8 b4 p, d& u1 Y; M    配置完成后,我们关闭Use MicroLIB选项,编译代码:" Y/ u: K# m4 \
$ T* t3 m: a+ G

2 c* f/ K3 K) z5 Q* [2 Q" W 3.png 9 F( V& w" `- l: O# v/ b
( V& P: X0 D: H) L4 u2 W% u3 q

. x8 N: C8 x" |" D+ _' L) n    编译成功,下载代码。# ?$ }  \& R7 v' B- y: B* k
/ v& O' k( y# K" E2 }1 k2 g

( S1 I$ k% J/ |5 D# e3 Y# v) a 2.png % w# E' v# L2 B+ d. N

- I/ A$ V* x) h
3 v  ?, t! j% v, R5 O' J/ \( e
    下载完成后程序复位,可以在OLED上看到Demo的示例动画。
% T7 T& G9 ?4 U" _& o0 F. H5 l0 s% M

9 l4 d' W% e  r; X, ~2 A# R/ y 1.png
# q9 ~5 [) d$ g2 T- m6 M" n
7 y& p7 D# Z. V8 \8 A+ h转载自:[url=]芯片之家[/url]7 K1 `; [8 B5 ]- Y$ B: L+ X
" r# M9 d. R8 c) T2 T
. A6 C$ K2 p5 u" w7 O
收藏 评论0 发布时间:2023-3-4 20:00

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版