! |0 @ o) O. b2 _) r# V5 t) H
官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。$ \. f: |3 I5 H" N8 c
* n/ w0 _+ S5 x2 |4 E" y
xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄. y( x! C2 Y8 o7 |5 F
vTaskDelete的函数模型如下,参数内容为函数句柄,如果为NULL则删除该任务本身。+ M9 z# E6 h% I8 u+ V6 u& k. Z q( q
# L, e0 u9 ]8 i; E+ Q9 e8 \/ _7 d/ a6 ]3 v) F6 v
因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。
, L1 g. o$ e& I1 X0 G
, a( B2 e9 x, ^- E任务函数编写
Z7 p! x9 h: Q: R8 Y! s- /*% ]' o3 W; }) z, w3 q: i' H
- LED1翻转
; h+ ?3 K4 ^5 ~# D+ Y - */9 s9 N3 N7 q3 ?" P6 {& L B
- void LED_TOG(void * pvParameters)//参数为 void * pvParameters+ D {# q4 c8 F; i
- {
# s( M" a' @/ v5 q! `0 w( [' j8 X - while(1)
+ m. i9 a" ]7 g/ m* v! ~! i - {- N& f1 T) A7 n) T* r
- printf("LED_TOG running\r\n");//串口打印运行信息- f( Y; h- u3 p7 P' V) n1 r
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转
; k! \1 u) X- b2 V - vTaskDelay(500);//延迟500ms
- P$ p# ?, A' z+ |( e - }
; K2 H- o3 Y' n6 W8 t8 e2 X' B0 ? - }
复制代码
+ Q* {+ i, ]' X1 |2 g% H3 d9 _
要注意的是vTaskDelay是FreeRTOS用来延时的函数。
i8 \7 \ x: Q) G2 `8 o; J/ J# f6 I* t4 Q; K: b: M
之后我们要创建任务函数的启动函数 - TaskHandle_t Start_LED_Handler;3 d' d4 ^' k# b# S4 x
& Q8 m( H0 z' D( E/ A: t$ `- void Start_LED(void * pvParameters)$ v4 Z% T0 `) A
- {% y" L* C' |& V
- xTaskCreate((TaskFunction_t )LED_TOG,//任务函数
$ B2 S1 R; E g2 g: ? - (char * )"LED_TOG",//任务名称
0 ?, b( @8 }1 p5 t5 B9 ^7 ] - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
! u5 z- |0 k9 [" ~1 A - (void* ) NULL,//无返回8 [0 I# U! A |8 k
- (UBaseType_t ) 1,//优先级14 n8 ?! v+ K3 U' Y8 Y. d
- (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
9 V9 S, v9 R, e6 Y/ ? - vTaskDelete(NULL);' r& X% \6 t K1 w" l
- }
: r) u' Q8 Y' F0 X& h( q. e
复制代码 7 U3 {& B A# y- M J! v9 W# F
我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。 同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务) - void FreeRTOS_Init()
! q( m! w' o5 U - {, h& L! k+ O' f
- xTaskCreate((TaskFunction_t )Start_LED,' x" |1 E$ \( @4 s; \. w
- (char * )"Start_LED",: _ s( O6 C8 L0 Q$ } S" k- ~8 _
- (configSTACK_DEPTH_TYPE) 128,2 j0 Q$ o6 R4 L" a3 g/ X+ M1 B
- (void* ) NULL,
u; o/ k& z! ]5 a, E8 @, v4 } - (UBaseType_t ) 0," O. o; L) I4 C, s9 Q6 A( W) M, ~5 r
- (TaskHandle_t * )Start_LED_Handler);
+ j4 h( N' {% F/ o3 j" r - vTaskStartScheduler();//启动运行函数! ]$ q H1 O6 `1 A2 Q: }: A
- }
复制代码
; |$ m. X: a5 \, [1 x7 L( ]( ^这样子我们在主函数中添加刚刚定义的启动启动函数 - int main(void)
H2 m/ @8 m4 M* _% C' k9 ~5 C - {
* z9 X9 S9 a* U% {$ { - /* USER CODE BEGIN 1 */- ^) {/ w. ?2 x3 a
- ; t. ]# B$ \! ?4 @$ n
- /* USER CODE END 1 */
" e6 o. E/ M/ U8 P - 3 {/ r# ~2 X. ?& e, r
- /* MCU Configuration--------------------------------------------------------*/
* h+ \6 b1 ?2 u8 I+ y6 B7 N - " V0 }6 d7 d8 x4 _
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
$ E5 @& {# A5 X) `1 X- m - HAL_Init();
# `# R8 q, j$ e* y3 A9 b$ o- U+ O
5 @0 p# ?$ U9 p5 ]7 t* t- /* USER CODE BEGIN Init */
N P |. W8 I - KEY_Init();" u1 ~( A7 d8 R
- /* USER CODE END Init */
. W) m- r( _+ Z- Z; R% U4 f - 2 v3 ?. N3 }: @ @$ P: ?
- /* Configure the system clock */
" I- q; f; I7 c: Y$ B N7 J - SystemClock_Config();0 N& K" L3 k8 `. H# |' K
4 m! Q2 D/ a2 Q8 ?" S- /* USER CODE BEGIN SysInit */- Y: w0 J& R8 I, L; ` }; X0 N9 B& q
- 1 w: _) ~8 Z9 } T7 z5 t
- /* USER CODE END SysInit */
( \- c4 N' m6 Y" Z$ U
6 ^$ }6 f9 o) y- b4 E) J* q2 y" `- /* Initialize all configured peripherals */
; G/ G4 C8 x, Y7 G - MX_GPIO_Init();' K4 P& Q9 q6 o r+ O
- MX_USART1_UART_Init();/ ~/ V( V1 z" X, H1 {7 W) |
- /* USER CODE BEGIN 2 */+ x1 A0 V1 v* K0 F) O
- FreeRTOS_Init();; J7 Q- Y" C8 s# N
- /* USER CODE END 2 */# ?" ?$ t% y: ?; i
- 8 D3 X7 q9 z* F/ u- W3 @: _
- /* Infinite loop */% r# h; ?0 i0 X( Y3 ^
- /* USER CODE BEGIN WHILE */
" G% _6 J' k8 u2 c* M/ Q4 C - while (1)2 c8 {3 r; d+ w p
- {
3 k; B o7 {) }7 l' T2 u6 q - /* USER CODE END WHILE */# W3 p. _: A' G1 O$ h$ {% W) d3 y& J* p
5 l0 K4 t' p e _- /* USER CODE BEGIN 3 */# d# Y+ E B# C& V
- }
4 M0 R+ z* A2 o0 Z7 c - /* USER CODE END 3 */
/ q q; x3 x9 C1 t1 I" } - }
' q: g! P+ y# d7 @, b
复制代码我们的代码就可以正常运行啦! ' I, a# N4 \; ]' i) T% n
我们在用上述的方法实现两个灯一起翻转还是先编辑任务函数如下,并且定义其相关句柄 - TaskHandle_t LED_TOG2_Handler;
}& j- e; `( M# r( s5 a9 N2 ? - void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
; t2 E5 a/ e, K3 ^6 \* f - {
% \! c# S# q4 A" L - while(1)2 L$ ^& @# |* _- L
- {3 ?1 {# ]+ q$ P' P, ^
- printf("LED_TOG running\r\n");//串口打印运行信息8 t _6 k, C J
- HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转8 h; ~. m9 [, _% x" [
- vTaskDelay(500);//延迟500ms/ N# `; m8 r, s8 ?2 R6 C9 k
- }' R% Y! s: l2 w- H3 {, y
- }
复制代码在任务启动函数中加入我们新建的任务。 - void Start_LED(void * pvParameters)4 l8 d) a2 U4 p! E+ a* e
- {
" j3 [) B* b3 ^) `7 [ - xTaskCreate((TaskFunction_t )LED_TOG,//任务函数* M, i- w+ T, W
- (char * )"LED_TOG",//任务名称; G! _- y1 N; J8 v& v( H w
- (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
% B' B H" N6 u6 h1 d1 B - (void* ) NULL,//无返回! i/ i$ Z) i" l" i3 w
- (UBaseType_t ) 1,//优先级1
4 s- d8 I2 Z5 N) B( h" Z - (TaskHandle_t * )LED_TOG_Handler);//任务函数句柄
! B- w! k9 X+ a4 ~+ V* t3 L -
. P& s$ z0 {; _6 { - xTaskCreate((TaskFunction_t )LED_TOG2,//任务函数
7 y$ b6 N, M! O: l3 c3 S" ]* R - (char * )"LED_TOG2",//任务名称
& S; o3 \3 b3 q$ S4 b# d' W - (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
6 s; ^5 K- m h$ N2 `& q - (void* ) NULL,//无返回
5 s5 O2 @! i9 v% k. q! M - (UBaseType_t ) 2,//优先级2) T- b* v6 f0 b9 D! ~6 v: S% N+ n. S
- (TaskHandle_t * )LED_TOG2_Handler);//任务函数句柄$ ^" `& Q0 F5 e9 |* l" i2 }
-
2 K" e$ J7 B. n7 ~ - vTaskDelete(NULL);4 h& E9 i% T9 F$ n9 [
- }
复制代码再次运行我们的代码。
& k) k8 @# H( k1 r$ e& b% {
转载自: 电路小白 如有侵权请联系删除
& {4 Y$ {# N# t* ?+ `: w
, E" b/ J% l3 B8 @2 z# C: U
/ [: R8 c, |" y6 K: ~# K4 @; M1 S4 h% e- ^
|