本帖最后由 baiyongbin2009 于 2015-2-12 14:38 编辑
' N3 U& B. n+ b; R, N4 C+ U' l' }9 {* t$ s0 Q
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接) q$ |& L w' l, U) V$ n% {9 @
第29章 STemWin多任务(uCOS-III) P) s+ ^8 R( O. t
本期教程主要是在开发板实现上期教程中所说的三种系统。这里大家重点学习一下官方推荐的设计框架即可,如果有不懂的函数会在后面跟大家讲。 29. 1 单任务系统(超级循环) 29. 2 多任务系统:一个任务调用emWin 29. 3 多任务系统:多个任务调用emWin 29. 4 总结 29.1 单任务系统(超级循环)工程代码的结构如下: 关于移植的知识已经在前面的第二章详细讲解了,这里重点介绍时间框架和接口函数。 29.1.1 内核接口 内核接口文件GUI_X.C内容如下: - ----------------------------------------------------------------------9 f, t5 o/ f7 T( e
- File : GUI_X.C: J0 T# l- J5 t4 ?% \. o
- Purpose : Config / System dependent externals for GUI
$ }" _9 A/ k6 i2 _ - ---------------------------END-OF-HEADER------------------------------
: R& i6 z9 g9 a2 @' u - */
+ P9 l" z8 D' z0 L. f - : z/ j+ Q3 c# f s
- #include "GUI.h" @1 a& o# y7 Y7 M7 F( O8 R% h7 o1 q
- #include "stm32f4xx.h"+ q0 {: w! S. \# ]8 }9 i$ r
- " F+ J1 N* h) M8 B( T h2 z- H9 |5 g
-
8 K. {, X2 Z( Z; g. Z/ a - % U7 O% K0 V: X1 e! i6 M
- /*********************************************************************
4 S. `1 v4 [; `& g+ S% X - *
, l2 c3 g+ F% H- b0 ?8 @1 @3 P - * Timing:4 Y7 w4 C( h% `+ z
- * GUI_X_GetTime() p* [" h5 D9 ^- o
- * GUI_X_Delay(int)' a& c5 M! M5 p
-
8 `* z6 P, n5 h - Some timing dependent routines require a GetTime* K. O6 D9 K1 Z. A
- and delay function. Default time unit (tick), normally is2 ?6 ]9 v" g+ F
- 1 ms.6 h ~0 L9 k! }, L' B0 H& ?
- */9 i6 p7 P: L. F* ~/ Q& \
- extern __IO int32_t g_iRunTime;(1)! H7 C6 V" F5 v, N9 S" u' l
- int GUI_X_GetTime(void)(2)- x1 E, Z' Q( G7 x: J3 K
- {
4 I1 J2 ~( ]3 T- d9 O- ^. @ - 0 ]+ J! S) _* \/ E
- return g_iRunTime;
: q z/ X8 O: P) ` - }
+ D8 q7 S+ m7 | \6 m9 F* f - 1 r0 e2 H2 V9 y C
- void GUI_X_Delay(int ms)(3)
- {6 M9 ^, f3 |9 N- Q! x4 A; ~ - {
! S7 i3 W2 a" k0 x8 Z" H- v7 y* g$ Q - int tEnd = g_iRunTime + ms;7 r) Q9 ]6 Y2 X* v" I; k6 i8 k
- while ((tEnd - g_iRunTime) > 0);
: f! i# {5 `4 J9 ? - }
$ {' d! u5 H1 A: ?1 t! a1 ~ -
# w! ]" [ V3 Q }, d4 u - /*********************************************************************6 N$ S; G6 J0 l. M; S1 T
- ** C1 ]3 ]4 o" i3 ]! G0 A; N
- * GUI_X_Init()
' G" A- v1 R9 r4 c3 g - *
2 J+ L! {% @% m- Y! f - * Note:
0 P s( h0 t2 K: w% P' o s8 C - * GUI_X_Init() is called from GUI_Init is a possibility to init+ ^8 i* S& v8 x- B" L& f+ p9 h
- * some hardware which needs to be up and running before the GUI.
$ j! @* @1 |0 [/ V! t% T - * If not required, leave this routine blank.+ q; f) L1 {1 i! H# [
- */
% F, A# b. e1 v- V - 6 B! C& E# I1 E/ _2 I
- void GUI_X_Init(void) {}
6 g. |: k) Q7 E/ E4 R$ p7 z -
# I! O7 G# A1 I' T6 \4 i8 Q) O -
; f6 D5 _5 G8 V7 @, H5 H/ u - /*********************************************************************
8 Z$ E# _# A2 { i j4 T R - *
* M& w9 h& _+ B - * GUI_X_ExecIdle
* L( d6 D6 a& j* B& [- v" X& _ - *
% r' r6 p& o G2 i: g6 o& C: X - * Note:
# i8 n" P7 d+ E1 F2 i - * Called if WM is in idle state
0 n9 R7 r) a4 Q E. ~9 F - */( M% l" E! c; f
-
+ f' P4 y3 ^) |3 l: }2 Z* R+ S - void GUI_X_ExecIdle(void) {}+ F* I0 [; p( D9 q1 x P
-
# n$ @ A: k9 [. I - /*********************************************************************
( L p& C$ T% o! ?9 O& ? - *5 J6 h* }% C" t) `- L" A% E
- * Logging: OS dependent4 g1 n# L" [2 ~ R- G- \
- ! r" a% l; j! v5 c7 C
- Note:
. _4 P+ z' f% _; [/ P - Logging is used in higher debug levels only. The typical target& r. \. C5 G. K( E0 @
- build does not use logging and does therefor not require any of
8 N# ^, D& X4 J/ I; ? - the logging routines below. For a release build without logging
: F5 S' y+ C/ p) T - the routines below may be eliminated to save some space.
4 e) g- m3 e8 |8 N5 O - (If the linker is not function aware and eliminates unreferenced
8 \6 ?" ?$ T/ r6 Y$ n) F8 b - functions automatically)# J( {; P+ T1 E0 j6 G% O" b
-
' k( w B( V$ q* g - */
) i0 ^4 Z( E: z" H8 }4 c -
3 e+ K% u z0 j6 g) n3 G6 t5 T - void GUI_X_Log (const char *s) { GUI_USE_PARA(s); }
6 a8 c/ A1 i6 |8 b' L4 ?+ U - void GUI_X_Warn (const char *s) { GUI_USE_PARA(s); }& K7 a* [6 B4 M' _6 U
- void GUI_X_ErrorOut(const char *s) { GUI_USE_PARA(s); }
复制代码1. 时间基准全局变量,这个变量在bsp_timer.c文件里面进行了定义,由嘀嗒定时器中断进行调用,每1ms调用一次。 -
6 `% A5 m8 I, r5 f5 r - /*
9 M- G! ]/ ~* ^& R9 w - 全局运行时间,单位1ms
6 D# J8 x$ M' N - 最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题9 ?8 a# g/ W0 `' {+ A
- */5 I2 e& u/ O% Y8 k5 V
- __IO int32_t g_iRunTime = 0;+ M8 s' T9 _$ P% f6 V
- /*4 H G: Y1 p) }& r) a% F8 t
- *********************************************************************************************************, d1 B0 `9 e# x4 m
- * 函 数 名: SysTick_ISR
: m8 p/ O+ w$ ^( B: y' `0 s0 [, y - * 功能说明: SysTick中断服务程序,每隔1ms进入1次: @9 w0 n0 {' F4 C- ~5 b
- * 形 参: 无
1 f+ N- }: Y' X% t+ n9 w( z5 ^' K - * 返 回 值: 无
* x7 l. W+ {2 p- _ - *********************************************************************************************************
' @! h0 K$ H7 s8 j - */
& w J& B7 O$ K/ o5 S: g$ i - void SysTick_ISR(void)
) O3 x. r: H- v2 ?/ K - {
% a- X/ E; M8 R2 O4 `, }9 ~ - static uint8_t s_count = 0;
/ S4 j3 t5 Y) r# P0 \3 e - uint8_t i;
7 ~0 Q7 ?; x% q - 9 ~+ O( s0 p; K3 r s
- /* 每隔1ms进来1次 (仅用于 bsp_DelayMS) */
( x# s8 I/ r$ K! F0 y - if (s_uiDelayCount > 0)- E! H3 _0 j# F
- {# _; }6 {( G# w, v5 A
- if (--s_uiDelayCount == 0)2 D j/ z% [$ j% w
- {
, f f' }2 t& c9 O- k" z - s_ucTimeOutFlag = 1;! `9 Q7 C: y$ Y* g
- }5 w% W$ J! ~& w8 j- J$ D
- }
1 a1 a1 J7 i3 w3 {' {- P -
3 c0 t: ?0 U5 ^" |; z8 ~ - /* 每隔1ms,对软件定时器的计数器进行减一操作 */
% `2 g1 {: `3 G8 [: n - for (i = 0; i < TMR_COUNT; i++)" a7 ?, B( @ V2 d1 t- ~! _
- {
; O! f: B4 S* Q - bsp_SoftTimerDec(&s_tTmr[i]);- r" S' @, {( H3 X
- }2 P! Y8 _. Z6 C
- # n1 t. v: U3 H, [. p# e) h$ k! u
- /* 全局运行时间每1ms增1 */
. \2 h' i# E% N' i( N& M/ f - g_iRunTime++;
8 [/ Y) s( _9 X+ ?9 S: r - if (g_iRunTime == 0x7FFFFFFF) /* 这个变量是 int32_t 类型,最大数为 0x7FFFFFFF */6 X' r3 H5 e t1 o
- {
3 H2 k4 T' C9 _! M- M - g_iRunTime = 0;
' a, }2 J/ @! t' }5 B0 c - }
0 z: W' f# b9 o. f3 j -
( N, Y5 V) L" l9 o - bsp_RunPer1ms(); /* 每隔1ms调用一次此函数,此函数在 bsp.c */ r( v/ x7 ]2 c/ z- i) B5 u
-
$ q' v! U( a3 _+ p' e - if (++s_count >= 10)! T7 N, h1 M p- Q9 J4 M
- {$ W( F8 i2 P7 ~( f8 M2 e
- s_count = 0;# g E, y# t, ^" w. ^$ f
-
- o( j' I: [0 n) Y - bsp_RunPer10ms(); /* 每隔10ms调用一次此函数,此函数在 bsp.c */
5 ^7 u( ^) S6 y: _& y1 L - }6 R6 o. s- N4 T9 L
- }
复制代码2. 供STemWin调用的接口函数,用于获取系统时钟基准。 3. 供STemWin调用的接口函数,用于延迟时间设置。 4. 主要设置上面两个函数即可,其余函数根据需要进行配置。 29.1.2 触摸接口 触摸部分由嘀嗒定时器中周期性的调用: - /*3 y3 J( O/ x, Y5 g
- *********************************************************************************************************
- T5 F" z+ E1 X R2 z" y' }- E - * 函 数 名: bsp_RunPer10ms" d2 _- k$ a* U' @
- * 功能说明: 该函数每隔10ms被调用1次。在bsp_timer.c的定时中断调用。主要用于硬件事件检测
7 u5 [: V# q# b! L( H% v - * 形 参:无/ B! r5 ^) `/ Y! J
- * 返 回 值: 无
& t3 e5 F0 a% b% ~) t' s - *********************************************************************************************************3 x' m/ r$ r* c5 ^$ ?: \3 [
- */
; Y- d; ]4 K) q( a: ^% Q) a: T - extern __IO uint8_t s_ucRA8875BusyNow;
" ?/ \2 F! p& D - void bsp_RunPer10ms(void)
! ?% N1 [; i6 @% h, ]& d+ P - {8 G) x6 M& Z, ~ Z0 C
- /* RA8875 触摸*/
$ E! K& l( ~9 E/ m* Y' \0 Z - if (g_ChipID == IC_8875)( _7 S* D& ^' [, D
- {
0 k. Q( R3 f$ P - /* 资源共享标志 */
) W6 q/ D* s- ^ - if(s_ucRA8875BusyNow == 0)7 y" v1 d) @ C8 Y! T# W/ g
- {2 S. Y# S! E' B( e0 {; d+ E' \
- GUI_TOUCH_Exec();) ]6 S: K: C1 r7 z! P
- }
' Q1 o. J" t; n" x - }
, ]& [* X4 x$ U, v - /* XPT2046 */
* ^+ ^, s( S! D. c6 I9 l% r p1 Y- t - else
7 @1 u# I) g$ }; P# s/ \ - {. ]/ A$ Y4 H& M8 Q5 g- m
- GUI_TOUCH_Exec();
+ g# [$ I, H3 r9 j% M$ q; @8 N - }
% g6 r6 p) \1 X- q$ z4 o - }
复制代码 29.1.3 主程序在文件main.c - /*' E9 c+ _) I& X. O8 Y4 Y
- *********************************************************************************************************, B; z' T- U* F; w2 A" b
- * 函 数 名: main
2 q0 v$ J. E: z' r2 s - * 功能说明: c程序入口
7 g2 o: B. t6 J2 k - * 形 参:无
9 K; P* D4 ]0 L+ e: N - * 返 回 值: 错误代码(无需处理)
6 T5 M0 o9 {9 u8 U% h& A6 m; \ - *********************************************************************************************************
9 x* V" i+ V* |6 @- H - */
6 R) C$ \9 I. ?- l8 W- { - int main(void): q1 g% D# A/ k5 @, m
- {9 V0 [+ O( ?& q& g; @5 [4 {
- bsp_Init(); /* 为了是main函数看起来更简洁些,我们将硬件初始化的代码封装到这个函数 */$ [$ p3 Y; O# j" I' \2 d
- 5 [' l8 V; u+ l0 S" \+ n
- MainTask();
8 ~. E; ^8 o, ~+ M2 V) H - }
复制代码在文件MainTask.c - /*8 r) u2 ~7 J* I8 r3 Y
- *********************************************************************************************************
2 {3 h* x- [5 O \2 k u - * 函 数 名: main' V2 I' h% P% ~0 S- \
- * 功能说明: c程序入口
6 V( U; Z J6 G. s( F( X; x - * 形 参:无1 F) t# k) B& v, i7 H3 v3 g( [
- * 返 回 值: 错误代码(无需处理)) y+ v& |6 i6 z1 f9 I
- *********************************************************************************************************- |4 i* X) J$ @ C' T/ z
- */( [9 e' Q' P4 b1 z3 ~0 p( S
- void MainTask(void)
* p, O% U2 @, {$ ]7 H9 \ - {& K! G$ Q% t& x6 V7 ~
- int xPos;8 F1 h( A8 S5 _8 R' E
- int yPos;- _8 K! m9 X) s% K0 j; |; M
- int xSize;
* ^* ?( T# @' p! J0 c' p; _, q - int i;
, r* O% y% I1 r2 R- E - * ?; b. h, h' t
- i = 0;
4 X8 [$ r! H) [ - /* 初始化 */
0 h' P2 ^: E# r# l6 H0 | - GUI_Init();
1 t+ D0 {9 p/ C1 R) I) E& F( } - /* 获取要显示的X,Y坐标 */3 g, K {$ L0 O& v6 f' {( q
- xPos = LCD_GetXSize() / 2;
- e% O g7 r3 j# d% J. v5 r C - yPos = LCD_GetYSize() / 3;
3 J' ~3 e- \% V! t. h% V9 F - /* 设置文本显示模式 */
4 i$ D* s) v, N; C - GUI_SetTextMode(GUI_TM_REV);# g* |/ U3 X; V& X
- /* 设置显示字体 */6 m$ x! `9 D/ q1 g j
- GUI_SetFont(GUI_FONT_20F_ASCII);# v; m7 M" e: D* N
- GUI_DispStringHCenterAt("Hello world!", xPos, yPos);* b. u3 J3 g1 P4 y. t
- /* 设置显示数字字体 */
2 `# N m5 d) w - GUI_SetFont(GUI_FONT_D24X32);
# I8 J) I1 W$ j* E - /* 获取显示0000,在字体GUI_FONT_D24X32下的显示情况 */$ b) V: v m" H% `: k" j
- xSize = GUI_GetStringDistX("0000");3 _, I, U8 H8 d9 H/ P
- /* 设置显示位置 */$ w$ L; ?; J; }! b# ^
- xPos -= xSize / 2;# u1 X9 ?; F# W5 g. I8 } |
- yPos += 24 + 10;
2 F( v C }" [; C0 a( J' a - while (1)
0 l% \4 i v0 i6 a( p6 Z - {
. l: K8 ?0 K( C: j Q - GUI_DispDecAt( i++, xPos, yPos, 4);
. _' d2 a3 O% V - if (i > 9999) c/ L& h7 r& t! p/ s
- {
/ H5 g8 m7 S! Q$ d' E - i = 0;
. F, X, C+ o) S' A - }
: _/ ]' v4 B2 u8 T - }3 l+ o5 M' O! W0 O6 ] i# }% A6 d
- }
复制代码功能比较简单,实现效果如下: 4 K' K d$ T8 Q( M4 c5 i2 ^
|