' _; M% o ]/ W+ x4 G. L
ST公司推出的用于图形界面开发的 TouchGFX Designer已经升级到4.20了。这两天我利用手头的STM32F429Discovery板对Touchgfx提供的部分控件功能做了些测试,把这个过程中遇到的一些问题做些整理,以备忘并顺便分享。
: x6 X* u/ K; W/ p6 f我这次主要测试了TextArea,界面按键响应、动态图形【dynamic graph】、模拟时钟【Analog Clock】、进度条显示以及软件上添加虚拟函数的实现。涉及的界面有下面几个:【仅为测试,界面美丑略过】
2 q4 \6 b( r1 ^ 4 L7 S* b$ a% k( |" p
第一个要注意的地方。 我使用的IDE是STM32CubeIDE。当我在相应hpp头文件里添加虚拟函数声明时,需要在IDE环境里专门对该头文件做个save操作,不然在cpp函数里写好相应函数后编译时总提示没有做函数声明。 举个例子说下,比方我要在Screen1View.cpp写一个IncDuty()函数。 # }: |/ _3 x1 v" l- A
, @ s9 H r% x0 ?! ^0 |
我们需在其对应的头文件里加上虚拟函数的声明。在头文件里添加了该虚拟函数声明后,需要手动对该文件做个SAVE操作【File菜单下选择Save】,否则老是编译出错,提示函数无声明,即像下面提示: 7 B/ o# G% A" k) T9 M% U
但别的cpp文件修改后倒不用单独做save操作,直接编译即可。这个地方因为要操作的文件较多,我多次忘记,直到编译提醒才知道。【不知该问题是否跟IDE有关?我没测试别的IDE。反正提醒下吧。】
; N& B4 b& O3 {' R& S
第2个要注意的地方,我这里通过TouchGFX designer的文本区域控件【textarea】显示STM32的某通道ADC转换值,用到了浮点。
: A% v6 R( N$ R6 f
" s; u! Q# X! n+ ]刚开始我用的是这个函数: Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%f",AdcResult);
, q8 P w* H3 d+ J M结果总是出不来,但当我将AdcResult改为整型变量,通过%d可以显示正确结果。先怀疑过IDE方面浮点功能相关配置,经检查没问题。后来到TouchGFX在线服务站点搜索snprintf才有新的发现,如下图所示: # U: K. L+ L" f6 m
. [( y; R; ~8 _7 L% O8 ~( y
看来我的函数用错了,使用浮点有另外一个输出函数,即: Unicode::snprintfFloat(textArea1Buffer, TEXTAREA1_SIZE, "%2.4f", AdcResult);
1 r5 b4 R+ L3 f2 U# I" c3 J. J第3个要注意的地方,也是跟上面textarea输出显示有关的问题。
3 p* l) }" a; G& q9 Z8 u8 L 5 G7 C: E0 f$ D& y6 s, p, o
在它的属性那里有个Auto-size的选项,勾选与不勾选的实现代码是不一样的。一般为了简单点,可以不做勾选,自己手动拉个合适大小的框来显示字符及数据。比方还是以上面显示ADC输出电压值为例,其实现代码如下: - void Screen2View:: DispAdcValue()
+ S. Z$ y' |) E - C1 e0 U! e ?) B
- {
% ]- a& ` G6 R$ U
+ |/ H1 D u( Q- Unicode::snprintfFloat(textArea1Buffer,TEXTAREA1_SIZE,"%2.4f", AdcResult);
+ V9 j/ X9 d4 \0 r - 6 I% |& P- D( [5 J/ U
- //textArea1.resizeToCurrentText();
* i* e M) W8 {, O - ! n& v% r% j8 ~" L2 ~
- //memset(textArea1Buffer,'\0',strlen(....) );- {& d# W& K/ U+ C6 f
- , G5 ^* J# a' q8 y! U- D
- textArea1.invalidate();; C W* [$ }1 f' g. }
4 k3 `4 e! `) Z& n7 m. l- }
复制代码
5 m% {8 `9 e; N6 T# g& q7 X* N1 y如果说你希望勾选,你的代码就将上面的屏蔽语句加上即可,有兴趣可以自行试试。 8 A2 W0 f" _; J& w3 V" ?. O8 U, l& ~, n# A
再就是那个动态图形显示那个地方,显示的点数及修改样点值的频率都是可以调整的。我这里是让它动态显示一路PWM输出的方波,为了实现它,我在这个地方做了些来回调试才实现比较好的效果。
8 ]6 ~7 R( @) L5 a/ @+ A6 ]另外,我在组织模拟时钟代码时遇到的一个小问题。我用到Model::Tick里的modelListener功能。
: m8 @ v) h" W1 [7 `
有个地方本来应该是view.UpdateClock(hours,minutes,seconds);我看库里面绝大部分单词的首字母都是大写的,我就惯性地将view的首字母写成大写V了,编译没有直接提示出错,但就是结果出不来。这里各种API函数很多,初次使用者对他们都较陌生,这种比较隐蔽的问题难免会碰上。
% Q7 j- V% E4 @- L ( C3 ^6 `6 ?- P/ D! {% E" _
我顺便把测试中用到的几个跟GUI这边有关的函数实现代码也贴过来,供有需要的人参考。 - modelListener->UpdateClock(sTime.Hours,sTime.Minutes,sTime.Seconds);# n* ?2 K4 s2 |* R& s5 D6 w
- 9 G1 r* A& l( M
- ( Q+ Z" g/ D3 g# t' r
; `. B; }5 z; |9 m( q4 }3 }! H- analogClock1.setTime24Hour(sTime1.Hours,sTime1.Minutes, sTime1.Seconds);
7 j- ]" x6 p: U1 p& A: `
. s5 L" v" `7 x0 H" n' V" D# v9 m
* r! J. R8 G9 j9 m5 d1 `0 Y
* ^( ]5 M3 y- v8 w: Z8 F$ s- void Screen2View:: DispAdcValue()//基于textarea控件固定宽度显示数据
$ U& p9 U8 t; n7 p
( |6 b3 O1 t# }- {
) g3 v2 q6 N/ z- R" H0 A
- X" H) r. K$ }/ A, }& V- //Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "%d?u?s?", AdcResult);
- p" [9 t" {4 s+ j! E - ( s3 g! U: U, a4 P
- 4 r+ @8 C2 g$ p3 v( u4 h' z
( S2 s; d* ]: W% f% i: j, r. n G0 |! A- Unicode::snprintfFloat(textArea1Buffer, TEXTAREA1_SIZE, "%2.4f", AdcResult);
" Y1 J- j9 h6 b5 h. P
; x) ~3 t) w* ?- //textArea1.resizeToCurrentText();5 K: A4 X4 B) c( @3 b" e7 Z
. u8 Z& `7 ] m$ g* J& d- //memset(textArea1Buffer,'\0',….. );( q" w' r5 T; T* ~ T
- 0 p0 s! I; W! d
- ) o/ A Y: R! L
& C% O0 V2 |/ m) J, u, ^- textArea1.invalidate();3 w, q: B4 j7 O' h
- - A' S* U+ t3 U1 P
- }7 R" S7 C0 Y) j8 F3 _! Y
- & L. L3 Q+ e! S% m1 v8 h
- 4 n& O4 F0 A9 \) ^' m/ F+ P1 {% [
- ( X |0 w; \1 `/ n" n. z
- void Screen3View::UpdateCnt() //For progress Bar6 W+ b( _. t. R( b; A
, ?6 d! }+ S, k3 N* ^6 e. Y. N8 ]- {
4 k7 g! e/ H$ i! }- }2 B. n _ - 4 i4 i8 I$ f! M* C
- if (UpdateCNT > 2000) {UpdateCNT = 0;}
5 O8 F# `# S( o3 U) S! X+ a - * e; i, n/ S6 N1 w& {2 q! H4 A
- //UpdateCNT comes from Timer Interrupt. H% @0 r0 b3 e+ i
- 7 X7 \$ Q5 d, E, p0 p, w
- textProgress1.setValue(UpdateCNT);
4 Y- \9 O' \! v5 {- G3 [! F: T, \
4 m( H' `( O# K! \# @- circleProgress1.setValue(UpdateCNT);
, ` { I5 T7 ^1 K - 6 Z; I( _( K* V0 e' r
- imageProgress1.setValue(UpdateCNT);7 K7 b$ o* }: X
8 H n4 X1 V# L. W( A- }
! }7 F# @3 f3 T0 d - 1 p2 V9 ]% o) ^9 @( t
- 7 D S+ ?% s1 } u
- 1 X! i% \& @$ N5 J) m
- void Screen1View::IncDuty() //For TIM3-CH18 t3 S! x7 G% ~
' C1 o! P/ ~- g, d0 R- {3 M: t* {% f# D
- , S I" v2 j6 P/ w) t
- CCRValue+=100;4 M2 ?# I. m0 J2 n# U) S% \
0 W% _! h0 j- I9 k' u- if (CCRValue > 50000)
$ O' |; v+ ?9 ]; Y1 N( a
7 I, A' q5 }+ b) {6 p- {. a) V' P# G% f
) Y$ H) X4 w# v# K; M r0 T- TIM3->CCR1 = 50000;
4 C: c5 F7 f2 C3 Y$ _' \ - - [; ]5 m+ |: ?% }# c
- }0 d- K% r0 x" M2 z" e
- & o. |1 \; V' ~, x2 X" Z
- else) |$ e6 D% U( i+ a7 U' M* g
- & Y% e: ~2 S$ a5 @- _
- {% |' P, F1 [2 Y5 X* |( g
9 S1 }& T# \: [. a- TIM3->CCR1 = CCRValue;
! _ i1 Y8 q! ?, B' x, a - + Y7 N5 \0 Q5 ~$ Q0 Y6 Z/ V) q0 h+ U
- }
- W6 v* {. ?6 e4 x8 L
& M m% [; y5 F4 ^- }- A5 _3 W: J& t
* o7 N" O3 H! c- & p2 `8 b% G( @3 t7 k# a
- , ^4 w% o/ |! L4 S
- void Screen1View::DecDuty()//For TIM3-CH1( j" r' U `& L# Q
0 @( i9 I# [9 O- `' F; u- {
$ y, ^" g$ r/ M+ R0 s - * N% v3 k, l+ Y
- CCRValue-=100;% @& s2 G0 t8 w4 ?5 J' V! a
x& P$ W5 Y. X( C1 ^& A, @- if (CCRValue <0000)0 U* v9 u" L8 X( a- j. h
# j1 V' _* W' Q% l# ]" F1 y- {
5 ? C$ B# x; o) ^% C
. ~) ` `4 |* C& C2 f! s- CCRValue = 0 ;- n; r+ \( P& q& I
- 4 K) c2 G5 {- E8 f/ y, r Z
- TIM3->CCR1 = 000;' b* m1 D" ^ w* {4 F2 [2 Z
- $ n/ V: K ?0 `) }8 q T5 `" F4 o
- }3 ^* I! O+ y0 q3 u2 u/ l
0 D g4 T4 J3 H, q% K) e- else. j. w! b8 d9 f, K( c
- : G# D. M, q- x# D7 i
- {
' [% h3 F( G- S - & G K4 Z7 ?1 A0 O
- TIM3->CCR1 = CCRValue;
8 t7 D+ u9 d* U8 `& Q
3 t& `4 s1 W/ Z) q/ m1 c- }
! L3 H2 e2 e0 g @ |- ?; T - # \ V( C( L" ?
- }: A7 t) v! P9 D, P
$ x4 q) Q! w7 R2 |
7 W% X! ~; K: R4 ?0 k: `- + {0 ?. _( U: K+ }' [, Y
- void Screen1View:: ModifyGraph() //for Dynamic grahph
) L; x; a. S8 t; w, F
& p8 t, v% g I$ q+ d- {6 E/ _0 K) p( |% |0 H, Y+ l
- $ B) N h' p/ w
- uint16_t temp;
0 r" |8 e$ K' e - " C9 _) C r b8 E: a# D# L# ]5 o d
- temp = GPIOB->IDR & 0x0010;" b8 w, h, R' M- T/ U6 h
- - ?, D2 I( O, Z$ f5 m5 l
- if (temp==0)
, r3 I* B" y! R$ M - / R! X6 I) R; k! [3 f7 V
- {1 ^( Q/ F. Q( v7 I3 K5 m' s
# |4 {# ?5 E9 F& O- dynamicGraph1.addDataPoint(0);, t4 k' J2 J5 b' [
- 6 K+ {4 O7 d3 A& i% i' G
- // dynamicGraph1.invalidate();
# \( b P; ?) c
0 I, Z+ x- w C( q5 ^7 A' K& Q- }
2 J6 C% ]1 C/ I* g7 u; O
8 y" l6 f, C# }/ n- else# b! K8 ` J9 L$ K
6 d @% ?# e5 @3 {% Q- {! ]9 F- f% F2 F; \8 F6 Q
- 5 b- ~9 P: ]$ P' ]3 @
- dynamicGraph1.addDataPoint(99);2 e- R# v2 B) {
- ; g% y4 i; Z6 M. F3 L; z' D- D% E' }
- // dynamicGraph1.invalidate();& ]3 x7 n0 ^1 \( |0 R
2 p- ^$ ]* x. ?, w- t S5 ]! U- }
% h. X% I$ b- J7 t: J - % Q/ l$ |6 \5 X" X. W. V9 [$ Y5 F
- }: n) m: K% U* q
- ! L4 a$ B5 c! B: H
复制代码
) N' ?% E. a7 `/ T& {$ k9 L, D
3 _( C8 ?# C; [4 g0 m0 c9 w9 s. b$ G T最后补充下,当我加入第4个页面屏的内容时,电脑上模拟下还行,基于STM32F429开发板已经没法正常稳定运行了,毕竟资源有限。当然,不同的人设计4个页面所涉及的内容及任务数可能大相径庭,可能的结果这里不好说绝对。不过,我的测试过程中运行上文中提到的前3个页面内容及功能是没有问题的,下方放了个效果视频供查看。
* ~, y8 P- j% i' j
; B* v" p& u& o- M9 F i9 Z6 s
|