7 `2 t1 M, _* S: P
, o& b6 ~6 }1 V( d官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。6 j/ E/ n ?, H9 i# c+ t
- x! Z ^& g. s8 `
xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄
7 t5 g& l' n; `% ~vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。) e4 `8 h8 y5 h0 f6 F! Q4 }
F, F# O7 R G0 h' f- A* B/ |
9 D7 ?. ~- }) V' s( b" ~' ^因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。" Z/ w2 b# b+ s5 B1 f- C
* r, ^* q1 _$ i) s2 A4 d& Q任务函数编写
/ e! H" D! t# f6 n; r, z# I- /*
* M( D, w# f V4 k" p - LED1翻转
2 V0 T7 Z/ p( K1 W' R; D - */
3 J& a8 Z2 {+ U* _ - void LED_TOG(void * pvParameters)//参数为 void * pvParameters/ k4 O0 Z4 P8 i$ ]* m
- {$ W6 @6 c4 Q H) c2 n1 m
- while(1)% Q$ x# j! p; W5 V, t- G
- {
8 `9 o7 J/ ~! Q2 b- i$ W* k S - printf("LED_TOG running\r\n");//串口打印运行信息7 V6 ~/ E" A# ~8 c
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转1 ^( O+ e. |5 o2 a4 j" `
- vTaskDelay(500);//延迟500ms
. P+ f, w& d7 n$ J6 ]' v4 [1 ] - }. P! R; R& P- y1 A
- }
复制代码
; d) K U4 f, A" i- H
要注意的是vTaskDelay是FreeRTOS用来延时的函数。
8 B5 F8 D4 h1 H& [& W
3 [! ]+ k0 @9 A之后我们要创建任务函数的启动函数 - TaskHandle_t Start_LED_Handler;
7 a/ A6 g0 A5 Z' {+ \- x/ j - 6 R( L! T' ?1 t$ r
- void Start_LED(void * pvParameters)
/ u/ F* U1 i" @# Y Q9 D - {, o2 ?0 u9 @' K$ p7 R# Y) B
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数1 ^$ b+ a3 }- R" f* p( C9 u
- (char * )"LED_TOG",//任务名称/ c. u5 u6 ~. s2 Z! C
- (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte: O( s4 d- F$ o/ ^/ O# q
- (void* ) NULL,//无返回5 k: {& s' o. ]. y8 _, ?5 H2 A- _5 W
- (UBaseType_t ) 1,//优先级1
; {5 |: b( e* I% H) t0 q- m# C7 x - (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
5 e3 s. n! e3 ?* q7 Z - vTaskDelete(NULL);
* ~" X& U. O' i! f2 H* I5 V - }8 H! M4 U: D& T1 M0 e
复制代码 1 S% i& P/ i' Q' e
我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。 同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务) - void FreeRTOS_Init()" q0 X Y' t* l4 @
- {
3 ]" h$ J$ \. j% x9 D- r: w& u. [ - xTaskCreate((TaskFunction_t )Start_LED,. i2 d) \/ K# A' N* ~5 Y0 x
- (char * )"Start_LED",
7 W8 r! J( u' d7 Q% n& Q: U - (configSTACK_DEPTH_TYPE) 128,: I) t6 U; \- X0 o+ E6 y6 I' G
- (void* ) NULL,
0 Z$ H" v" F2 V- r - (UBaseType_t ) 0,
5 ~' ^- }' b6 o* A - (TaskHandle_t * )Start_LED_Handler);1 y7 Q& W* c7 ?- X4 o- d+ `
- vTaskStartScheduler();//启动运行函数
! X7 n# b' e' d* i! x - }
复制代码 # W9 w1 x: Q% i4 [
这样子我们在主函数中添加刚刚定义的启动启动函数 - int main(void)
% g6 ]2 V+ }& b* [ - {9 ]# J" b% m6 \0 k6 {1 }- y- F
- /* USER CODE BEGIN 1 */
: @6 Z8 i/ c/ J* P7 G4 J. L# P - 2 J* E$ r/ Y* c7 w
- /* USER CODE END 1 */
4 }% x2 J0 v7 ^1 H5 Z+ E. h" | - " }) Q2 B# O4 U2 }- J
- /* MCU Configuration--------------------------------------------------------*/& E5 b5 z8 h5 o4 F h+ B& S1 l8 R
2 O H& [; j; z) u8 O9 \& f' _$ `- F& e- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */. Z/ ^4 L2 x1 a, S |2 O5 V0 |( I
- HAL_Init();
# [# F8 h1 `9 _2 w9 o4 K$ n; ^+ u - _3 S G/ [3 g& O
- /* USER CODE BEGIN Init */0 f: C Y8 |+ C+ ]4 Z
- KEY_Init(); g1 |* E6 l q/ z; \
- /* USER CODE END Init */
- P& G# ~$ J1 H8 n - . k, k8 d. z4 [, L. h5 |9 z
- /* Configure the system clock */
3 |8 ?: b/ q3 p0 c- q. n1 N - SystemClock_Config();
) P3 |' r1 d( ]( H. E
' R D3 Y4 i+ c% `, x- /* USER CODE BEGIN SysInit */" T l8 g9 y% | q8 x1 a+ m; M
- ) Y* r# r; X- b1 i
- /* USER CODE END SysInit */
2 a: v& M- x# b: a0 v+ Z - 3 e8 n9 H% _( M$ T
- /* Initialize all configured peripherals */1 X0 B6 ^4 v0 ~) N9 Z
- MX_GPIO_Init();7 W8 K' j, I8 I( C( I
- MX_USART1_UART_Init();
6 R% V9 ]6 ^, C# H. K - /* USER CODE BEGIN 2 */
1 [7 \) ~; @3 R$ E - FreeRTOS_Init();
: H; W/ ^+ c3 k$ i/ D8 J6 M - /* USER CODE END 2 */
) w) o1 K. \' G3 A6 W
) ^& N+ U6 }) \) Q/ C- /* Infinite loop *// s0 a5 Y2 p4 w
- /* USER CODE BEGIN WHILE */
, `" E$ ]4 a( M8 A# }; l, I9 m* x - while (1)
$ I% T2 B/ y3 {2 L - { P; A+ ?+ o' L; U& N# F! A
- /* USER CODE END WHILE */0 N& Q! R, w. v4 m8 ?2 R" k
1 T1 l: T: X3 o# _1 s- c! K- /* USER CODE BEGIN 3 */
; T; C! F- O. W8 Y6 O8 e/ N3 v - }' i8 V+ z. \3 @! y. v; g& O
- /* USER CODE END 3 */" I9 o% d% u0 w5 A/ H8 y
- }
& g# R, p. F* w: V
复制代码我们的代码就可以正常运行啦!
% s. \/ y0 W" U# J" w我们在用上述的方法实现两个灯一起翻转还是先编辑任务函数如下,并且定义其相关句柄 - TaskHandle_t LED_TOG2_Handler;
9 S. }& \8 k R. H( ? - void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
* s9 N/ U- D1 G. j( M g3 O( N% x - {
8 X# s3 E: k _( `- Y - while(1)
. D3 {4 n1 L: Y! h# B - {
) v9 P, a$ e! P1 a5 J) }% W - printf("LED_TOG running\r\n");//串口打印运行信息/ U( O5 v, a. w& n: b5 k; H! ~
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转
" A, c: X, e* j0 \7 y" i - vTaskDelay(500);//延迟500ms3 k& F4 d+ x! o
- }
1 p( T4 G' a% W! U! @ - }
复制代码在任务启动函数中加入我们新建的任务。 - void Start_LED(void * pvParameters)7 K7 H9 Z# z: Q. t' n
- {- J: N. b* I4 y# E8 ?& \
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数/ O" O1 g2 b2 z: N
- (char * )"LED_TOG",//任务名称
( f0 ?) W3 Z% N. D3 v! [ - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
& v# {6 O8 |2 z {# t - (void* ) NULL,//无返回
( r/ O" Y L( z) E, l - (UBaseType_t ) 1,//优先级1
4 `) Z5 @7 f: k6 Q - (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
4 v' R, I7 e0 C7 A8 @ - $ s- h5 A! u* P b4 T1 {
- xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数2 e) J" j) L2 o j0 w
- (char * )"LED_TOG2",//任务名称$ r2 G& L' i) z- [2 E
- (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte: {' S( U0 z4 C& l- y* o
- (void* ) NULL,//无返回' `- ?- G1 ]" `/ H" x
- (UBaseType_t ) 2,//优先级2
' d2 S# _+ X4 f" M( U - (TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄" [1 U% `8 V4 n( v' K, I4 e3 f
-
; Q' s. m0 o0 t/ a/ Y. Y - vTaskDelete(NULL);- O+ f1 l' T$ @9 V$ z
- }
复制代码再次运行我们的代码。 ( L* W! m, H) X! m; b! {7 q
转载自: 电路小白 如有侵权请联系删除9 S# Z0 k( a( E: |8 H6 ]
* x* ~0 C2 Z% A" A+ a
1 {' }' b9 S& B" _5 Z% g
3 y0 ~4 c3 R- {/ z% l |