' q5 y, l5 Z }1 S$ H; ?
: O/ b2 S* Q& c6 J. y官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。( V/ J% \0 }: O3 }' {3 b2 R4 W6 g4 i& B
5 Y! o* A/ c9 I9 X' ~4 V; Q) C
xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄9 [6 o& j$ i5 m" z b* a
vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。+ E; F! |' w a" N
0 h4 u7 \/ f$ Z; g: f$ \* A9 Y
! t' s' e5 Q) y! _
因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。- d1 K: p: E$ z9 d) Z m* A4 n+ D
9 {. a: C+ }% Z; H任务函数编写& G6 D8 N& e2 f7 F Z* D: g
- /*+ b5 d! N- \. |; v# v+ }! t z/ P1 O
- LED1翻转
8 g( n+ m& t4 Y1 }3 D! ^ - */+ g2 |8 |# c: M* \3 X
- void LED_TOG(void * pvParameters)//参数为 void * pvParameters
7 n' B4 h* |8 f6 k" v - {
( u) k# O; b$ i& B8 O - while(1)
' z$ j) y' m( n1 [ - {/ g4 g% E- t5 \7 _% A+ |
- printf("LED_TOG running\r\n");//串口打印运行信息
0 _$ D J0 j P- C - HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转
3 p) g# G1 |) n" l8 Z, l - vTaskDelay(500);//延迟500ms
) [6 v: x _- u# M: \ - }: U" j M W$ C1 w
- }
复制代码
# t9 I9 g6 \$ m+ o9 J6 y- J
要注意的是vTaskDelay是FreeRTOS用来延时的函数。
1 q7 ?9 V5 t; e. F3 S# e$ x- @& C: F$ H _- Y
之后我们要创建任务函数的启动函数 - TaskHandle_t Start_LED_Handler;; L! S8 B; c/ q1 x2 b
& B; t9 ~+ z9 M/ l% p- void Start_LED(void * pvParameters)
o3 o( \1 ]# I' j* R" ^# e - {/ }4 l( c2 g3 C5 B1 @5 t
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
. ?) h' t7 t. v; x; X - (char * )"LED_TOG",//任务名称
! m/ s8 [' O( v8 {! \- |% p - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
, ?8 X, V- C( S2 p6 G) r4 x5 [2 f - (void* ) NULL,//无返回7 z, n$ R2 j0 ?$ _2 _
- (UBaseType_t ) 1,//优先级11 I9 m0 m. {9 W6 L. V# |
- (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
" i9 [7 s8 V5 A# W1 n - vTaskDelete(NULL);1 |: d; C! [1 V8 s) l
- }
3 t9 B6 @8 u' ~( ^4 s& s
复制代码
5 `7 S8 [+ ~; b/ p: b: ^我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。 同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务) - void FreeRTOS_Init()1 O9 e3 e5 G2 s: |, d
- {
! F9 l2 g% r" X9 l" b1 B# y- S$ G - xTaskCreate((TaskFunction_t )Start_LED,3 m( R) H7 J! x1 L
- (char * )"Start_LED",/ J1 Y1 J1 d5 X& }% O
- (configSTACK_DEPTH_TYPE) 128,
/ V) n: C; u5 e - (void* ) NULL,$ @, I8 {( ?" ]( A$ [
- (UBaseType_t ) 0,( x6 x3 Y- l" b" _
- (TaskHandle_t * )Start_LED_Handler);
8 ~# `, h8 O0 ?1 U - vTaskStartScheduler();//启动运行函数9 q! `3 x G' s! a( m
- }
复制代码
! C& S7 Z9 Z! R5 _* M/ Q8 ^这样子我们在主函数中添加刚刚定义的启动启动函数 - int main(void)
! w6 A; L/ M& W6 y/ p& L. u- J% o - {
9 @6 @5 o% l, V+ K; P% U, T - /* USER CODE BEGIN 1 */" P- P' ^ r. f9 Z8 z
8 T; x: A( W% |- E: Q. ~- /* USER CODE END 1 */% K8 Q0 s5 b8 v' ^/ n
- 5 g4 s4 h& v/ R5 V; h8 {# W
- /* MCU Configuration--------------------------------------------------------*/+ N4 G9 P( C8 K1 ]# S
- 7 c0 x; p' y+ a" n0 N, v: N6 q& _
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
; |+ w- U& F$ Z2 \8 l& |5 p& I - HAL_Init();( U' L' G4 j' A" o
7 g2 x: e9 \: P+ p- /* USER CODE BEGIN Init */; u9 z; I* |4 i
- KEY_Init();
7 e" |3 G, w, _4 d - /* USER CODE END Init */
4 e% |" q i; n2 z1 @6 z
+ R# e9 v h! z, L1 _: m- /* Configure the system clock */
" `/ w) y9 X O7 l( u - SystemClock_Config();
6 o1 T% z- C/ w" c
# `% [1 _. H3 P: H+ Z- /* USER CODE BEGIN SysInit */0 y" N+ o" \& H4 |( n+ A* A
- ( \/ e6 z' I1 W, R7 W
- /* USER CODE END SysInit */; x) H+ m; d, b! ]3 v" z3 ?. y' A, [
1 x- a5 s" q5 z- /* Initialize all configured peripherals */
% J& Q* T4 [0 ~" ~& l! b, v% c - MX_GPIO_Init();% [- Y' c+ z5 Y: c
- MX_USART1_UART_Init();4 G. ^0 D3 k8 D- S/ s' T
- /* USER CODE BEGIN 2 */! A. Y5 v% k o1 M) q" y
- FreeRTOS_Init();
_+ u# F8 ] V- U( ^" u. w# Z* b - /* USER CODE END 2 */4 o7 _9 j( {) |3 Y
1 k- n0 i: e, ~; O9 Q, {- /* Infinite loop */1 e* k& }; a5 Y7 s
- /* USER CODE BEGIN WHILE */
! \5 K4 ^& J w3 R- U+ u [ i3 u - while (1)8 {2 x( M f* Z t$ @
- {
f: m. ^( G" V( \" z9 e - /* USER CODE END WHILE *// g' ?9 u& Q. P$ _
- - T/ `2 o- a. W7 ~; M
- /* USER CODE BEGIN 3 */
) T; q" a2 v; T+ ^7 | - }" p( d( m8 k) {- W9 u
- /* USER CODE END 3 */
& m) {8 f H/ j9 U6 s. _* W& N) E - }
; K5 q2 i5 ~3 l0 c! l$ _) }: a
复制代码我们的代码就可以正常运行啦! + w: t3 p4 m: n9 H8 `! N
我们在用上述的方法实现两个灯一起翻转还是先编辑任务函数如下,并且定义其相关句柄 - TaskHandle_t LED_TOG2_Handler;
0 x& }7 Y& H7 ?! F2 r$ f. h - void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
0 m8 a/ x& o( q - {% p. D! D& A9 m* _* u2 w) K3 | v! h
- while(1)/ B: A1 O: k8 j6 w/ r) u; u
- {9 A7 s+ ^4 `3 n( ~5 f2 d
- printf("LED_TOG running\r\n");//串口打印运行信息9 f( C5 W; r2 U; r7 j$ L' i' X3 y! v
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转
! d/ J9 o i2 [4 Z1 @4 w6 E - vTaskDelay(500);//延迟500ms, n/ u0 m! T+ l0 Q! p" }/ j) o
- }
* b5 p2 m4 r. i2 _0 \+ h+ }3 r6 ~, t - }
复制代码在任务启动函数中加入我们新建的任务。 - void Start_LED(void * pvParameters)6 Y2 O7 m! D4 J; f
- {; c1 l) d. }7 s5 D5 t
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
: f3 Y& _- o, B: S& W$ n# B - (char * )"LED_TOG",//任务名称
: v4 r; O/ s8 b( D# S - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
( w% _8 i* [5 K - (void* ) NULL,//无返回
1 e/ W) ]* v. O* T - (UBaseType_t ) 1,//优先级1
! h( k- a) X0 u* h - (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄% x, S. V- S. n6 a3 Q! w
- * k" D7 b0 y9 N
- xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数
2 q; q! ]# Y- B, P" S - (char * )"LED_TOG2",//任务名称
3 g; a3 e5 {1 e( @: B - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte" Z% o$ `& @' `0 o u% e
- (void* ) NULL,//无返回
, H5 X% b; r3 R% n8 w - (UBaseType_t ) 2,//优先级2. M% E$ Z- V8 T1 T2 M2 ]/ U! D, q
- (TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄# r0 O6 k$ k6 m
- / @' k [6 V9 B- I
- vTaskDelete(NULL);
9 }- R5 v6 x( H- }# _ - }
复制代码再次运行我们的代码。
5 `7 g. S" O0 i. O& j* U6 ?
转载自: 电路小白 如有侵权请联系删除
; j" e* C3 `7 X6 \8 h! S
# A/ v. D' k$ m: k! C* A3 n# K/ D
- a0 }& [4 n# R) D6 `# A
3 D# X& ]2 I3 Q7 ~! i: a |