& R2 Q5 o5 d; s4 a% W. @& [
6 X. x u9 Q* t" A$ ~1 h官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。
: v, N, @7 f. d2 z/ V
& P, c4 e( i' U, a7 oxTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄
& k/ M2 p$ V4 }0 O: U- x7 c5 Q9 |vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。
' r7 _7 ^0 R% R0 A- i5 g5 m, X* I9 ~# B) T
* c. t4 y" @# q2 n1 g( q因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。
9 r4 b( I" { L4 e8 U
% Q2 H9 `" ~+ j/ \7 i t, m任务函数编写& I7 u) e% h4 t# ^
- /*
/ _2 Z" c q# B& j) l/ R - LED1翻转
. p3 q3 D+ u' u) \/ D - */6 G# }1 E) V7 b8 W
- void LED_TOG(void * pvParameters)//参数为 void * pvParameters
1 w6 e6 Q: ~+ B8 y - {
, u6 {& u7 X- w) R7 S0 j0 C - while(1)
" u4 Y: d" K! S$ \( H+ X r+ L - {
% x9 L% n2 g9 B7 O - printf("LED_TOG running\r\n");//串口打印运行信息
; j( H" S9 Q i; ^ - HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转/ H* v* ?7 @6 V3 s% N7 H5 K
- vTaskDelay(500);//延迟500ms
( M( h9 W4 X+ @8 N2 C0 g - }
( d# W7 k U# L7 |, x! L - }
复制代码2 R) u6 B/ @& Z! j+ ?
要注意的是vTaskDelay是FreeRTOS用来延时的函数。 , s z! D3 P. Z3 B
6 r$ w! b% h0 J; F. Z% y之后我们要创建任务函数的启动函数 - TaskHandle_t Start_LED_Handler;" i( x8 U4 G7 d v& n
( p0 Y& L) {/ k+ T$ d" L- void Start_LED(void * pvParameters): o4 v5 ~( Q/ o' K. x
- {
+ e# a" s+ B& \3 r% l" y7 @ - xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
1 L% Q- R8 x3 \- D1 [ B/ R - (char * )"LED_TOG",//任务名称
- B2 Y$ p, Y2 d7 i6 e" S: Y - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
6 t$ X% P0 ]% u% l5 i$ Y: ~) P - (void* ) NULL,//无返回3 u# N6 `% ` Y: ^
- (UBaseType_t ) 1,//优先级1: U. P0 o1 t) M
- (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄5 ^6 |/ X0 [2 K. |( z$ I3 |
- vTaskDelete(NULL);# ~. [3 q& X- I
- }
& C! N+ _- m1 J6 u) h$ H: L
复制代码 ! ~ d7 I; K) v
我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。 同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务) - void FreeRTOS_Init()
' ?9 t: }$ h. O4 b/ Q - {0 X: ?: A* ^7 H+ X2 m0 Y
- xTaskCreate((TaskFunction_t )Start_LED,
% A5 j* W$ f0 J8 Y5 u; }. m& { - (char * )"Start_LED",
. a/ q$ B* T$ y( T3 j4 } - (configSTACK_DEPTH_TYPE) 128,
' Q; i5 }5 \ O8 p; c5 E3 g/ g - (void* ) NULL,
# ?$ K! p/ S, u$ k+ z3 J/ ^ - (UBaseType_t ) 0,, Y A* g9 y% m7 N; ]8 J3 ?$ \
- (TaskHandle_t * )Start_LED_Handler);% T: B/ I# e- q z4 I. R6 O: M
- vTaskStartScheduler();//启动运行函数- u+ T: u! [* V! z7 L0 v4 a
- }
复制代码 : D2 _+ U- }# {3 b5 z
这样子我们在主函数中添加刚刚定义的启动启动函数 - int main(void)" K0 q7 p/ T: j( H* ]+ }5 \- S
- {
, H! g) D& X* }- T6 A$ P - /* USER CODE BEGIN 1 */ V& d5 l# i( g# o/ q; {
- 4 J* q- l$ T C4 ]
- /* USER CODE END 1 */8 }- n6 J3 T+ a M2 V/ k6 F
; g& w% l9 b ]8 X; n+ e/ Q9 h- /* MCU Configuration--------------------------------------------------------*/% J! n2 G. a7 F y
- + b- O5 x; U' [( v w) N/ {8 F
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */4 Y: m3 }' t4 m
- HAL_Init();1 g4 j3 J" ?% C% I9 X. e
4 }+ U0 ~7 P& t4 Z/ G$ @- /* USER CODE BEGIN Init */5 Q) u! W- a0 b7 s$ _3 d
- KEY_Init();
1 k* w7 V: P: T. K - /* USER CODE END Init */, U* a; J, v% E
3 ?2 O/ y: ?" X6 P# Q- /* Configure the system clock */8 h' n; e0 t" _8 O
- SystemClock_Config();
% q* Y5 G. [+ ]' W2 \2 u - , R% z7 Z$ s5 A( G) \3 U
- /* USER CODE BEGIN SysInit */+ B% A( u1 {/ ^" r
$ \& r2 G O4 v( |( Z- /* USER CODE END SysInit */
! w3 a6 i, F9 D$ H; W) b' F/ ~( m8 E - `; L! t) M) w, Z4 p: i# j: ?
- /* Initialize all configured peripherals */: l/ k. F+ H/ [% p L; F
- MX_GPIO_Init();
% c' U/ y# r& ^/ i6 D5 ] - MX_USART1_UART_Init();
+ k( B! U4 {. F& h1 N7 z1 \ g U0 [3 B - /* USER CODE BEGIN 2 */3 i' V$ m; l0 _) N$ o, G
- FreeRTOS_Init();
# O: M* I9 `0 v% D( j - /* USER CODE END 2 */
) b s! f9 R5 u* }8 V
Z2 n$ ~7 H K4 r2 R1 y- ]+ j- /* Infinite loop */6 a3 r2 M0 |; _# o7 S' J4 b+ h
- /* USER CODE BEGIN WHILE */
$ v5 ~8 X. @% W) o - while (1)2 N+ g& M' H1 s9 x( B3 V3 O
- {3 I' _1 g7 w+ p* s4 q2 F6 {
- /* USER CODE END WHILE */) m I& r! ~6 `1 r7 P
0 a: J: p |3 d' ^, i1 }- /* USER CODE BEGIN 3 *// @5 G$ E6 p. D8 ]0 B. @5 P& _
- }
& q2 M1 ~5 }( }, P) i5 [ - /* USER CODE END 3 */
6 b1 q0 m" h" | - }
: L# b# X" ~8 \0 a/ C- B
复制代码我们的代码就可以正常运行啦! + O1 N! d u' A' U5 m
我们在用上述的方法实现两个灯一起翻转还是先编辑任务函数如下,并且定义其相关句柄 - TaskHandle_t LED_TOG2_Handler;
6 M7 G$ q0 o5 Y - void LED_TOG2(void * pvParameters)//参数为 void * pvParameters$ \$ k ~5 z6 {6 @. E$ y, Y& I
- {( X7 ?5 s' c: o* V$ [
- while(1)
4 R" [& P" }; k - {
6 v+ F9 z# k! D( a% a - printf("LED_TOG running\r\n");//串口打印运行信息
7 U9 }& W( {4 i) `% T* [. W6 s - HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转4 d. @- V2 a* d3 e
- vTaskDelay(500);//延迟500ms0 _. i- v! u) _( }2 z/ z1 q
- }
! r, i( t0 ~+ R6 U: o* ~ - }
复制代码在任务启动函数中加入我们新建的任务。 - void Start_LED(void * pvParameters)) b% M+ u* l& M7 ?
- {
0 m3 R E# c3 Z. ] - xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
. @1 o9 w) ?$ a! j7 f1 i4 K+ } - (char * )"LED_TOG",//任务名称
* X& N" ]$ |* b/ f2 O& S$ o - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
4 f A2 S3 `0 f* w# r - (void* ) NULL,//无返回
2 [1 h: ]( G% Q# T- i - (UBaseType_t ) 1,//优先级1
& J$ ^1 N: V: M& O: j% x& V( P - (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄: d8 W& s1 f% r4 E: I/ [: H
- 2 u8 [9 u$ {4 C! y
- xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数
, S0 P$ T/ a* y8 Z( j - (char * )"LED_TOG2",//任务名称% A/ }. V, Q, N0 v R
- (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
$ m# E" D" z) h8 D t2 I# b* Q - (void* ) NULL,//无返回! }- T m4 I* v( M- M: @
- (UBaseType_t ) 2,//优先级2* g. }* A7 f [/ i3 b7 e
- (TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄" M8 a9 J0 b/ |+ l5 k0 D
-
3 n Z6 `! B q2 l5 f - vTaskDelete(NULL);
8 c+ p( j. S+ x( R" V8 f% G - }
复制代码再次运行我们的代码。
9 S& c, D4 T+ ]) {7 K& r
转载自: 电路小白 如有侵权请联系删除8 k! D c: b/ ]# h1 |8 I6 s
: O' r" N" h$ y! n. k7 B4 X
; U( n6 {) v$ S1 a3 X+ S
$ l8 i: G- n6 g2 X4 G) z |