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

【经验分享】STM32开发,正点原子Nano开发板移植Free RTOS实现RTC液晶显示RTC时钟

[复制链接]
STMCU小助手 发布时间:2022-5-5 14:46
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 %X[H_Q~BNJGY7XG4JI4XBWB.png
/ 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
  1. #include "led.h"4 |1 a) B2 f9 Q  V; x; o7 {
  2. #include "delay.h"8 o: g: p. o# \/ X, C! w; _
  3. #include "sys.h"# s2 G" r  L4 R" S
  4. #include "FreeRTOS.h"
    ! r! C0 S& i; g( {5 c/ Y- K
  5. #include "task.h"" y1 ?, ^4 h* ?6 _4 U  ~2 J  ^4 p! G
  6. #include "LCD.h"2 d" O( z* x' ?1 f
  7. #include "gui.h": T. Z" h) T+ e
  8. #include "RTC_Time.h"
    / F5 D' v+ Y/ M' N
  9. #include "queue.h"
    8 ?( ^  l# z6 B% {
  10. #include "key.h"' K: ~! `# A) a4 w1 B" j$ p2 G/ L! N
  11. #include "semphr.h"
    2 X6 ~- `+ p. n: O. E  F2 S
  12. #include "malloc.h"
    0 u' D6 P. s+ v) x
  13. 8 @" E# W% K, D0 S8 f1 ^

  14. 3 n/ B, M# d, r- t

  15. 4 \: ~5 y% _3 }  L; U, m% G) U
  16. //任务优先级
    ( [4 N+ x/ V2 n
  17. #define START_TASK_PRIO                1
    9 T5 E& }7 y. D* b9 f$ |. k
  18. //任务堆栈大小        $ l/ h  F; v8 z+ T
  19. #define START_STK_SIZE                 50  
    2 r2 W9 n" f; _$ L
  20. //任务句柄
    $ r, x. S0 J' [6 q0 ^' j9 v
  21. TaskHandle_t StartTask_Handler;
    . t* z) `/ K2 n& @( l
  22. //任务函数
    & g6 V  l4 y2 {' }
  23. void start_task(void *pvParameters);7 S6 P+ _) I0 o; i3 {  ]- o# q

  24. 7 u% Z' a7 Y1 c# t+ T% O
  25. //任务优先级
    , d$ s1 C* M3 ]6 z8 k0 g* a8 {
  26. #define LED0Toggle_task_PRIO                4
      e% l- ~: g  q8 [! T& E( }
  27. //任务堆栈大小        
    & {/ [8 U+ ?) D  x: F, F$ j: s& E
  28. #define LED0Toggle_STK_SIZE                 50 2 w5 r7 M9 x) ~* Q8 o) y
  29. //任务句柄
    1 A' x$ Z6 y: ?5 b8 R" a; x
  30. TaskHandle_t LED0ToggleTask_Handler;; B: g7 w& L1 J& _$ f
  31. //任务函数
    $ N5 f; X' ^% k5 q
  32. void LED0Toggle_task(void *pvParameters);% t4 c3 f/ T( p! m! W
  33. - X4 r& P" L% a( D6 S
  34. //任务优先级& s" U: R: ^- g) O# }( U/ S
  35. #define LED1_TASK_PRIO                37 V- ^( q; N* {; ^2 t7 l
  36. //任务堆栈大小        ( Y7 s5 N/ [) A7 S
  37. #define LED1_STK_SIZE                 128  
    - e% m+ ?0 q. V5 \3 ^- s
  38. //任务句柄
    9 W/ I) V9 M9 J* {( {1 N1 m) Y
  39. TaskHandle_t LED1Task_Handler;0 t  ?% L, C8 @- r& y
  40. //任务函数4 Y2 ]- l% ?& ?$ V
  41. void LED1_task(void *pvParameters);
    8 b7 d! b' N5 b
  42. 4 X3 }; d4 Q4 K7 o% ]. @
  43. //任务优先级2 x# B) a3 W5 h( v
  44. #define RTC_TASK_PRIO                51 r8 l3 n) q3 H
  45. //任务堆栈大小        4 x( M' j' l$ W+ Z
  46. #define RTC_STK_SIZE                 128  * ^0 T! W+ E8 h1 q* V7 ]; x
  47. //任务句柄
    ( F9 |' p  A& v
  48. TaskHandle_t RTCTask_Handler;
    / U" p* X3 G" d- r# \; O
  49. //任务函数
    2 @5 V. p* X: C/ F
  50. void RTC_task(void *pvParameters);
    / h2 H$ y5 \; a. O" d9 V4 O8 o  b. i  R
  51. , Y8 L- y1 K- x! E: t- p- \
  52. //任务优先级6 e2 Z; h; M. O% e+ u1 Z
  53. #define BEEP_TASK_PRIO                2
    ; H. G3 w7 B' e
  54. //任务堆栈大小        
    3 i; B$ C4 e5 q6 ]' E# [
  55. #define BEEP_STK_SIZE                 128  
    $ f) Z0 d1 U" ~5 P5 R* y/ S" W. H, G
  56. //任务句柄
    7 b: z7 u! h% D0 |
  57. TaskHandle_t BEEPTask_Handler;2 r1 n8 e: x" l8 h# x+ n# H
  58. //任务函数
    " p% h0 c8 b: i& k/ V( k( A
  59. void BEEP_task(void *pvParameters);0 c/ Y. N# I# `# n# c

  60. $ b0 e3 G& v- U$ j
  61. QueueHandle_t Key_Queue;                   //按键值消息队列句柄
    6 s# L$ w; t1 u1 u
  62. #define KEYMSG_Q_NUM    1                  //按键消息队列的数量  
    + [. D0 m# ]6 [

  63. 5 ?# W5 j" q0 Z7 E/ a# M
  64. //二值信号量句柄
    4 n5 t. U- C9 W  u" ?  J
  65. SemaphoreHandle_t BinarySemaphore;        //二值信号量句柄) V& z+ q1 b8 {" O- X
  66. ( D' k, X* ?8 x% B$ _2 C6 W! n
  67. //用于命令解析用的命令值- Q: y7 I  I9 q, G* b
  68. #define BEEPON        1
    0 [$ ~3 }9 u" O* U' I
  69. #define BEEPOFF        2
    : R/ C) v5 E+ d7 o  ^4 f  a
  70. #define COMMANDERR        0XFF
    : p9 \4 ]$ E" S) m8 B6 j- F
  71. ! J! ~! f0 w7 \$ R& S2 \
  72. //将字符串中的小写字母转换为大写% H7 l. `5 A* i% V8 o
  73. //str:要转换的字符串+ |" F3 n7 a# T6 P7 W
  74. //len:字符串长度& K9 x/ f: k' O& {0 K3 D- G
  75. void LowerToCap(u8 *str,u8 len)* C# n( s. h- g& D8 r0 o1 x
  76. {
    , f" T. s8 L1 Q: F
  77.         u8 i;+ n+ O" S  R3 [# p
  78.         for(i=0;i<len;i++)1 m. d# [2 y. g2 f5 K
  79.         {
    2 j; v3 U+ o9 x3 }, g$ C$ W# e7 S
  80.                 if((96<str<i>)&&(str<i><123))        //小写字母: T2 w4 O1 a) q- m2 C
  81.                 str<i>=str<i>-32;                                //转换为大写
    ! L  g' |. {6 [
  82.         }+ l( a( h/ q8 z/ z
  83. }, P7 q: Y5 C4 n( R& \0 s9 n
  84. ( s, E% A7 b" d0 z- Q
  85. //命令处理函数,将字符串命令转换成命令值
    8 d/ x: ~) g. _1 ?
  86. //str:命令
    . a  a4 |7 A8 g
  87. //返回值: 0XFF,命令错误;其他值,命令值+ M8 y* L4 p/ Q5 B7 M( r; O
  88. u8 CommandProcess(u8 *str)
    $ w. b4 q. ^7 j$ V3 v
  89. {
    ' d2 }+ q8 H# d5 c9 ^( ~! u  _
  90.         u8 CommandValue=COMMANDERR;
    9 B+ m! a! ~0 A, F0 Y. G" Y( b) a
  91.         if(strcmp((char*)str,"BEEPON")==0) CommandValue=BEEPON;
    ; _, h3 I# N4 F2 G
  92.         else if(strcmp((char*)str,"BEEPOFF")==0) CommandValue=BEEPOFF;
    0 O1 v2 [' Y8 W- I' {
  93.         return CommandValue;& Z8 M8 d( l1 d9 G( }
  94. }0 Y8 o' u0 y: O9 F) j

  95. $ B; [, q1 u1 z7 n! X
  96. int main(void)
    , G  U* N3 ~9 C" X- M1 i
  97. {5 f. n/ W7 r) Q* |. @
  98.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4                  - A! d, ]' [3 [4 z7 \2 z, z
  99.         delay_init();                                            //延时函数初始化         
    ' l! x* s8 S; A- b! X
  100.         uart_init(115200);                                        //初始化串口
    # P! {) j: I; B; z' |. H
  101.         LED_Init();                                                          //初始化LED/ H9 m/ R4 W) p, V8 h/ O& @
  102.         KEY_Init();        //按键初始化% P/ M; @) x' o1 ]/ Y/ B, H! D
  103.         LCD_Init();           //液晶屏初始化+ g! h! t# i) F" H* t
  104.     RTC_Init();        //RTC初始化; g) C3 n' K! v* ]4 M6 D# C0 {
  105.         printf("*******************************\r\n");. a6 ^& Q$ }5 a" Y
  106.         printf("* WKUP_PRES Backward LED\r\n");
    % o* H3 J# Q7 T8 p: z- o6 N+ ]
  107.         printf("* KEY0_PRES Forward LED\r\n");
    . Z' r# S9 K7 [8 s% ]2 r7 Y' @
  108.         printf("* KEY1_PRES ALL LED ON\r\n");# m0 ]& m+ l0 u4 ^- R
  109.         printf("* KEY2_PRES ALL LED OFF\r\n");* L5 w* W7 P! _2 Q/ T( _
  110.         printf("* Uart send “BEEPON”:BEEP ON \r\n");$ d6 L/ \- F* d( ?* t
  111.         printf("* Uart send “BEEPOFF”:BEEP OFF \r\n");        
    ( P* N" ~  Y  d; v# e& R
  112.         printf("*******************************\r\n");        
    2 p7 P7 G/ N5 x( M" ?5 e5 t" C, L
  113.         //创建开始任务9 \- X4 @7 [% r4 D0 ?4 ^2 v
  114.     xTaskCreate((TaskFunction_t )start_task,            //任务函数
    + t7 {% }/ N3 W( o. p# {6 _# J1 U: x
  115.                 (const char*    )"start_task",          //任务名称
    * d& z4 W$ a& E, M& r/ h1 K
  116.                 (uint16_t       )START_STK_SIZE,        //任务堆栈大小
      x& X  x5 q% n  K. T+ \
  117.                 (void*          )NULL,                  //传递给任务函数的参数
    - h; b2 [/ B0 ^! P2 J' [
  118.                 (UBaseType_t    )START_TASK_PRIO,       //任务优先级
    - {0 [$ F/ U3 a# v$ c5 x
  119.                 (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    3 a: E& W9 j/ b! Y9 ?+ _
  120.     vTaskStartScheduler();          //开启任务调度" K" ?/ X! w  N9 \5 a$ C$ A
  121. }6 t! B- ^; W2 V( k% S& B4 z* m. n

  122. + U; ~( R, y8 X% p
  123. //开始任务任务函数
    & j3 [# I5 |* \: m& X4 A
  124. void start_task(void *pvParameters)
    " Q, X3 ]+ q9 O3 z1 j
  125. {
    0 v6 I% e5 |+ P7 O2 ~
  126.     taskENTER_CRITICAL();           //进入临界区
    2 U1 n2 m* _, r5 n" C8 U9 h& l' k3 k
  127.     Key_Queue=xQueueCreate(KEYMSG_Q_NUM,sizeof(u8));        //创建消息Key_Queue
    * H8 Q, N% T: H& Z' p6 S( X) W
  128.         //创建二值信号量) E  D& f0 i. x$ J1 e
  129.         BinarySemaphore=xSemaphoreCreateBinary();        
    9 U3 q( u# }7 F4 z' v3 T" h1 a
  130.     //创建LED0任务
    , U6 E$ j! m# m9 |8 z
  131.     xTaskCreate((TaskFunction_t )LED0Toggle_task,             6 ]* ~9 ^7 M! q  V
  132.                 (const char*    )"LED0Toggle_task",           ) q  ]1 U1 l7 L
  133.                 (uint16_t       )LED0Toggle_STK_SIZE, 3 X8 `5 n8 _0 y& x1 T  V
  134.                 (void*          )NULL,                                
    2 ], U- p' s/ U7 a% b' i: N
  135.                 (UBaseType_t    )LED0Toggle_task_PRIO,        
    ; F! U! ]) R% Q! }0 B) c2 m
  136.                 (TaskHandle_t*  )&LED0ToggleTask_Handler);   
    7 G+ m1 \9 N& W; w
  137.     //创建LCD任务
    6 t* e3 F) [! d& q  a! C
  138.     xTaskCreate((TaskFunction_t )LED1_task,     
    + @+ ~( Y+ R  D7 T, |! J
  139.                 (const char*    )"LED1_task",   / Q4 G6 w' T" V8 |; u
  140.                 (uint16_t       )LED1_STK_SIZE,
    + W2 \- s( E: N9 M1 R( ~
  141.                 (void*          )NULL,5 |  p8 `8 `2 M  Z
  142.                 (UBaseType_t    )LED1_TASK_PRIO,4 T% R- M1 X. e
  143.                 (TaskHandle_t*  )&LED1Task_Handler);
    + ]3 C! B  x/ \2 P
  144.     xTaskCreate((TaskFunction_t )RTC_task,     ; F. V4 a2 Q- A
  145.                 (const char*    )"RTC_task",   
    0 c" r8 I8 q# ~
  146.                 (uint16_t       )RTC_STK_SIZE, * A1 S6 }5 q+ r2 I5 S2 S0 W* [
  147.                 (void*          )NULL,! l) z7 Q$ {# v
  148.                 (UBaseType_t    )RTC_TASK_PRIO,4 R6 p4 I& `) W# v* b
  149.                 (TaskHandle_t*  )&RTCTask_Handler);   
    & L8 ?, s$ C, o: C5 m
  150.     xTaskCreate((TaskFunction_t )BEEP_task,     
    9 {5 ?, F* x# A+ _" R) {' m) N
  151.                 (const char*    )"BEEP_task",   
    ) ^" U0 Z  X( Q" {: s* Z
  152.                 (uint16_t       )BEEP_STK_SIZE,
    1 u( D' I  f; I' X
  153.                 (void*          )NULL,+ Q/ i5 q, X, f) @6 u+ E' P( Y$ e% _
  154.                 (UBaseType_t    )BEEP_TASK_PRIO,
    ( J8 h) }% R" G( P# D( s; r& K
  155.                 (TaskHandle_t*  )&BEEPTask_Handler);                                   ( q) F# M0 O* ?& o$ M! n
  156.     vTaskDelete(StartTask_Handler); //删除开始任务
    % n3 m# @2 g/ ]6 W9 Y3 R: h
  157.     taskEXIT_CRITICAL();            //退出临界区
    8 M- o, }4 X/ R, T0 _, T9 F7 c
  158. }
    $ p6 u3 a  m2 A1 X/ l$ r

  159. 1 W3 V, @" v0 P& c; ]
  160. //LED0闪烁任务函数,提示程序正在运行,且为按键扫描程序,像队列发送信息
    : r7 \1 Z& ~- T6 e6 e
  161. void LED0Toggle_task(void *pvParameters)3 z  `7 o7 B* P4 U( `3 {! Z
  162. {6 |: [% N3 Q# l4 }+ H
  163.         u8 key,i=0;
    . M9 [( X6 c" D( f: `0 H* X& ^
  164.     BaseType_t err;
    , T1 F9 T- I0 N/ h
  165.         printf("LED0Toggle Task Running!\r\n");
    : r$ r# X" V. X/ m  C" r
  166.         while(1)3 Y) @0 l, ]! W/ s
  167.         {/ {* L0 ^5 R0 q# a) F" C
  168.                 key=KEY_Scan(0);                    //扫描按键
    0 Y$ u  c; w* x
  169.         if((Key_Queue!=NULL)&&(key))           //消息队列Key_Queue创建成功,并且按键被按下* Z8 s  j: H( }4 ?' L
  170.         {$ F1 E8 O" c7 X% w! \2 Z% g
  171.             err=xQueueSend(Key_Queue,&key,10);
    ! `; b6 O3 A+ }- \3 H7 i
  172.             if(err==errQUEUE_FULL)           //发送按键值
    8 }; H; [% Q  e0 O8 M
  173.             {
    " I4 }. j/ U3 }8 D
  174.                 printf("队列Key_Queue已满,数据发送失败!\r\n");
    + s0 I1 c' w3 @
  175.             }
    5 c4 K5 \, [$ ~
  176.         }
    . r! n! G, b) J4 [: Z9 u4 s. w! e
  177.         i++;
    + ?6 ?( p; ^" V
  178.         if(i==50)
    . H; Z' R7 s: A4 w5 G& M
  179.         {
    ) l5 [" F" j' l* D' N6 A
  180.             i=0;& D( o: u+ d$ q) r; @
  181.             LED0=!LED0;9 f4 L* i3 ~# y4 u& O4 T
  182.         }0 W6 w; _: a2 I
  183.         vTaskDelay(10);   //延时10ms,也就是10个时钟节拍        ; e8 }7 ?  L+ J. |" J) s- c
  184.         }2 a, O8 Z! g: L) s1 W# r7 t! x9 _
  185. }   
    # _- {) ]. _2 K
  186. 5 d, v, M+ C  d, t3 T! E9 U
  187. //跑马灯任务函数,使用按键控制灯的方向,以及控制灯的亮灭
    . I# x& u  ^/ f" p
  188. void LED1_task(void *pvParameters)! w( Z5 L1 h3 O; ?: f
  189. {8 y2 H3 a  ~6 l
  190.          u8 key=0;
    # Z" G- `1 ?2 ?" T$ w$ G9 D  @
  191.         printf("LED1 Task Running!\r\n");  [! Q; S9 `% t) }) P7 x
  192.         / b" e6 A) c, W& U4 f, P, h' Y4 _
  193.         while(1)
    $ ?, `, I# f( l) @, C
  194.         {
      T/ N" S7 Y8 i; ~
  195.         if(Key_Queue!=NULL)
    ( p$ O: m: ~# }' |( S+ y" B6 }
  196.         {" Y) ~! ?7 K( J1 u: e+ n: }0 x
  197.             if(xQueueReceive(Key_Queue,&key,portMAX_DELAY))//请求消息Key_Queue
    / c0 |7 f2 D9 O$ ]6 m: d
  198.             {; Y. M5 u5 j  h3 L$ g
  199.                 switch(key)! e2 A7 V, b/ H' D9 N4 ^. Y
  200.                 {" ]9 }% b+ C  I; T' P6 Q& Z5 U
  201.                     case WKUP_PRES:                //KEY_UP控制流水灯方向,逆向
    0 `# R! |' z4 s
  202.                                                 LED1=1;
    ! g% E$ {2 A& A0 Q+ {0 M; Q% e6 J
  203.                                                 LED7=0;2 p& `: |6 D6 J8 K! L/ T
  204.                                                 vTaskDelay(200);
    - x$ T9 w3 K3 a2 D
  205.                                                 LED7=1;9 o' U3 d  L3 i% K
  206.                                                 LED6=0;2 A. x  t3 [$ m" j) i$ M0 f' j
  207.                                                 vTaskDelay(200);6 W) m7 |+ P" A$ A: l5 K8 ]
  208.                                                 LED6=1;
    * g$ }3 |; x7 b
  209.                                                 LED5=0;
    # I1 |& K3 b8 J& X* Z
  210.                                                 vTaskDelay(200);
    % H+ a6 S7 [  R$ r5 V
  211.                                                 LED5=1;
    + j) B- i/ V; [9 g1 E9 s% W
  212.                                                 LED4=0;
    ! r2 R; @. G; `; I) w( n& u
  213.                                                 vTaskDelay(200);
    ( |. _% ?6 s, ]! \
  214.                                                 LED4=1;
    ! _$ j/ z! \) @. ^5 \& U) G5 T
  215.                                                 LED3=0;
    " ~0 [6 x% R8 e
  216.                                                 vTaskDelay(200);
    & g! j9 {2 `( N3 \# [; Y
  217.                                                 LED3=1;( ?$ G# p5 X) x0 ]0 {; b
  218.                                                 LED2=0;
    ; _% U8 n: y9 a: Y( ]$ S
  219.                                                 vTaskDelay(200);        6 L; L+ R! u& S% P5 ?; S
  220.                                                 LED2=1;1 s2 |5 C: d0 A& W" T
  221.                                                 LED1=0;
    + q& p  B$ f. [' l; `
  222.                                                 vTaskDelay(200);" d# D* A6 \% E% \/ j, p
  223.                         break;
    9 X, W  D% ?9 s% y) }
  224.                     case KEY0_PRES:                //KEY0控制LED灯方向,顺向5 d( G+ l. i$ U& |4 ~
  225.                                                 LED7=1;
    6 l% w4 A/ k& J" e
  226.                                                 LED1=0;
    1 P$ S$ w! p+ \9 _( v! A
  227.                                                 vTaskDelay(200);+ P- u* D1 b% h5 ?% I
  228.                                                 LED1=1;
    ! a+ q  H2 @+ l' o+ g' u
  229.                                                 LED2=0;
    # z' x9 ~& r# E$ U; w
  230.                                                 vTaskDelay(200);
    3 g) D  p, {" {8 l) q" P' E% }$ Y+ S
  231.                                                 LED2=1;9 n, x1 y: D. T# O  v) l& s
  232.                                                 LED3=0;& R8 @9 t, h( L% N: g7 ]
  233.                                                 vTaskDelay(200);& s* ]) _8 c7 P8 y! T6 t7 I* o; I
  234.                                                 LED3=1;/ C2 Y6 N$ e' T) r% L
  235.                                                 LED4=0;# C& |$ q  Y% ?
  236.                                                 vTaskDelay(200);
    ' Z* }& h. Y, u: w3 o5 ^) U
  237.                                                 LED4=1;
    ' b) R! O: v0 d7 M5 P4 `
  238.                                                 LED5=0;1 y# B8 k/ Q+ ]* q: u/ ]
  239.                                                 vTaskDelay(200);. c! r! L5 a* ?6 ?/ j
  240.                                                 LED5=1;( [5 l) j4 W+ v
  241.                                                 LED6=0;* g$ x: l/ v. D% n; ]+ \
  242.                                                 vTaskDelay(200);        
    9 W. w$ E) t" L
  243.                                                 LED6=1;
    5 N1 |) V" O2 [- `+ F
  244.                                                 LED7=0;
    9 Y7 E( Y+ e* `' L/ j9 T
  245.                                                 vTaskDelay(200);
    4 k1 l+ ^1 ~. Q8 l. H# f
  246.                         break;
    - m7 z% ?( g# F
  247.                                         case KEY2_PRES:
    % S2 h, I/ L5 y2 R) J" F
  248.                                                 LED1=1;LED2=1;LED3=1;LED4=1;LED5=1;LED6=1;LED7=1;//关闭所有LED灯8 c! v" W4 X$ p# K3 g% p, [
  249.                                                 break;/ Z8 k0 G3 u' g; P# y
  250.                                         case KEY1_PRES:; _- y5 r0 X$ ^) P- K# D
  251.                                                 LED1=0;LED2=0;LED3=0;LED4=0;LED5=0;LED6=0;LED7=0;//打开所有LED灯                " o/ c; j& `2 Y
  252.                                                 break;. ~* y8 \6 }7 W3 Z, S
  253.                 }5 L* p: Y$ |: u  R7 M
  254.             }
    1 z' p, ^  ]/ t4 d; x
  255.         }
    - k: j, ^$ L8 y! e, |0 C! d
  256.                 vTaskDelay(10);      //延时10ms,也就是10个时钟节拍        
    ! i( W' G- n; o" q3 }; C
  257.         }
    , q+ ^, w7 z! f  ^+ Q# j
  258. }) h3 ^8 e. g' l  E/ Z9 H
  259. //RTC的LCD液晶显示,串口打印任务,并在LCD上进行显示/ y# z; U! T) ?: Y: [2 e" s& m
  260. void RTC_task(void *pvParameters)
    8 o+ F- e# x  N9 z' b
  261. {1 q! ~) {9 H) e# a0 b! E# |! k
  262.     printf("RTC Task Running!\r\n");
    # p9 o: E) m& O* d- l& Z
  263.         while(1)
    3 @0 e6 f% S( @( M- A
  264.     {
    9 h" q& `3 j' q9 x' v: x, q) r# Y
  265.                 Time_Display(); . Y0 T: Z0 q( A' p( L5 ]  m
  266.                 vTaskDelay(1000);//每一秒钟刷新LED屏幕,显示时间9 r& X: x. g: b$ b
  267.     }
    ; w& z$ Z8 V; g6 t5 F9 B9 \
  268. } ' z) o, P" a  A& H' m, a4 N
  269. 3 n2 k  V$ ?$ n& G$ u  K# {, F; y8 e
  270. //BEEP任务,通过串口发送数据控制蜂鸣器/ s7 `- g2 Y& {4 M
  271. void BEEP_task(void *pvParameters)3 s0 O6 a% u) T- b
  272. {
    2 Y  w4 ]' ?9 Z* f) u
  273.         u8 len=0;& ?& c: Q% G( v/ U
  274.         u8 CommandValue=COMMANDERR;  y5 C& j7 v1 F2 v. f8 z2 W# j
  275.         BaseType_t err=pdFALSE;
    $ j* R/ }9 j% Q6 u$ I/ K
  276.         & |5 n) t, m9 m% k- c! S
  277.         u8 *CommandStr;
    4 q4 ?8 i! A& v2 [
  278.         POINT_COLOR=BLUE;% R$ M/ K  a( ]) J; ^/ C
  279.     printf("BEEP Task Running!\r\n");
    8 l$ @$ w* A$ p; e% ?( ~  B
  280.         while(1)
    4 Q' O' G" J- e( P6 r( h
  281.         {0 k' t- J8 N8 K+ A- b5 O
  282.                 if(BinarySemaphore!=NULL)
    & j( [/ E& O0 w0 l9 K8 \
  283.                 {+ _% T: a- T/ v+ O' P
  284.                         err=xSemaphoreTake(BinarySemaphore,portMAX_DELAY);        //获取信号量
    ) e/ @7 r2 w7 q& \
  285.                         if(err==pdTRUE)                                                                                //获取信号量成功! T& a# w4 i" I9 s0 S& {! X" |
  286.                         {# l' |. k2 d' j! Q; [5 e% v
  287.                                 len=USART_RX_STA&0x3fff;                                                //得到此次接收到的数据长度* l* J6 I' v- U8 ^- z" _
  288.                                 CommandStr=mymalloc(len+1);                                                //申请内存
    2 q! n8 {* E6 B: B2 Q5 a
  289.                                 sprintf((char*)CommandStr,"%s",USART_RX_BUF);
    ' ^" e5 c5 P" _& E* r
  290.                                 CommandStr[len]='\0';                                                        //加上字符串结尾符号  I) L, u; Y9 A# m# e
  291.                                 LowerToCap(CommandStr,len);                                                //将字符串转换为大写                8 C. F* |% ^9 A
  292.                                 CommandValue=CommandProcess(CommandStr);                //命令解析
    , `9 O# ^% S! u1 M3 O6 }
  293.                                 if(CommandValue!=COMMANDERR)' d& J& K8 Y( \8 `1 r. o$ D1 c
  294.                                 {! q1 H0 J5 Q7 H1 Y3 F. Q
  295.                                         printf("命令为:%s\r\n",CommandStr);
    4 Y- W8 c/ G1 K. E
  296.                                         switch(CommandValue)                                                //处理命令
    8 o$ Z, c+ y7 c* Q; O: D7 M' b  l" U
  297.                                         {
    : C) j( L, i  r( _4 {) r% I8 |( w
  298.                                                 case BEEPON: , B4 ~7 ^+ b  r6 [) B9 {
  299.                                                         BEEP=0;$ \6 Q: @! T% i3 `$ D8 A
  300.                                                         break;
    / b9 d' r# H. s# o; ~
  301.                                                 case BEEPOFF:
    & C& x( D0 M: B; Y
  302.                                                         BEEP=1;5 H, q. f7 c. w
  303.                                                         break;
    ' A: {5 z# _' S
  304.                                         }, q0 ^2 q# V9 L
  305.                                 }+ ~: g3 |) |& |2 [+ E6 z# t9 e, _+ Y
  306.                                 else+ G2 s% n9 u1 j
  307.                                 {
    ) i1 R3 k5 P/ u+ v9 R. T
  308.                                         printf("无效的命令,请重新输入!!\r\n");; K. Y: N1 W) S: [# v
  309.                                 }9 E; J: M4 {1 V/ _( q% [* `
  310.                                 USART_RX_STA=0;, }3 r$ T7 p2 D% G
  311.                                 memset(USART_RX_BUF,0,USART_REC_LEN);                        //串口接收缓冲区清零; X  f! Z7 v, z. ?( d; Y' Y
  312.                                 myfree(CommandStr);                                                                //释放内存' S9 h6 |6 F, l5 N4 M' a" ]3 \
  313.                         }
    $ J9 i0 `7 D0 V6 d: U/ i
  314.                 }7 v- w! a. m$ ~/ L& H% |
  315.                 else if(err==pdFALSE)
    7 E9 C3 J  m2 s
  316.                 {* t/ {4 M" F* u
  317.                         vTaskDelay(10);      //延时10ms,也就是10个时钟节拍        % w! ?/ F4 G0 N$ D! `! b
  318.                 }) O+ U9 F, N3 X: l! u
  319.         }7 k1 l6 E+ A3 u3 c9 E6 h
  320. }              </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
  1. void Time_Display(void)
      [; Y+ d5 E9 F( F) X
  2. {
    ' m) T; R! Y- p. S2 \1 M
  3.    struct tm time;& _# ^+ c0 L/ f' J1 a1 L
  4.    char LCDTemp[100];9 f; g2 R$ w4 E" L7 }5 F
  5.    time = Time_GetCalendarTime();7 I4 E+ Z' i$ s2 s& D8 Y+ N4 h- R
  6.    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
  7.                    time.tm_mon+1, time.tm_mday,\0 m; i$ b; S" \, m/ q; o2 [, `) ^
  8.                    time.tm_hour, time.tm_min, time.tm_sec);//打印到串口( d+ ?" t6 K) Y1 \( [/ x3 V
  9.         
    / t6 E. S7 M  z9 G9 i# H
  10.         sprintf(LCDTemp,"Time: %d-%d-%d   %02d:%02d:%02d \r\n", time.tm_year, \
    ) B8 ?$ l6 c% S: n
  11.                    time.tm_mon+1, time.tm_mday,\  U7 [4 J- Z& h* @( p3 z8 j
  12.                    time.tm_hour, time.tm_min, time.tm_sec);//打印到字符串* ?! O# T# J  g9 |( C2 K
  13.         Show_Str(10,80,BLUE,YELLOW,LCDTemp,16,0);//显示字符串
    2 f% O! K' t8 M! r
  14. }
复制代码

% 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
9PCM0QN38(APUSTARAIJEEB.png
& 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
P7}XE[PQ`5X{K}EQ@Y48Z1J.png 1 p. ~0 ^8 a( T) \6 ^
6 F/ X) [$ x1 R" {; |2 _# V8 X
赞 收藏 评论0 发布时间:2022-5-5 14:46

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版