1 概述9 m! K3 P7 y2 K* M+ i
1.1 资源概述
# o& }7 h4 N2 P5 E* y P开发板:正点原子STM32F103 Nano开发板4 x$ V6 ~8 i) S: n4 J4 c2 z. T! g( x
MDK版本:5.275 a- T4 I* P. [# @* N0 e
主控芯片型号:STM32F103RBT61 j1 Y2 e b8 O7 k* k1 B: V. H, ?
+ p: _5 ?3 T, I" v g( i. N7 p
/ g% b) m" t3 O- B! ?" v9 X+ y( K
7 B( B& U+ M* R8 E/ h p* d1.2 实现功能
3 X8 W! g, y' a, A- z6 |2 D* y本实验在STM32F103开发板上移植了FreeRTOS,版本为V9.0.0。例程中创建了5个任务来测试移植是否成功。+ A1 A$ q! U; [3 o( P K
start_task任务创建其他4个测试任务
4 {& E( }# c2 t' D# K; {1 RTC_task:RTC的LCD液晶显示,串口打印任务
5 h: O6 u9 i8 `5 s. z2 LED1_task:跑马灯任务函数
+ j0 Y4 u, Q/ A2 X+ R3 LED0Toggle_task:LED0闪烁任务函数,键盘扫描任务" E* V, d# w! @& C2 k3 x& n3 `# f
4 BEEP_task 串口控制蜂鸣器任务
) S8 Q- C! W" o& u$ g# W6 O! A- m) E3 F: Z; ^+ U: ]; i6 |
2 程序源码& D" c! z0 F$ R
在程序中建立5个Task,一个启动Task,4个应用Task。按键扫描使用队列,检测到对应按键时,执行相应的操作。串口通讯使用信号量,检测到字符串后控制LED灯的亮灭。另外有一个任务1S钟一次刷新LCD显示,显示时间。: X6 Z4 a0 ?$ x6 r! w
主要代码借鉴了正点原子的程序,SPI屏幕商家提供的驱动以及最小系统版商家提供的驱动,由于RTOS这种系统的任务具有高内聚的特性。因此很容易将不同的任务移植到一起。
) U* Y x! M! ^
) c- K1 S8 a+ k' W, S" V- #include "led.h"4 |1 a) B2 f9 Q V; x; o7 {
- #include "delay.h"8 o: g: p. o# \/ X, C! w; _
- #include "sys.h"# s2 G" r L4 R" S
- #include "FreeRTOS.h"
! r! C0 S& i; g( {5 c/ Y- K - #include "task.h"" y1 ?, ^4 h* ?6 _4 U ~2 J ^4 p! G
- #include "LCD.h"2 d" O( z* x' ?1 f
- #include "gui.h": T. Z" h) T+ e
- #include "RTC_Time.h"
/ F5 D' v+ Y/ M' N - #include "queue.h"
8 ?( ^ l# z6 B% { - #include "key.h"' K: ~! `# A) a4 w1 B" j$ p2 G/ L! N
- #include "semphr.h"
2 X6 ~- `+ p. n: O. E F2 S - #include "malloc.h"
0 u' D6 P. s+ v) x - 8 @" E# W% K, D0 S8 f1 ^
3 n/ B, M# d, r- t
4 \: ~5 y% _3 } L; U, m% G) U- //任务优先级
( [4 N+ x/ V2 n - #define START_TASK_PRIO 1
9 T5 E& }7 y. D* b9 f$ |. k - //任务堆栈大小 $ l/ h F; v8 z+ T
- #define START_STK_SIZE 50
2 r2 W9 n" f; _$ L - //任务句柄
$ r, x. S0 J' [6 q0 ^' j9 v - TaskHandle_t StartTask_Handler;
. t* z) `/ K2 n& @( l - //任务函数
& g6 V l4 y2 {' } - void start_task(void *pvParameters);7 S6 P+ _) I0 o; i3 { ]- o# q
7 u% Z' a7 Y1 c# t+ T% O- //任务优先级
, d$ s1 C* M3 ]6 z8 k0 g* a8 { - #define LED0Toggle_task_PRIO 4
e% l- ~: g q8 [! T& E( } - //任务堆栈大小
& {/ [8 U+ ?) D x: F, F$ j: s& E - #define LED0Toggle_STK_SIZE 50 2 w5 r7 M9 x) ~* Q8 o) y
- //任务句柄
1 A' x$ Z6 y: ?5 b8 R" a; x - TaskHandle_t LED0ToggleTask_Handler;; B: g7 w& L1 J& _$ f
- //任务函数
$ N5 f; X' ^% k5 q - void LED0Toggle_task(void *pvParameters);% t4 c3 f/ T( p! m! W
- - X4 r& P" L% a( D6 S
- //任务优先级& s" U: R: ^- g) O# }( U/ S
- #define LED1_TASK_PRIO 37 V- ^( q; N* {; ^2 t7 l
- //任务堆栈大小 ( Y7 s5 N/ [) A7 S
- #define LED1_STK_SIZE 128
- e% m+ ?0 q. V5 \3 ^- s - //任务句柄
9 W/ I) V9 M9 J* {( {1 N1 m) Y - TaskHandle_t LED1Task_Handler;0 t ?% L, C8 @- r& y
- //任务函数4 Y2 ]- l% ?& ?$ V
- void LED1_task(void *pvParameters);
8 b7 d! b' N5 b - 4 X3 }; d4 Q4 K7 o% ]. @
- //任务优先级2 x# B) a3 W5 h( v
- #define RTC_TASK_PRIO 51 r8 l3 n) q3 H
- //任务堆栈大小 4 x( M' j' l$ W+ Z
- #define RTC_STK_SIZE 128 * ^0 T! W+ E8 h1 q* V7 ]; x
- //任务句柄
( F9 |' p A& v - TaskHandle_t RTCTask_Handler;
/ U" p* X3 G" d- r# \; O - //任务函数
2 @5 V. p* X: C/ F - void RTC_task(void *pvParameters);
/ h2 H$ y5 \; a. O" d9 V4 O8 o b. i R - , Y8 L- y1 K- x! E: t- p- \
- //任务优先级6 e2 Z; h; M. O% e+ u1 Z
- #define BEEP_TASK_PRIO 2
; H. G3 w7 B' e - //任务堆栈大小
3 i; B$ C4 e5 q6 ]' E# [ - #define BEEP_STK_SIZE 128
$ f) Z0 d1 U" ~5 P5 R* y/ S" W. H, G - //任务句柄
7 b: z7 u! h% D0 | - TaskHandle_t BEEPTask_Handler;2 r1 n8 e: x" l8 h# x+ n# H
- //任务函数
" p% h0 c8 b: i& k/ V( k( A - void BEEP_task(void *pvParameters);0 c/ Y. N# I# `# n# c
$ b0 e3 G& v- U$ j- QueueHandle_t Key_Queue; //按键值消息队列句柄
6 s# L$ w; t1 u1 u - #define KEYMSG_Q_NUM 1 //按键消息队列的数量
+ [. D0 m# ]6 [
5 ?# W5 j" q0 Z7 E/ a# M- //二值信号量句柄
4 n5 t. U- C9 W u" ? J - SemaphoreHandle_t BinarySemaphore; //二值信号量句柄) V& z+ q1 b8 {" O- X
- ( D' k, X* ?8 x% B$ _2 C6 W! n
- //用于命令解析用的命令值- Q: y7 I I9 q, G* b
- #define BEEPON 1
0 [$ ~3 }9 u" O* U' I - #define BEEPOFF 2
: R/ C) v5 E+ d7 o ^4 f a - #define COMMANDERR 0XFF
: p9 \4 ]$ E" S) m8 B6 j- F - ! J! ~! f0 w7 \$ R& S2 \
- //将字符串中的小写字母转换为大写% H7 l. `5 A* i% V8 o
- //str:要转换的字符串+ |" F3 n7 a# T6 P7 W
- //len:字符串长度& K9 x/ f: k' O& {0 K3 D- G
- void LowerToCap(u8 *str,u8 len)* C# n( s. h- g& D8 r0 o1 x
- {
, f" T. s8 L1 Q: F - u8 i;+ n+ O" S R3 [# p
- for(i=0;i<len;i++)1 m. d# [2 y. g2 f5 K
- {
2 j; v3 U+ o9 x3 }, g$ C$ W# e7 S - if((96<str<i>)&&(str<i><123)) //小写字母: T2 w4 O1 a) q- m2 C
- str<i>=str<i>-32; //转换为大写
! L g' |. {6 [ - }+ l( a( h/ q8 z/ z
- }, P7 q: Y5 C4 n( R& \0 s9 n
- ( s, E% A7 b" d0 z- Q
- //命令处理函数,将字符串命令转换成命令值
8 d/ x: ~) g. _1 ? - //str:命令
. a a4 |7 A8 g - //返回值: 0XFF,命令错误;其他值,命令值+ M8 y* L4 p/ Q5 B7 M( r; O
- u8 CommandProcess(u8 *str)
$ w. b4 q. ^7 j$ V3 v - {
' d2 }+ q8 H# d5 c9 ^( ~! u _ - u8 CommandValue=COMMANDERR;
9 B+ m! a! ~0 A, F0 Y. G" Y( b) a - if(strcmp((char*)str,"BEEPON")==0) CommandValue=BEEPON;
; _, h3 I# N4 F2 G - else if(strcmp((char*)str,"BEEPOFF")==0) CommandValue=BEEPOFF;
0 O1 v2 [' Y8 W- I' { - return CommandValue;& Z8 M8 d( l1 d9 G( }
- }0 Y8 o' u0 y: O9 F) j
$ B; [, q1 u1 z7 n! X- int main(void)
, G U* N3 ~9 C" X- M1 i - {5 f. n/ W7 r) Q* |. @
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4 - A! d, ]' [3 [4 z7 \2 z, z
- delay_init(); //延时函数初始化
' l! x* s8 S; A- b! X - uart_init(115200); //初始化串口
# P! {) j: I; B; z' |. H - LED_Init(); //初始化LED/ H9 m/ R4 W) p, V8 h/ O& @
- KEY_Init(); //按键初始化% P/ M; @) x' o1 ]/ Y/ B, H! D
- LCD_Init(); //液晶屏初始化+ g! h! t# i) F" H* t
- RTC_Init(); //RTC初始化; g) C3 n' K! v* ]4 M6 D# C0 {
- printf("*******************************\r\n");. a6 ^& Q$ }5 a" Y
- printf("* WKUP_PRES Backward LED\r\n");
% o* H3 J# Q7 T8 p: z- o6 N+ ] - printf("* KEY0_PRES Forward LED\r\n");
. Z' r# S9 K7 [8 s% ]2 r7 Y' @ - printf("* KEY1_PRES ALL LED ON\r\n");# m0 ]& m+ l0 u4 ^- R
- printf("* KEY2_PRES ALL LED OFF\r\n");* L5 w* W7 P! _2 Q/ T( _
- printf("* Uart send “BEEPON”:BEEP ON \r\n");$ d6 L/ \- F* d( ?* t
- printf("* Uart send “BEEPOFF”:BEEP OFF \r\n");
( P* N" ~ Y d; v# e& R - printf("*******************************\r\n");
2 p7 P7 G/ N5 x( M" ?5 e5 t" C, L - //创建开始任务9 \- X4 @7 [% r4 D0 ?4 ^2 v
- xTaskCreate((TaskFunction_t )start_task, //任务函数
+ t7 {% }/ N3 W( o. p# {6 _# J1 U: x - (const char* )"start_task", //任务名称
* d& z4 W$ a& E, M& r/ h1 K - (uint16_t )START_STK_SIZE, //任务堆栈大小
x& X x5 q% n K. T+ \ - (void* )NULL, //传递给任务函数的参数
- h; b2 [/ B0 ^! P2 J' [ - (UBaseType_t )START_TASK_PRIO, //任务优先级
- {0 [$ F/ U3 a# v$ c5 x - (TaskHandle_t* )&StartTask_Handler); //任务句柄
3 a: E& W9 j/ b! Y9 ?+ _ - vTaskStartScheduler(); //开启任务调度" K" ?/ X! w N9 \5 a$ C$ A
- }6 t! B- ^; W2 V( k% S& B4 z* m. n
+ U; ~( R, y8 X% p- //开始任务任务函数
& j3 [# I5 |* \: m& X4 A - void start_task(void *pvParameters)
" Q, X3 ]+ q9 O3 z1 j - {
0 v6 I% e5 |+ P7 O2 ~ - taskENTER_CRITICAL(); //进入临界区
2 U1 n2 m* _, r5 n" C8 U9 h& l' k3 k - Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8)); //创建消息Key_Queue
* H8 Q, N% T: H& Z' p6 S( X) W - //创建二值信号量) E D& f0 i. x$ J1 e
- BinarySemaphore=xSemaphoreCreateBinary();
9 U3 q( u# }7 F4 z' v3 T" h1 a - //创建LED0任务
, U6 E$ j! m# m9 |8 z - xTaskCreate((TaskFunction_t )LED0Toggle_task, 6 ]* ~9 ^7 M! q V
- (const char* )"LED0Toggle_task", ) q ]1 U1 l7 L
- (uint16_t )LED0Toggle_STK_SIZE, 3 X8 `5 n8 _0 y& x1 T V
- (void* )NULL,
2 ], U- p' s/ U7 a% b' i: N - (UBaseType_t )LED0Toggle_task_PRIO,
; F! U! ]) R% Q! }0 B) c2 m - (TaskHandle_t* )&LED0ToggleTask_Handler);
7 G+ m1 \9 N& W; w - //创建LCD任务
6 t* e3 F) [! d& q a! C - xTaskCreate((TaskFunction_t )LED1_task,
+ @+ ~( Y+ R D7 T, |! J - (const char* )"LED1_task", / Q4 G6 w' T" V8 |; u
- (uint16_t )LED1_STK_SIZE,
+ W2 \- s( E: N9 M1 R( ~ - (void* )NULL,5 | p8 `8 `2 M Z
- (UBaseType_t )LED1_TASK_PRIO,4 T% R- M1 X. e
- (TaskHandle_t* )&LED1Task_Handler);
+ ]3 C! B x/ \2 P - xTaskCreate((TaskFunction_t )RTC_task, ; F. V4 a2 Q- A
- (const char* )"RTC_task",
0 c" r8 I8 q# ~ - (uint16_t )RTC_STK_SIZE, * A1 S6 }5 q+ r2 I5 S2 S0 W* [
- (void* )NULL,! l) z7 Q$ {# v
- (UBaseType_t )RTC_TASK_PRIO,4 R6 p4 I& `) W# v* b
- (TaskHandle_t* )&RTCTask_Handler);
& L8 ?, s$ C, o: C5 m - xTaskCreate((TaskFunction_t )BEEP_task,
9 {5 ?, F* x# A+ _" R) {' m) N - (const char* )"BEEP_task",
) ^" U0 Z X( Q" {: s* Z - (uint16_t )BEEP_STK_SIZE,
1 u( D' I f; I' X - (void* )NULL,+ Q/ i5 q, X, f) @6 u+ E' P( Y$ e% _
- (UBaseType_t )BEEP_TASK_PRIO,
( J8 h) }% R" G( P# D( s; r& K - (TaskHandle_t* )&BEEPTask_Handler); ( q) F# M0 O* ?& o$ M! n
- vTaskDelete(StartTask_Handler); //删除开始任务
% n3 m# @2 g/ ]6 W9 Y3 R: h - taskEXIT_CRITICAL(); //退出临界区
8 M- o, }4 X/ R, T0 _, T9 F7 c - }
$ p6 u3 a m2 A1 X/ l$ r
1 W3 V, @" v0 P& c; ]- //LED0闪烁任务函数,提示程序正在运行,且为按键扫描程序,像队列发送信息
: r7 \1 Z& ~- T6 e6 e - void LED0Toggle_task(void *pvParameters)3 z `7 o7 B* P4 U( `3 {! Z
- {6 |: [% N3 Q# l4 }+ H
- u8 key,i=0;
. M9 [( X6 c" D( f: `0 H* X& ^ - BaseType_t err;
, T1 F9 T- I0 N/ h - printf("LED0Toggle Task Running!\r\n");
: r$ r# X" V. X/ m C" r - while(1)3 Y) @0 l, ]! W/ s
- {/ {* L0 ^5 R0 q# a) F" C
- key=KEY_Scan(0); //扫描按键
0 Y$ u c; w* x - if((Key_Queue!=NULL)&&(key)) //消息队列Key_Queue创建成功,并且按键被按下* Z8 s j: H( }4 ?' L
- {$ F1 E8 O" c7 X% w! \2 Z% g
- err=xQueueSend(Key_Queue,&key,10);
! `; b6 O3 A+ }- \3 H7 i - if(err==errQUEUE_FULL) //发送按键值
8 }; H; [% Q e0 O8 M - {
" I4 }. j/ U3 }8 D - printf("队列Key_Queue已满,数据发送失败!\r\n");
+ s0 I1 c' w3 @ - }
5 c4 K5 \, [$ ~ - }
. r! n! G, b) J4 [: Z9 u4 s. w! e - i++;
+ ?6 ?( p; ^" V - if(i==50)
. H; Z' R7 s: A4 w5 G& M - {
) l5 [" F" j' l* D' N6 A - i=0;& D( o: u+ d$ q) r; @
- LED0=!LED0;9 f4 L* i3 ~# y4 u& O4 T
- }0 W6 w; _: a2 I
- vTaskDelay(10); //延时10ms,也就是10个时钟节拍 ; e8 }7 ? L+ J. |" J) s- c
- }2 a, O8 Z! g: L) s1 W# r7 t! x9 _
- }
# _- {) ]. _2 K - 5 d, v, M+ C d, t3 T! E9 U
- //跑马灯任务函数,使用按键控制灯的方向,以及控制灯的亮灭
. I# x& u ^/ f" p - void LED1_task(void *pvParameters)! w( Z5 L1 h3 O; ?: f
- {8 y2 H3 a ~6 l
- u8 key=0;
# Z" G- `1 ?2 ?" T$ w$ G9 D @ - printf("LED1 Task Running!\r\n"); [! Q; S9 `% t) }) P7 x
- / b" e6 A) c, W& U4 f, P, h' Y4 _
- while(1)
$ ?, `, I# f( l) @, C - {
T/ N" S7 Y8 i; ~ - if(Key_Queue!=NULL)
( p$ O: m: ~# }' |( S+ y" B6 } - {" Y) ~! ?7 K( J1 u: e+ n: }0 x
- if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue
/ c0 |7 f2 D9 O$ ]6 m: d - {; Y. M5 u5 j h3 L$ g
- switch(key)! e2 A7 V, b/ H' D9 N4 ^. Y
- {" ]9 }% b+ C I; T' P6 Q& Z5 U
- case WKUP_PRES: //KEY_UP控制流水灯方向,逆向
0 `# R! |' z4 s - LED1=1;
! g% E$ {2 A& A0 Q+ {0 M; Q% e6 J - LED7=0;2 p& `: |6 D6 J8 K! L/ T
- vTaskDelay(200);
- x$ T9 w3 K3 a2 D - LED7=1;9 o' U3 d L3 i% K
- LED6=0;2 A. x t3 [$ m" j) i$ M0 f' j
- vTaskDelay(200);6 W) m7 |+ P" A$ A: l5 K8 ]
- LED6=1;
* g$ }3 |; x7 b - LED5=0;
# I1 |& K3 b8 J& X* Z - vTaskDelay(200);
% H+ a6 S7 [ R$ r5 V - LED5=1;
+ j) B- i/ V; [9 g1 E9 s% W - LED4=0;
! r2 R; @. G; `; I) w( n& u - vTaskDelay(200);
( |. _% ?6 s, ]! \ - LED4=1;
! _$ j/ z! \) @. ^5 \& U) G5 T - LED3=0;
" ~0 [6 x% R8 e - vTaskDelay(200);
& g! j9 {2 `( N3 \# [; Y - LED3=1;( ?$ G# p5 X) x0 ]0 {; b
- LED2=0;
; _% U8 n: y9 a: Y( ]$ S - vTaskDelay(200); 6 L; L+ R! u& S% P5 ?; S
- LED2=1;1 s2 |5 C: d0 A& W" T
- LED1=0;
+ q& p B$ f. [' l; ` - vTaskDelay(200);" d# D* A6 \% E% \/ j, p
- break;
9 X, W D% ?9 s% y) } - case KEY0_PRES: //KEY0控制LED灯方向,顺向5 d( G+ l. i$ U& |4 ~
- LED7=1;
6 l% w4 A/ k& J" e - LED1=0;
1 P$ S$ w! p+ \9 _( v! A - vTaskDelay(200);+ P- u* D1 b% h5 ?% I
- LED1=1;
! a+ q H2 @+ l' o+ g' u - LED2=0;
# z' x9 ~& r# E$ U; w - vTaskDelay(200);
3 g) D p, {" {8 l) q" P' E% }$ Y+ S - LED2=1;9 n, x1 y: D. T# O v) l& s
- LED3=0;& R8 @9 t, h( L% N: g7 ]
- vTaskDelay(200);& s* ]) _8 c7 P8 y! T6 t7 I* o; I
- LED3=1;/ C2 Y6 N$ e' T) r% L
- LED4=0;# C& |$ q Y% ?
- vTaskDelay(200);
' Z* }& h. Y, u: w3 o5 ^) U - LED4=1;
' b) R! O: v0 d7 M5 P4 ` - LED5=0;1 y# B8 k/ Q+ ]* q: u/ ]
- vTaskDelay(200);. c! r! L5 a* ?6 ?/ j
- LED5=1;( [5 l) j4 W+ v
- LED6=0;* g$ x: l/ v. D% n; ]+ \
- vTaskDelay(200);
9 W. w$ E) t" L - LED6=1;
5 N1 |) V" O2 [- `+ F - LED7=0;
9 Y7 E( Y+ e* `' L/ j9 T - vTaskDelay(200);
4 k1 l+ ^1 ~. Q8 l. H# f - break;
- m7 z% ?( g# F - case KEY2_PRES:
% S2 h, I/ L5 y2 R) J" F - LED1=1;LED2=1;LED3=1;LED4=1;LED5=1;LED6=1;LED7=1;//关闭所有LED灯8 c! v" W4 X$ p# K3 g% p, [
- break;/ Z8 k0 G3 u' g; P# y
- case KEY1_PRES:; _- y5 r0 X$ ^) P- K# D
- LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;LED6=0;LED7=0;//打开所有LED灯 " o/ c; j& `2 Y
- break;. ~* y8 \6 }7 W3 Z, S
- }5 L* p: Y$ |: u R7 M
- }
1 z' p, ^ ]/ t4 d; x - }
- k: j, ^$ L8 y! e, |0 C! d - vTaskDelay(10); //延时10ms,也就是10个时钟节拍
! i( W' G- n; o" q3 }; C - }
, q+ ^, w7 z! f ^+ Q# j - }) h3 ^8 e. g' l E/ Z9 H
- //RTC的LCD液晶显示,串口打印任务,并在LCD上进行显示/ y# z; U! T) ?: Y: [2 e" s& m
- void RTC_task(void *pvParameters)
8 o+ F- e# x N9 z' b - {1 q! ~) {9 H) e# a0 b! E# |! k
- printf("RTC Task Running!\r\n");
# p9 o: E) m& O* d- l& Z - while(1)
3 @0 e6 f% S( @( M- A - {
9 h" q& `3 j' q9 x' v: x, q) r# Y - Time_Display(); . Y0 T: Z0 q( A' p( L5 ] m
- vTaskDelay(1000);//每一秒钟刷新LED屏幕,显示时间9 r& X: x. g: b$ b
- }
; w& z$ Z8 V; g6 t5 F9 B9 \ - } ' z) o, P" a A& H' m, a4 N
- 3 n2 k V$ ?$ n& G$ u K# {, F; y8 e
- //BEEP任务,通过串口发送数据控制蜂鸣器/ s7 `- g2 Y& {4 M
- void BEEP_task(void *pvParameters)3 s0 O6 a% u) T- b
- {
2 Y w4 ]' ?9 Z* f) u - u8 len=0;& ?& c: Q% G( v/ U
- u8 CommandValue=COMMANDERR; y5 C& j7 v1 F2 v. f8 z2 W# j
- BaseType_t err=pdFALSE;
$ j* R/ }9 j% Q6 u$ I/ K - & |5 n) t, m9 m% k- c! S
- u8 *CommandStr;
4 q4 ?8 i! A& v2 [ - POINT_COLOR=BLUE;% R$ M/ K a( ]) J; ^/ C
- printf("BEEP Task Running!\r\n");
8 l$ @$ w* A$ p; e% ?( ~ B - while(1)
4 Q' O' G" J- e( P6 r( h - {0 k' t- J8 N8 K+ A- b5 O
- if(BinarySemaphore!=NULL)
& j( [/ E& O0 w0 l9 K8 \ - {+ _% T: a- T/ v+ O' P
- err=xSemaphoreTake(BinarySemaphore,portMAX_DELAY); //获取信号量
) e/ @7 r2 w7 q& \ - if(err==pdTRUE) //获取信号量成功! T& a# w4 i" I9 s0 S& {! X" |
- {# l' |. k2 d' j! Q; [5 e% v
- len=USART_RX_STA&0x3fff; //得到此次接收到的数据长度* l* J6 I' v- U8 ^- z" _
- CommandStr=mymalloc(len+1); //申请内存
2 q! n8 {* E6 B: B2 Q5 a - sprintf((char*)CommandStr,"%s",USART_RX_BUF);
' ^" e5 c5 P" _& E* r - CommandStr[len]='\0'; //加上字符串结尾符号 I) L, u; Y9 A# m# e
- LowerToCap(CommandStr,len); //将字符串转换为大写 8 C. F* |% ^9 A
- CommandValue=CommandProcess(CommandStr); //命令解析
, `9 O# ^% S! u1 M3 O6 } - if(CommandValue!=COMMANDERR)' d& J& K8 Y( \8 `1 r. o$ D1 c
- {! q1 H0 J5 Q7 H1 Y3 F. Q
- printf("命令为:%s\r\n",CommandStr);
4 Y- W8 c/ G1 K. E - switch(CommandValue) //处理命令
8 o$ Z, c+ y7 c* Q; O: D7 M' b l" U - {
: C) j( L, i r( _4 {) r% I8 |( w - case BEEPON: , B4 ~7 ^+ b r6 [) B9 {
- BEEP=0;$ \6 Q: @! T% i3 `$ D8 A
- break;
/ b9 d' r# H. s# o; ~ - case BEEPOFF:
& C& x( D0 M: B; Y - BEEP=1;5 H, q. f7 c. w
- break;
' A: {5 z# _' S - }, q0 ^2 q# V9 L
- }+ ~: g3 |) |& |2 [+ E6 z# t9 e, _+ Y
- else+ G2 s% n9 u1 j
- {
) i1 R3 k5 P/ u+ v9 R. T - printf("无效的命令,请重新输入!!\r\n");; K. Y: N1 W) S: [# v
- }9 E; J: M4 {1 V/ _( q% [* `
- USART_RX_STA=0;, }3 r$ T7 p2 D% G
- memset(USART_RX_BUF,0,USART_REC_LEN); //串口接收缓冲区清零; X f! Z7 v, z. ?( d; Y' Y
- myfree(CommandStr); //释放内存' S9 h6 |6 F, l5 N4 M' a" ]3 \
- }
$ J9 i0 `7 D0 V6 d: U/ i - }7 v- w! a. m$ ~/ L& H% |
- else if(err==pdFALSE)
7 E9 C3 J m2 s - {* t/ {4 M" F* u
- vTaskDelay(10); //延时10ms,也就是10个时钟节拍 % w! ?/ F4 G0 N$ D! `! b
- }) O+ U9 F, N3 X: l! u
- }7 k1 l6 E+ A3 u3 c9 E6 h
- } </i></i></i></i>
复制代码
- t9 p5 M: L8 x$ m% r) A7 s. \LCD显示函数Time_Display如下
; G1 F/ w2 W1 l' O5 L X& j; J, K6 l& ]7 w+ \6 H$ V
- void Time_Display(void)
[; Y+ d5 E9 F( F) X - {
' m) T; R! Y- p. S2 \1 M - struct tm time;& _# ^+ c0 L/ f' J1 a1 L
- char LCDTemp[100];9 f; g2 R$ w4 E" L7 }5 F
- time = Time_GetCalendarTime();7 I4 E+ Z' i$ s2 s& D8 Y+ N4 h- R
- printf("Time: %d-%d-%d %02d:%02d:%02d \r\n", time.tm_year, \ k4 X0 H5 N; e' A5 e* h6 u6 u' c/ M
- time.tm_mon+1, time.tm_mday,\0 m; i$ b; S" \, m/ q; o2 [, `) ^
- time.tm_hour, time.tm_min, time.tm_sec);//打印到串口( d+ ?" t6 K) Y1 \( [/ x3 V
-
/ t6 E. S7 M z9 G9 i# H - sprintf(LCDTemp,"Time: %d-%d-%d %02d:%02d:%02d \r\n", time.tm_year, \
) B8 ?$ l6 c% S: n - time.tm_mon+1, time.tm_mday,\ U7 [4 J- Z& h* @( p3 z8 j
- time.tm_hour, time.tm_min, time.tm_sec);//打印到字符串* ?! O# T# J g9 |( C2 K
- Show_Str(10,80,BLUE,YELLOW,LCDTemp,16,0);//显示字符串
2 f% O! K' t8 M! r - }
复制代码
% M% M/ ?8 g7 c7 n7 l- W0 M: z. }, h1 E0 K2 a5 S" ]1 y
3 实验结果
8 X- ~4 p& _: D" I+ `! }& J) M打开串口,显示时间如下,每秒将时间打印到串口
6 U5 t5 j6 t! J6 c6 ]1 ~7 V" |& _& {7 v& Y$ R
& O* v J& E- u/ L5 \5 `
$ n; J4 V G0 t% r& G0 ELCD移植后效果图
0 Z) t2 }. y" c5 n$ b- M0 f1 S0 j( F+ P0 X3 o3 V8 _1 j
1 p. ~0 ^8 a( T) \6 ^
6 F/ X) [$ x1 R" {; |2 _# V8 X
|