本帖最后由 baiyongbin2009 于 2015-2-12 14:38 编辑 ( n2 R1 f% t% P8 x* n. [; i
& A0 @* |; ~/ `7 d
特别说明:完整STemWin的1-60期教程和配套实例下载地址:链接
' F9 H: w) d$ B8 L) p; c3 |第29章 STemWin多任务(uCOS-III) $ S O7 R+ s3 t
本期教程主要是在开发板实现上期教程中所说的三种系统。这里大家重点学习一下官方推荐的设计框架即可,如果有不懂的函数会在后面跟大家讲。 29. 1 单任务系统(超级循环) 29. 2 多任务系统:一个任务调用emWin 29. 3 多任务系统:多个任务调用emWin 29. 4 总结 29.1 单任务系统(超级循环)工程代码的结构如下: 关于移植的知识已经在前面的第二章详细讲解了,这里重点介绍时间框架和接口函数。 29.1.1 内核接口 内核接口文件GUI_X.C内容如下: - ----------------------------------------------------------------------
9 ^7 V7 {3 p9 S0 w - File : GUI_X.C5 s' E' U- ~& U2 W, C, F
- Purpose : Config / System dependent externals for GUI* x; H# s4 z1 \$ ^; i. G, P
- ---------------------------END-OF-HEADER------------------------------
. _' L8 ?/ O1 n* }" a! ?! Y - */# Y1 a; t4 f( U+ [5 j3 G o' Q
-
$ _! ?: d% q- L$ @ - #include "GUI.h", F4 `! M; y% z1 Q: t" r
- #include "stm32f4xx.h"
9 a0 {; S) }7 c4 y - & n+ ?* T% z. @) W7 \
-
3 E, w$ c4 c! q y5 ? -
1 z' a- T5 h! Z, `3 G - /*********************************************************************, A1 |3 G4 t! ~- |7 A
- *
n& V7 T. g5 {, j% d - * Timing:# A4 y7 }+ R: N Z' A* p9 V' I& V
- * GUI_X_GetTime()1 {0 ~9 B0 L6 w% K3 d2 ^
- * GUI_X_Delay(int)5 F+ P. w+ g3 A- L! r4 D
-
3 n0 I3 \# @8 g0 C* O - Some timing dependent routines require a GetTime
* W, x2 ?5 o/ B' R - and delay function. Default time unit (tick), normally is
$ I4 m) z/ ~9 }" y8 @4 h1 h& k - 1 ms.! g! q8 i9 a) n, t, s, |
- */: e& m% L$ Z; x
- extern __IO int32_t g_iRunTime;(1)
# ^! D% a5 J; F/ r' B0 S* V3 C" D - int GUI_X_GetTime(void)(2), Z* \1 t/ ~$ O0 ]5 @
- {- v6 U8 C& H. u( q8 G) \" Y
- 7 y* l2 R/ G& b: t
- return g_iRunTime;
$ H9 `) `$ M7 Q0 j - }
0 O4 o2 }. Q3 B5 |7 \9 X' _, @ -
" {7 n, i3 X' {- _% y4 K# { - void GUI_X_Delay(int ms)(3)7 U/ ^, R( @) z+ ^2 O2 K4 q N
- {3 h. }, f4 k1 M! f& z
- int tEnd = g_iRunTime + ms;
- u) B) U! ]1 }1 \" A - while ((tEnd - g_iRunTime) > 0);
3 |1 x; p7 D8 D$ I8 | - }9 [; O8 V1 i8 n0 o ?! ^3 \' o
- " n1 T9 G: N# _9 ^& @
- /*********************************************************************
) l; G$ i' a0 ]& K9 w - *$ K% {& D. E4 ~. J( Z: k, n7 ^+ P; Z
- * GUI_X_Init()4 ]( y; f" `& r- f0 B
- *
5 T& d% M, F- s. c9 s - * Note:
3 ?' r" V. k3 n+ f, e5 k2 b - * GUI_X_Init() is called from GUI_Init is a possibility to init3 j) c' g! b5 D' m" [
- * some hardware which needs to be up and running before the GUI.
7 [- p( C' Z6 {- g- Z - * If not required, leave this routine blank.
$ F) |+ U7 B, G5 ^ - */* V% o. G# y8 ~& s% o
-
0 v7 j' W! s+ O$ ~- p3 I9 R" D - void GUI_X_Init(void) {}; ?9 ~& {- g% b: F
-
# [9 q+ y: {! w: R7 B6 g - 8 Q& v* R1 K& c' R' R' g
- /*********************************************************************
( \8 V/ l5 f+ l; G$ o5 P; | - *
; U) W7 p! B7 g* J2 g% l. W - * GUI_X_ExecIdle) h# c: h, |& g% K% F) f4 F M
- *
. Z! @- `5 \+ Q q/ c - * Note:7 H i$ N. X) L/ h3 i, G
- * Called if WM is in idle state
3 K& T2 e' c- Y) p1 n. R - */
/ z+ M) [2 f1 N; U$ T5 {, R2 x -
/ x& X6 V. h% r0 D9 G - void GUI_X_ExecIdle(void) {}8 f% e4 l( e6 }9 X- V9 g
- % R9 R0 b! C* q: ~
- /*********************************************************************
O1 H' u M4 W - *
$ F) k: P/ G+ C; g8 m1 ] - * Logging: OS dependent3 e9 x! U: o% J* c1 Q. b
-
' {: s- }8 e7 E9 K3 l - Note:
5 _% Y+ Z; I8 v7 D/ q - Logging is used in higher debug levels only. The typical target2 f d+ L: d1 b7 [6 k x* I
- build does not use logging and does therefor not require any of
* B [6 O# w6 E; P' U - the logging routines below. For a release build without logging+ v3 [+ M& x3 |( t l: m4 d
- the routines below may be eliminated to save some space.
% h- O. c* H+ G( ]7 z" z& v! y' o - (If the linker is not function aware and eliminates unreferenced
: i; Q m' y3 [" C6 \; E; g - functions automatically)
( w' s% \0 m; M7 K: \( P1 `8 q -
6 R ?* U8 n L& h; U - */
- U+ S x, G$ P. A. E) t8 R -
6 T8 `. M5 f3 z. g8 Y# |$ N: F - void GUI_X_Log (const char *s) { GUI_USE_PARA(s); }
9 m; I# _ G9 [% W; C' f - void GUI_X_Warn (const char *s) { GUI_USE_PARA(s); }
: U2 b! V1 p) ^! w/ L* V" D9 D2 E - void GUI_X_ErrorOut(const char *s) { GUI_USE_PARA(s); }
复制代码1. 时间基准全局变量,这个变量在bsp_timer.c文件里面进行了定义,由嘀嗒定时器中断进行调用,每1ms调用一次。 -
' v/ q6 [) j Z: t6 v$ Q, y - /*+ r& w3 C0 R" [) D
- 全局运行时间,单位1ms
5 e# {4 I5 o; n; @& M - 最长可以表示 24.85天,如果你的产品连续运行时间超过这个数,则必须考虑溢出问题 v( {1 S! w' j1 K$ W
- */
- g: H( Z' J$ E9 ^- E& d - __IO int32_t g_iRunTime = 0;9 Y! H3 c0 x1 C( i6 ]2 @8 W( p
- /*; j( k3 V( X2 A' l4 Z
- *********************************************************************************************************
6 s6 P" W5 ^: V( Q - * 函 数 名: SysTick_ISR3 B6 v2 r1 Q# D3 i+ f
- * 功能说明: SysTick中断服务程序,每隔1ms进入1次- h5 c& Y1 M+ r/ s! J' ^! m, s
- * 形 参: 无9 u( B4 r i9 ~, a
- * 返 回 值: 无
- X; K9 q8 X w' v( u - *********************************************************************************************************
* D1 \/ |, f0 i6 [: } - */" P# g3 s' E6 Q
- void SysTick_ISR(void)
3 k0 d" ~6 }7 x/ O; [3 M: Y - {: c |9 H% P# U( v- O
- static uint8_t s_count = 0;
& N3 D6 Q( D" r" z$ a R5 N) @" a - uint8_t i;9 D7 h `( e# c8 W
- 0 S7 r* p; p& P. B1 o3 y* C
- /* 每隔1ms进来1次 (仅用于 bsp_DelayMS) */$ G3 z, x5 u6 M: Q% K- A4 }2 ]
- if (s_uiDelayCount > 0)' ~2 J$ l! W( x8 i v" o$ @7 b+ G8 i
- {" e S8 ^) a1 v7 Y% T- t9 R8 a
- if (--s_uiDelayCount == 0)
+ g+ _& y9 ~# D9 _ - {, `' i: Z) z! |4 p s! Q
- s_ucTimeOutFlag = 1;
( q3 q. d: Z5 G2 y) q, h - }
/ t! H7 t F; N0 Y - }
- v Y0 I8 C( ]0 { -
4 m3 J' `# E/ D5 c9 N6 Q - /* 每隔1ms,对软件定时器的计数器进行减一操作 */# ~( }* ~# u! w9 E
- for (i = 0; i < TMR_COUNT; i++)8 e$ A( d7 z: J: b K" H/ L% D! _5 L
- {9 o' u' ~" }) D4 k
- bsp_SoftTimerDec(&s_tTmr[i]);5 Y0 Q- f1 _: F1 J, S6 H
- }& e. n# R7 _+ x
- 5 x X" T5 X, N) f
- /* 全局运行时间每1ms增1 */) v7 |: b$ }: e# C
- g_iRunTime++;; ]" X$ q7 C: V* E( y1 b% D: D# D
- if (g_iRunTime == 0x7FFFFFFF) /* 这个变量是 int32_t 类型,最大数为 0x7FFFFFFF */0 X- {. _- u: @
- {
B8 h7 l# i. k$ b1 { - g_iRunTime = 0;/ G3 f) [ U0 q D: l: [$ o
- }5 U$ @3 r% u# U3 k" W
-
$ H8 P9 L2 x+ Y+ ^, ^& m/ A3 ] - bsp_RunPer1ms(); /* 每隔1ms调用一次此函数,此函数在 bsp.c */
; D+ `- t) B/ ^9 c6 J+ {5 F -
% h/ }* @7 H- O7 C! x- O - if (++s_count >= 10)9 i, {! Q4 O1 X6 Z6 z3 h; U) s
- {+ b5 i" p- R7 j6 e- ^7 E7 t
- s_count = 0;# l: m6 t/ z6 G) K F- W* v, k
-
. D1 R: C& `, a - bsp_RunPer10ms(); /* 每隔10ms调用一次此函数,此函数在 bsp.c */) R5 j, a/ F$ }7 ~8 a+ ^3 f
- }$ z' z) g/ F* v# L7 D7 G; ?
- }
复制代码2. 供STemWin调用的接口函数,用于获取系统时钟基准。 3. 供STemWin调用的接口函数,用于延迟时间设置。 4. 主要设置上面两个函数即可,其余函数根据需要进行配置。 29.1.2 触摸接口 触摸部分由嘀嗒定时器中周期性的调用: - /*
* L( Q. b0 x% d; M - *********************************************************************************************************
- Y" v6 O5 l+ f. k# R" N - * 函 数 名: bsp_RunPer10ms
0 y. Q7 y' Q( d9 I - * 功能说明: 该函数每隔10ms被调用1次。在bsp_timer.c的定时中断调用。主要用于硬件事件检测 t( l: z1 A8 U. r
- * 形 参:无6 ~2 j0 Y# e5 j; J4 u" b
- * 返 回 值: 无 @, |: M% w3 X
- *********************************************************************************************************
2 b& a0 P/ Q8 i- }/ ?" _ - */7 |: m, [. X; p( e$ k# b
- extern __IO uint8_t s_ucRA8875BusyNow;" P4 T" U; | V6 b9 j2 Q
- void bsp_RunPer10ms(void)/ Q$ N! s* ]; ^8 F( J, ]
- {5 m3 H. K+ K& `/ |: s5 y& Y# v
- /* RA8875 触摸*/
. y- p% W+ o+ t2 [7 M2 P( \ - if (g_ChipID == IC_8875), {1 H. o e0 s
- {% h7 J/ f& l' g0 V7 G
- /* 资源共享标志 */
* M8 P, Q& n# Q - if(s_ucRA8875BusyNow == 0)
2 k0 J% ~6 c8 }9 _, y( R - {
. k, F8 w. v* T6 T: Z: N! ^ - GUI_TOUCH_Exec();
v- J3 h1 H. C0 R9 ]# _ - }
2 t# l+ j( C$ f( h1 t# Z& G* r7 P' o8 V - }
0 ?7 H( a/ V: g9 b# m' D# t$ Y1 R - /* XPT2046 */
4 L0 i7 t W2 _5 t8 w - else& H2 ?- U1 @/ L6 [0 Q3 H
- {# `* H2 T, }. D
- GUI_TOUCH_Exec();
5 r6 A" L, m6 `! g1 `7 | - }
3 @; j4 [9 K. L$ |- p3 b4 ] - }
复制代码 29.1.3 主程序在文件main.c - /*3 M: n- A7 _* `8 u1 c
- *********************************************************************************************************
9 Y: X! S, e- \7 {. T3 {' R& ^7 o - * 函 数 名: main& ~% L6 D2 m) z" I9 a/ D
- * 功能说明: c程序入口
9 k. x" ~8 p8 a" Q( r2 G' l - * 形 参:无
6 y! m& ] _" {( c" P - * 返 回 值: 错误代码(无需处理)5 Q6 N# O( C# l- `5 p1 a
- *********************************************************************************************************7 B F0 Z' p( V# K
- */
B# _- R- } Z% c' l4 S! A) f - int main(void)( ^8 ^4 A1 ]! p1 C. N) H
- {7 w0 ` e0 Z% a" }) K
- bsp_Init(); /* 为了是main函数看起来更简洁些,我们将硬件初始化的代码封装到这个函数 */; V5 T: I: c2 Y4 r
- + T$ @: [8 U Y+ {& C( A4 _6 w9 N8 b
- MainTask();+ O/ r8 P3 q" x# _0 G
- }
复制代码在文件MainTask.c - /*
4 M+ j, q3 a1 N5 X2 ]1 p. _ - *********************************************************************************************************7 P. a, }" `. d: q
- * 函 数 名: main9 ^7 R8 A& j! O9 ~
- * 功能说明: c程序入口0 j' A7 n% k- K: ~
- * 形 参:无 \9 B8 A% {7 M7 {, H
- * 返 回 值: 错误代码(无需处理)9 I7 u5 g) g- |" D
- *********************************************************************************************************$ l m( b, w' b
- */$ [: ~2 ^* |" d
- void MainTask(void)
- {6 f8 i$ Z5 n4 [" l6 u - {
M# {) I* I$ \% i0 P( z* A) C - int xPos;. N1 d4 t/ F, D
- int yPos;) b& A4 P8 R2 \' R' O. O, V
- int xSize;
; g) q+ F0 {. l( J1 U# c1 B( b - int i;. c6 k+ J' p/ C
-
$ N+ [3 c8 k- `: M( V - i = 0;0 ]- l9 Q Q4 _7 _0 i) {1 f) |
- /* 初始化 */0 ^* ]& A' c3 f* u$ a% m6 @* {3 J
- GUI_Init();
. {2 ]* \6 y* W; g- m$ C - /* 获取要显示的X,Y坐标 */% g% e6 w1 D4 J9 t* i6 V
- xPos = LCD_GetXSize() / 2;
& g1 I8 |9 j% P - yPos = LCD_GetYSize() / 3;
3 w/ E0 q+ v+ c9 g- F# T - /* 设置文本显示模式 */2 d$ \- |1 d9 i1 o/ T' E3 ^ \
- GUI_SetTextMode(GUI_TM_REV);
9 G% {# B' J2 I1 p0 n - /* 设置显示字体 */
: n" S2 K% u" ~' i) z; H5 v3 W' q { - GUI_SetFont(GUI_FONT_20F_ASCII);
$ d L; K1 c: g3 x7 ^4 m - GUI_DispStringHCenterAt("Hello world!", xPos, yPos);
! n7 M7 S" h2 t, i; v7 Q; w* { - /* 设置显示数字字体 */
: F- S7 ~% _1 W4 U$ E - GUI_SetFont(GUI_FONT_D24X32);! R9 g, ^( Z1 E; Y
- /* 获取显示0000,在字体GUI_FONT_D24X32下的显示情况 */. `. o6 {- I9 o% G) ^4 d* G
- xSize = GUI_GetStringDistX("0000");
6 ?( V: t' A7 f) ]' V0 @ - /* 设置显示位置 */
5 N' r* P+ P; O+ Z( z* ]2 @ - xPos -= xSize / 2;
0 ^) z z. ^4 y! _ - yPos += 24 + 10;
0 }# g" e; S! q. Q. q - while (1)
2 T+ h, X6 t, ?" |- y: y - {- x y. T! t) h% n W: _
- GUI_DispDecAt( i++, xPos, yPos, 4);
2 p0 {4 H [' Y! w; j+ K+ N - if (i > 9999) ) }: o; v& P$ V$ P1 ^: B
- {
1 Q$ s+ Z) g) N4 p# @ - i = 0;: l3 l3 R a9 a7 q) g
- }. |) d% ~) M& `* g
- }
6 _8 t' d x% S! I - }
复制代码功能比较简单,实现效果如下:
8 g U3 p+ M* K) C! b |