你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F407的FreeRTOS任务的创建与删除经验分享(2)

[复制链接]
攻城狮Melo 发布时间:2023-10-19 15:54

' q5 y, l5 Z  }1 S$ H; ?
微信图片_20231019155406.png

: 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的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄
微信图片_20231019155403.png
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
微信图片_20231019155400.png
! t' s' e5 Q) y! _
因此我们创建任务的步骤是:首先定义一个启动任务,该任务是为了启动我们的真正任务,因此在调用完一遍后要用vTaskDelete 中输入NULL删除启动函数本身。- d1 K: p: E$ z9 d) Z  m* A4 n+ D
微信图片_20231019155357.png

9 {. a: C+ }% Z; H任务函数编写& G6 D8 N& e2 f7 F  Z* D: g
  1. /*+ b5 d! N- \. |; v# v+ }! t  z/ P1 O
  2. LED1翻转
    8 g( n+ m& t4 Y1 }3 D! ^
  3. */+ g2 |8 |# c: M* \3 X
  4. void LED_TOG(void * pvParameters)//参数为 void * pvParameters
    7 n' B4 h* |8 f6 k" v
  5. {
    ( u) k# O; b$ i& B8 O
  6.   while(1)
    ' z$ j) y' m( n1 [
  7.   {/ g4 g% E- t5 \7 _% A+ |
  8.     printf("LED_TOG running\r\n");//串口打印运行信息
    0 _$ D  J0 j  P- C
  9.     HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED1翻转
    3 p) g# G1 |) n" l8 Z, l
  10.     vTaskDelay(500);//延迟500ms
    ) [6 v: x  _- u# M: \
  11.   }: U" j  M  W$ C1 w
  12. }
复制代码


# t9 I9 g6 \$ m+ o9 J6 y- J

要注意的是vTaskDelay是FreeRTOS用来延时的函数。


1 q7 ?9 V5 t; e
微信图片_20231019155354.png
. F3 S# e$ x- @& C: F$ H  _- Y

之后我们要创建任务函数的启动函数

  1. TaskHandle_t Start_LED_Handler;; L! S8 B; c/ q1 x2 b

  2. & B; t9 ~+ z9 M/ l% p
  3. void Start_LED(void * pvParameters)
      o3 o( \1 ]# I' j* R" ^# e
  4. {/ }4 l( c2 g3 C5 B1 @5 t
  5.   xTaskCreate((TaskFunction_t        )LED_TOG,//任务函数
    . ?) h' t7 t. v; x; X
  6.               (char *                )"LED_TOG",//任务名称
    ! m/ s8 [' O( v8 {! \- |% p
  7.               (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
    , ?8 X, V- C( S2 p6 G) r4 x5 [2 f
  8.               (void*                 ) NULL,//无返回7 z, n$ R2 j0 ?$ _2 _
  9.               (UBaseType_t          ) 1,//优先级11 I9 m0 m. {9 W6 L. V# |
  10.               (TaskHandle_t *        )LED_TOG_Handler);//任务函数句柄
    " i9 [7 s8 V5 A# W1 n
  11.   vTaskDelete(NULL);1 |: d; C! [1 V8 s) l
  12. }
    3 t9 B6 @8 u' ~( ^4 s& s
复制代码

5 `7 S8 [+ ~; b/ p: b: ^

我们创建启动任务的函数,将任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄,填入vTaskCreate函数中,其中每个参数都使用了强制类型转换防止出现错误。

同样的方法,我们创建启动 启动函数的任务(有点绕口因为启动函数本身是一个任务)

  1. void FreeRTOS_Init()1 O9 e3 e5 G2 s: |, d
  2. {
    ! F9 l2 g% r" X9 l" b1 B# y- S$ G
  3.   xTaskCreate((TaskFunction_t        )Start_LED,3 m( R) H7 J! x1 L
  4.               (char *                )"Start_LED",/ J1 Y1 J1 d5 X& }% O
  5.               (configSTACK_DEPTH_TYPE) 128,
    / V) n: C; u5 e
  6.               (void*                 ) NULL,$ @, I8 {( ?" ]( A$ [
  7.               (UBaseType_t          ) 0,( x6 x3 Y- l" b" _
  8.               (TaskHandle_t *        )Start_LED_Handler);
    8 ~# `, h8 O0 ?1 U
  9.   vTaskStartScheduler();//启动运行函数9 q! `3 x  G' s! a( m
  10. }
复制代码

! C& S7 Z9 Z! R5 _* M/ Q8 ^

这样子我们在主函数中添加刚刚定义的启动启动函数

  1. int main(void)
    ! w6 A; L/ M& W6 y/ p& L. u- J% o
  2. {
    9 @6 @5 o% l, V+ K; P% U, T
  3.   /* USER CODE BEGIN 1 */" P- P' ^  r. f9 Z8 z

  4. 8 T; x: A( W% |- E: Q. ~
  5.   /* USER CODE END 1 */% K8 Q0 s5 b8 v' ^/ n
  6. 5 g4 s4 h& v/ R5 V; h8 {# W
  7.   /* MCU Configuration--------------------------------------------------------*/+ N4 G9 P( C8 K1 ]# S
  8. 7 c0 x; p' y+ a" n0 N, v: N6 q& _
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    ; |+ w- U& F$ Z2 \8 l& |5 p& I
  10.   HAL_Init();( U' L' G4 j' A" o

  11. 7 g2 x: e9 \: P+ p
  12.   /* USER CODE BEGIN Init */; u9 z; I* |4 i
  13.   KEY_Init();
    7 e" |3 G, w, _4 d
  14.   /* USER CODE END Init */
    4 e% |" q  i; n2 z1 @6 z

  15. + R# e9 v  h! z, L1 _: m
  16.   /* Configure the system clock */
    " `/ w) y9 X  O7 l( u
  17.   SystemClock_Config();
    6 o1 T% z- C/ w" c

  18. # `% [1 _. H3 P: H+ Z
  19.   /* USER CODE BEGIN SysInit */0 y" N+ o" \& H4 |( n+ A* A
  20. ( \/ e6 z' I1 W, R7 W
  21.   /* USER CODE END SysInit */; x) H+ m; d, b! ]3 v" z3 ?. y' A, [

  22. 1 x- a5 s" q5 z
  23.   /* Initialize all configured peripherals */
    % J& Q* T4 [0 ~" ~& l! b, v% c
  24.   MX_GPIO_Init();% [- Y' c+ z5 Y: c
  25.   MX_USART1_UART_Init();4 G. ^0 D3 k8 D- S/ s' T
  26.   /* USER CODE BEGIN 2 */! A. Y5 v% k  o1 M) q" y
  27.   FreeRTOS_Init();
      _+ u# F8 ]  V- U( ^" u. w# Z* b
  28.   /* USER CODE END 2 */4 o7 _9 j( {) |3 Y

  29. 1 k- n0 i: e, ~; O9 Q, {
  30.   /* Infinite loop */1 e* k& }; a5 Y7 s
  31.   /* USER CODE BEGIN WHILE */
    ! \5 K4 ^& J  w3 R- U+ u  [  i3 u
  32.   while (1)8 {2 x( M  f* Z  t$ @
  33.   {
      f: m. ^( G" V( \" z9 e
  34.     /* USER CODE END WHILE *// g' ?9 u& Q. P$ _
  35. - T/ `2 o- a. W7 ~; M
  36.     /* USER CODE BEGIN 3 */
    ) T; q" a2 v; T+ ^7 |
  37.   }" p( d( m8 k) {- W9 u
  38.   /* USER CODE END 3 */
    & m) {8 f  H/ j9 U6 s. _* W& N) E
  39. }
    ; K5 q2 i5 ~3 l0 c! l$ _) }: a
复制代码

我们的代码就可以正常运行啦!

+ w: t3 p4 m: n9 H8 `! N
我们在用上述的方法实现两个灯一起翻转

还是先编辑任务函数如下,并且定义其相关句柄

  1. TaskHandle_t LED_TOG2_Handler;
    0 x& }7 Y& H7 ?! F2 r$ f. h
  2. void LED_TOG2(void * pvParameters)//参数为 void * pvParameters
    0 m8 a/ x& o( q
  3. {% p. D! D& A9 m* _* u2 w) K3 |  v! h
  4.   while(1)/ B: A1 O: k8 j6 w/ r) u; u
  5.   {9 A7 s+ ^4 `3 n( ~5 f2 d
  6.     printf("LED_TOG running\r\n");//串口打印运行信息9 f( C5 W; r2 U; r7 j$ L' i' X3 y! v
  7.     HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);//LED0翻转
    ! d/ J9 o  i2 [4 Z1 @4 w6 E
  8.     vTaskDelay(500);//延迟500ms, n/ u0 m! T+ l0 Q! p" }/ j) o
  9.   }
    * b5 p2 m4 r. i2 _0 \+ h+ }3 r6 ~, t
  10. }
复制代码

在任务启动函数中加入我们新建的任务。

  1. void Start_LED(void * pvParameters)6 Y2 O7 m! D4 J; f
  2. {; c1 l) d. }7 s5 D5 t
  3.   xTaskCreate((TaskFunction_t        )LED_TOG,//任务函数
    : f3 Y& _- o, B: S& W$ n# B
  4.               (char *                )"LED_TOG",//任务名称
    : v4 r; O/ s8 b( D# S
  5.               (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte
    ( w% _8 i* [5 K
  6.               (void*                 ) NULL,//无返回
    1 e/ W) ]* v. O* T
  7.               (UBaseType_t          ) 1,//优先级1
    ! h( k- a) X0 u* h
  8.               (TaskHandle_t *        )LED_TOG_Handler);//任务函数句柄% x, S. V- S. n6 a3 Q! w
  9.   * k" D7 b0 y9 N
  10.    xTaskCreate((TaskFunction_t        )LED_TOG2,//任务函数
    2 q; q! ]# Y- B, P" S
  11.               (char *                )"LED_TOG2",//任务名称
    3 g; a3 e5 {1 e( @: B
  12.               (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte" Z% o$ `& @' `0 o  u% e
  13.               (void*                 ) NULL,//无返回
    , H5 X% b; r3 R% n8 w
  14.               (UBaseType_t          ) 2,//优先级2. M% E$ Z- V8 T1 T2 M2 ]/ U! D, q
  15.               (TaskHandle_t *        )LED_TOG2_Handler);//任务函数句柄# r0 O6 k$ k6 m
  16.               / @' k  [6 V9 B- I
  17.   vTaskDelete(NULL);
    9 }- R5 v6 x( H- }# _
  18. }
复制代码

再次运行我们的代码。


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
收藏 评论0 发布时间:2023-10-19 15:54

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版