1 f, Z* b4 b2 G8 L
* Q5 K0 W1 b0 o: e2 G官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。/ H2 w7 l' |( c
7 ]4 H7 J9 s" X$ g: f4 V' C4 {
xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄
1 g1 o& a4 O' N% r" z) ~% ovTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。
. K, G4 ]+ {8 f9 w0 r
) H3 o! H0 V2 Y5 w8 `2 e
4 { e9 t+ h8 W) M: W因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。
9 m, R1 a- a# a- o# x5 `( z+ v+ F4 j2 z& Y/ i1 b. G: I- v% t
任务函数编写. d2 x0 d) d1 U$ p3 R7 i
- /*
( ]! \! L+ o& V% F/ |" d. _, s' v5 R+ q - LED1翻转; w, q/ F! V8 i
- */
6 G- I; N" K d p8 H5 [ g. C - void LED_TOG(void * pvParameters)//参数为 void * pvParameters+ Z4 m/ U; G4 ^* B! `
- {) g5 c9 p2 l, a8 F4 A# g8 M' f2 W1 c
- while(1)
+ X v5 @8 o6 w7 B& B) n& j6 k" ^* n1 ? - {; I% Q9 k1 y$ E/ M
- printf("LED_TOG running\r\n");//串口打印运行信息9 f( h: G' P" ~. ]: O" W
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转
7 g z3 c6 p4 P6 p8 E - vTaskDelay(500);//延迟500ms
5 t5 p; G- x G7 v# H5 f# c8 C' h& ^ - }
: N" ]+ Z- S8 g3 s! V# z3 P. B - }
复制代码6 m% h' k1 d, x
要注意的是vTaskDelay是FreeRTOS用来延时的函数。
" A; Z# M" Y. r" m
! y" \! Z2 H$ |# q; e/ [# y( y& k之后我们要创建任务函数的启动函数 - TaskHandle_t Start_LED_Handler;. v4 i$ a6 c. f! T' X4 A
- 2 y; s- @3 J# r# A
- void Start_LED(void * pvParameters)0 c; |- n I+ I/ Z) n
- {+ U; O3 U. ~8 a
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
$ U' h& I# S% X: E& }: o - (char * )"LED_TOG",//任务名称" N/ r* l2 S- r! v2 x" F) O
- (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte; m4 n# T l; \5 Z: b7 C
- (void* ) NULL,//无返回
# ?. s! I9 ~. j2 r0 U+ Z - (UBaseType_t ) 1,//优先级13 s# Q# e$ |# Y* v
- (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄/ b% {* _3 M" O5 J6 y, K
- vTaskDelete(NULL);1 ?* |4 x4 |. B
- }
" O) f. A2 Q3 s5 P& {
复制代码 " m( @ ]8 H }: p5 F) @5 G
我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。 同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务) - void FreeRTOS_Init()
: b; Z- ^$ q1 T3 w3 b7 H - {/ b9 L8 i# W0 j/ [+ z% d s
- xTaskCreate((TaskFunction_t )Start_LED,
; _0 V r3 o* B1 Y8 e8 c8 E3 W - (char * )"Start_LED",
: ?4 V. ~9 n# U+ u- c# a3 ?' ? - (configSTACK_DEPTH_TYPE) 128,4 U* ]7 {; e8 c! B5 Q
- (void* ) NULL,- }" E- P+ z* p) I: A8 l& S
- (UBaseType_t ) 0,
& K/ ?9 P, |! Q* [/ Z+ D1 Z4 e - (TaskHandle_t * )Start_LED_Handler);, W2 J% c2 ]/ |( K6 W
- vTaskStartScheduler();//启动运行函数5 o9 `, S' b; o; U
- }
复制代码 + y$ L7 u, a5 E. F1 D- q
这样子我们在主函数中添加刚刚定义的启动启动函数 - int main(void)
3 N7 Y" }; u; ~$ k' V8 q - {
* j D$ P1 u$ r) X& [ - /* USER CODE BEGIN 1 */
& A6 l h) `, r% D" u
: w, {* b7 u3 y& k* G8 J" m3 h- /* USER CODE END 1 */* p V; V3 c$ q( }/ g! a! C
- + V$ b7 Z" i( o X \7 n
- /* MCU Configuration--------------------------------------------------------*/. D; c0 Y; I4 N
1 h- a% Y" f% P- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
9 l/ g: Y6 C3 ?% ^7 D) p - HAL_Init();
5 o/ ]# k4 }6 p' s8 }" L
1 K. U* V- ^# q; [2 ?- /* USER CODE BEGIN Init */3 {1 @; c$ w1 R3 t) n) X
- KEY_Init();# K% W9 }6 h& i: ?- f" Y6 K) F7 ]
- /* USER CODE END Init */
4 }1 D1 v, m6 e1 c0 F0 t6 b0 T - * l9 e* \5 s3 n( n( i3 F# w) q
- /* Configure the system clock */
" p# w! X& @9 b$ O; Q - SystemClock_Config();, P, [; w+ v# c* }; e
1 X. L. T" ^+ I( y: l; S1 h- /* USER CODE BEGIN SysInit */; z# d A; X# z
- / z5 e1 G; d5 Q# M% u9 |9 s
- /* USER CODE END SysInit */0 }) S+ N6 X, Y
- / _: R& o0 M3 d1 k2 a) A$ j
- /* Initialize all configured peripherals */
0 B; l3 D- P9 W" z" b6 \. O - MX_GPIO_Init();2 H! q; F2 _6 U9 f
- MX_USART1_UART_Init();
2 Y& Q9 W& @: z) p [; W, X - /* USER CODE BEGIN 2 */0 Z& O9 X4 a# N2 u
- FreeRTOS_Init();! Q: N" G. T- R J5 ~( A
- /* USER CODE END 2 */
8 E+ I9 s3 B8 t5 x+ F+ O
' V$ _( ?7 d( U+ }. w5 Y! ~- /* Infinite loop */
/ H4 o _' \* d* r3 d9 N% u/ O! K - /* USER CODE BEGIN WHILE */( [4 K; p4 @8 x0 M' o
- while (1)
4 O" l) n7 I/ {) n - {( g* u$ i7 \0 f0 T
- /* USER CODE END WHILE */$ |* e0 O. i8 p% O5 x2 y$ F% u- g
- 5 k" K/ U: c2 Q f
- /* USER CODE BEGIN 3 */$ C# \% f/ A. k2 O+ a; Z8 P) F$ }
- }% U2 A' }% I1 ^7 t
- /* USER CODE END 3 */" w: q# c) e& a3 E# d. ?
- }2 i r9 \8 |6 R8 l" F7 T2 t7 ^
复制代码我们的代码就可以正常运行啦!
) x' ]: o! \* _! w H* o我们在用上述的方法实现两个灯一起翻转还是先编辑任务函数如下,并且定义其相关句柄 - TaskHandle_t LED_TOG2_Handler;
4 E$ t* L- _ [5 X* Q% h# ?! i - void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
; ~ _* \" E5 B- W% x( M$ R - {/ h. M3 e2 @8 o0 ^! d' V* O3 q4 @
- while(1)2 t6 Q! C. n9 @* f: r6 c6 n4 B7 ?
- {6 q# r* j! I5 Y/ b6 n, I) w
- printf("LED_TOG running\r\n");//串口打印运行信息
6 g5 |! C4 F% I& H' S6 w - HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转
5 n; f% F% {) G7 M - vTaskDelay(500);//延迟500ms w5 q1 B T( L% R; `( f
- }% F) B9 O2 N3 E) x* ^2 c, ?) x" } }
- }
复制代码在任务启动函数中加入我们新建的任务。 - void Start_LED(void * pvParameters)
1 J( K8 Z* U' P9 W - {
/ p& c5 Z$ Z0 E. y1 u# \ - xTaskCreate((TaskFunction_t )LED_TOG,//任务函数1 k6 [6 K7 ^6 W$ S9 h! V* ]
- (char * )"LED_TOG",//任务名称
( F, c4 l. c- R9 ^: I4 m; B# v& D - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte! n3 v3 Z" I9 Z" u
- (void* ) NULL,//无返回( G9 W3 J, N" B
- (UBaseType_t ) 1,//优先级15 b' R- O3 P1 S' U, X% |) h( R9 ?5 q8 N
- (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄: C- v0 ?- \$ _! {9 q% L8 @
-
+ d2 v3 ?+ q2 Y5 k - xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数
+ |3 }3 D/ ^; n$ W- J6 ~, P+ z. `& |. g - (char * )"LED_TOG2",//任务名称
: Q9 U2 T1 u0 t0 X3 J# E - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte. s7 `7 `- w b8 T2 Z. r
- (void* ) NULL,//无返回
, |# [8 a9 K4 D% h& c/ f) H" Q- Q5 } - (UBaseType_t ) 2,//优先级2
( F3 Q7 S9 f* S i" Z- ^ - (TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄
' a+ x+ R- \ P# C. L$ R4 ^- F - 0 X& r- w0 P6 ]/ j! A+ _
- vTaskDelete(NULL);: _; r8 G+ T! m/ ?0 }$ \$ b
- }
复制代码再次运行我们的代码。 8 S$ Y' o! ^ i$ a6 K4 \" Q$ J" v
转载自: 电路小白 如有侵权请联系删除
) e4 ?. m$ ?$ d7 q& k , G; W) P, t- I7 I
. ]: M& |& @1 v* R/ @' k4 D$ @# g, d" ?! k6 n4 U& m
|