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

基于STM32的FreeRTOS学习之中断测试实验(五)

[复制链接]
STMCU小助手 发布时间:2022-11-17 16:47
1. 实验目的
4 m0 v. t* F% a  n: ^( G% tFreeRTOS可以屏蔽优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断,不会屏蔽高于其的中断。本次实验就是验证这个说法。本实验使用两个定时器,一个优先级为4,另一个为5,两个定时器每隔1s通过串口输出一串字符串。然后在某个任务中关闭中断一段时间,查看输出情况。, |# ~. z, y! E

1 W! Z4 S, i% O$ S! j" ^2. 实验设计
7 h6 g% y9 L) _/ ^- B, f' S
本实验设计了两个任务start_task()和interrupt_task(),这两个任务的任务功能分别为:& c# _* o6 H& R7 e  M
start_task():创建另外一个任务;
6 W+ _6 K  y: K% M0 O* W, Einterrupt_task():中断测试任务,任务会调用FreeRTOS的中断函数portDISABLE_INTERRUPTS()来将中断关闭一段时间。( Q! J, k& t) j7 c8 f
$ A0 t/ V/ Q  c+ g+ F
3. 硬件. k% c3 [0 w: z5 Y
3.1 正点原子战舰v3开发板(其他板子应该也可以,主要涉及USART,TIM3,TIM5,LED);
( c; z% K* e3 Q2 \, w6 Y3.2 JLINK仿真器。4 B; @' ^7 b, N  I' F8 p: v

0 c& L  X9 x$ T; ^9 \( r4. 代码解读
* ?5 H1 H9 \/ S4.1 timer.h和timer.c
# m3 D+ `3 y" j- }% t: I因为用到2个定时器,这里选择TIM3和TIM5,其定时器初始化和中断函数如下:
: f9 H) ?3 s; _) X# j' U; [- P; b7 S9 b& K
  1. #ifndef __TIMER_H  R6 g* B( `5 P3 ^1 P; y2 a& }
  2. #define __TIMER_H* S. |5 v5 q' v* b
  3. #include "stm32f10x.h" ( k) D7 e0 s5 \  {
  4. void TIM3_Int_Init(u16 arr,u16 psc);   // 优先级4,认为高优先级
    # F1 I+ }, T. V! e
  5. void TIM5_Int_Init(u16 arr,u16 psc);   // 优先级5, 认为低优先级
    6 l! b8 }2 N# o7 j, d
  6. #endif
复制代码
  1. #include "timer.h"
    7 ]  A3 V* e! r+ w' r& H7 ]
  2. #include "usart.h"          : l* z5 i% {1 f% q+ t3 ]+ {
  3. // 函数名称:通用定时器3中断初始化
    ; q0 O& u" p* N. K5 l- U( [! J
  4. // 入口参数:arr:自动重装值;psc:时钟预分频数& I; s; |5 X/ {2 g+ j* G; S7 \
  5. void TIM3_Int_Init(u16 arr,u16 psc)
    7 H2 n0 N/ Z5 ^1 t8 I: Q5 q- I, P
  6. {# ~; D* y, v$ u6 n! `& w5 }
  7.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;2 _: f. z- N: j) q3 h
  8.     NVIC_InitTypeDef NVIC_InitStruct;& X! \* O6 }! T0 W3 }
  9.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);         
    $ r/ a5 J( e  R! U5 [% b3 x2 V) l; Z
  10.         // 定时器TIM3初始化0 i0 a$ r7 J. q0 R- K2 h9 F
  11.         TIM_TimeBaseStruct.TIM_Period = arr;               ' A% L) r( n1 I  d
  12.         TIM_TimeBaseStruct.TIM_Prescaler =psc; / C9 C/ \% {- U5 J- }
  13.         TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1; 2 `2 G, v/ l7 C/ i
  14.         TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;  
    8 @* ^5 h2 `8 K$ s
  15.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);
    & o5 l% L8 [7 k) _7 K7 Q
  16.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); / c) K! P/ |6 K( Z7 s" s* W, ^
  17.         // 中断优先级NVIC设置6 c2 H, ^" H% U3 t: f7 [
  18.         NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
    ' ?. [5 v, l2 m7 O
  19.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 4;  
    ! l7 k. Y# ^8 v% ~8 @/ @9 z, D8 d
  20.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;  " B, Z% }6 L2 S2 m% j% \
  21.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    + P. g% q1 Z1 ]7 y# U; I. Y
  22.         NVIC_Init(&NVIC_InitStruct);  " @$ m) z; V  v( p& j. J0 E2 B
  23.         TIM_Cmd(TIM3, ENABLE);                                   
    ( `* B$ c. i8 p' W/ j5 s
  24. }
      R: o% n# A8 i0 b( P% \% B
  25. // 函数名称:通用定时器5中断初始化
    ; p$ D& I- E8 l" M/ }& c
  26. // 入口参数:arr:自动重装值;psc:时钟预分频数
    6 D6 M8 K2 t) Q* j! u2 g' ~
  27. void TIM5_Int_Init(u16 arr,u16 psc)* s+ B$ j2 @# O' C2 b" K8 O7 E
  28. {
    0 }' Z2 f  |+ i1 D1 W# \3 o& A
  29.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;% ?4 v: T! L6 e; }% O! c9 Q
  30.         NVIC_InitTypeDef NVIC_InitStruct;/ w6 J8 J# y) K! ~# D2 O: F
  31.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);         ' Q+ D  R7 q0 r4 f7 U
  32.         // 定时器TIM5初始化1 ^- x& I& `- g
  33.         TIM_TimeBaseStruct.TIM_Period = arr;                         6 ?, Z" B8 c5 |
  34.         TIM_TimeBaseStruct.TIM_Prescaler =psc;                                 + N: u( J6 T$ R5 j# _
  35.         TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    4 k/ L0 w" p1 \6 P, z$ _
  36.         TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; 0 g8 q' B$ v( P% J# z9 ]7 e
  37.         TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStruct);                        
    & n# z+ [( ]' p( D5 N' s$ v3 ?4 w
  38.         TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE );                                 7 o+ P, }( V1 c6 I
  39.         // 中断优先级NVIC设置1 N/ S. b( x+ p5 c
  40.         NVIC_InitStruct.NVIC_IRQChannel = TIM5_IRQn;                  
    ' _4 U: i1 d4 S. v  {/ L
  41.         NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 5;         
    * Q3 L3 [: _: B$ r* A$ ?, p
  42.         NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;          4 f- Z5 t7 W5 s3 r+ c8 ?/ P7 \
  43.         NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;                 
    - O) Q2 w" J, I0 X6 d0 B9 q( ^
  44.         NVIC_Init(&NVIC_InitStruct);                                                  
    0 h6 r: @. O2 L& x9 I1 {/ k/ x
  45.         TIM_Cmd(TIM5, ENABLE);                                                                                   " l8 Y+ r! b- v; a5 U
  46. }/ k0 ^( r  Y% G) |1 k  t
  47. // 函数名称:定时器3中断服务函数- }1 m  M4 P! O( p6 L5 u( o/ ?
  48. void TIM3_IRQHandler(void)
    ; \1 m( `3 D% w# ~# K
  49. {
    6 k% P7 m# N. P& y0 o7 l0 L2 b
  50.         if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) / H- e: W# P$ W* z* m
  51.         {        printf("TIM3输出.......\r\n"); }
    # @# a$ p8 j" @
  52.         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  5 B5 R/ [  v/ i( {
  53. }
    3 X2 ^! ?" \+ d8 e6 {0 W
  54. // 函数名称:定时器5中断服务函数) F* F( h% \& h8 {! F8 i
  55. void TIM5_IRQHandler(void)+ V5 a+ h' E' r3 Y1 e
  56. {, G  p; B* a' ~% i4 L4 m
  57.         if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET)
    - r6 u9 \# e- P
  58.         {        printf("TIM5输出.......\r\n");  }7 j- ^5 T& @3 G$ c
  59.         TIM_ClearITPendingBit(TIM5,TIM_IT_Update); ) j' l, T- P* x& c8 p- p" E* l) D
  60. }8 T7 g& ?0 Z! U% [% E
复制代码

3 t; E$ O! o6 H$ ]7 x4.2 main.c文件代码
$ r% _- P" U" a2 p- }! T& m* I5 f
  1. #include "sys.h"
    7 `* A! z1 `7 A$ M) V! s: i& u3 A
  2. #include "delay.h"
    " v6 U0 {. R+ d& H7 d2 ~; Q4 l8 L
  3. #include "usart.h"
    ( A4 D8 R6 W6 ~! C& H
  4. #include "led.h"
    8 g1 R4 Z+ d( W. g- K6 [1 F) Z
  5. #include "timer.h"
    8 }9 G) |7 ]$ H+ @
  6. #include "FreeRTOS.h"
    7 L; A! [5 j7 m9 u9 w" `; j
  7. #include "task.h"
    ; K: y2 v3 U; k. B6 f* T4 T
  8. // 设计第一个任务start_task()
    + B4 K# q( e/ X: |7 y
  9. #define START_TASK_PRIO                          1         // 任务优先级; i. J/ e. x* y4 z% `3 ]; L
  10. #define START_STK_SIZE                           256       // 任务堆栈大小        " O# L' D) O% M9 W* J' [: E3 I
  11. TaskHandle_t StartTask_Handler;             // 任务句柄
    : w" `2 B1 W+ ~! ?# F' l
  12. void start_task(void *pvParameters);        // 任务函数
    & a2 [2 y# E( t( a5 I' s2 r
  13. // 设计第二个任务interrupt_task()
    * {# A% W' A6 c4 C) n0 b
  14. #define INTERRUPT_TASK_PRIO                  2         // 任务优先级
    + y# l$ X4 `  C( N/ U7 {$ I
  15. #define INTERRUPT_STK_SIZE                   256       // 任务堆栈大小
    + `; W. k7 K% }5 x
  16. TaskHandle_t INTERRUPTTask_Handler;         // 任务句柄
    " {1 S0 p) @- |. `( q
  17. void interrupt_task(void *p_arg);           // 任务函数
    ( ]7 m- A' v4 u0 ^3 T

  18. 5 s$ G8 c- o- q. w  R9 ^  x. g
  19. // 主函数) a7 E* E) ?* e( }/ c
  20. int main(void)  ~' `3 g" d* B6 ~$ F
  21. {, _; m$ ]6 {2 V& U
  22.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);    // 设置系统中断优先级分组4         1 H! F( |" @( `+ v" D. v% g- _
  23.         delay_init();                                                           // 延时函数初始化         4 z6 Q3 `  a% D4 w3 l2 x
  24.         uart_init(115200);                                                       // 初始化串口4 j! A, E! r0 u7 O8 @* g4 b
  25.         LED_Init();                                                                         // 初始化LED
    - }8 n6 Z0 R+ B$ V/ J! O, t
  26.         TIM3_Int_Init(10000-1,7200-1);                               // 初始化定时器3,定时器周期1S9 O% u) r, r. ?, j; f* n0 O& C
  27.         TIM5_Int_Init(10000-1,7200-1);                               // 初始化定时器5,定时器周期1S/ }8 Q/ W3 F. c! n1 f. k
  28.         // 创建开始任务
    + A! d* Z  h  p7 b% c# P
  29.         xTaskCreate(        (TaskFunction_t )start_task,            // 任务函数
    3 p5 X- X5 D: y* i7 z/ W& x
  30.                                         (const char*    )"start_task",          // 任务名称
    1 ]+ d# h6 }+ W4 C
  31.                                         (uint16_t       )START_STK_SIZE,        // 任务堆栈大小& h! Y% q% }3 G" @7 N  z  w* D4 J
  32.                                     (void*          )NULL,                  // 传递给任务函数的参数
    1 k2 t9 f8 P7 h. g. A! m  E- e
  33.                         (UBaseType_t    )START_TASK_PRIO,       // 任务优先级; |; {3 J. z5 W6 `
  34.                         (TaskHandle_t*  )&StartTask_Handler);   // 任务句柄              - k$ P! g" t% _. K2 L0 j$ z
  35.         vTaskStartScheduler();                                      // 开启任务调度
    ( w1 W+ B5 @4 L' c; S" R# q0 ]* {
  36. }
    - P6 r5 s9 c: |  ~2 a) _1 Z

  37. 9 a! [+ L& U4 `4 a
  38. // 主函数里创建了第一个任务函数——开始任务6 |8 ~1 q6 H, J8 F5 N: {$ x
  39. void start_task(void *pvParameters)
    5 s% m/ M" _0 N# c7 [  h
  40. {. y$ e# G5 @, _6 _3 m
  41.         taskENTER_CRITICAL();                                       // 进入临界区- ]4 q8 q2 S( v/ s- ?' e! i
  42.         // 创建中断测试任务,用来执行开关中断操作
    + {1 B0 {/ @" a
  43.         xTaskCreate(        (TaskFunction_t )interrupt_task,                  // 任务函数4 `+ v6 a( ^, G" n
  44.                         (const char*    )"interrupt_task",                         // 任务名称
    ( j/ C  y4 c* |: j9 y% c* T
  45.                         (uint16_t       )INTERRUPT_STK_SIZE,                // 任务堆栈大小- i8 T4 A& ^9 P
  46.                         (void*          )NULL,                                                // 传递给任务函数的参数$ `+ Z/ f7 ?8 H+ j
  47.                         (UBaseType_t    )INTERRUPT_TASK_PRIO,                // 任务优先级) d7 b1 |$ i! ?. Q, B) F
  48.                            (TaskHandle_t*  )&INTERRUPTTask_Handler);         // 任务句柄3 f  [; v, E/ W6 n9 S, h
  49.         vTaskDelete(StartTask_Handler);                             // 删除开始任务
    1 X3 d$ J# s0 m( o2 `
  50.         taskEXIT_CRITICAL();                                        // 退出临界区, x; f. s+ g0 t' _' ]( s, p1 w
  51. }
    ) t2 Q" I  M; j4 ]" @
  52. 0 @% X5 m0 s! X) X
  53. // 开始任务里创建了第二个任务函数——中断测试任务 / `" f! p, i) T
  54. void interrupt_task(void *pvParameters)2 C9 n  F! A# k* n4 T3 y4 ~
  55. {: \  E! z; {2 u# i8 ?' Q+ x
  56.         static u32 total_num=0;' C% W- o9 ^4 n* h( R' _8 g
  57.         while(1)
    ) }0 }1 n9 f; p, U1 Y
  58.         {
    ; [( A1 w% g. P1 m! K. l, u
  59.                 total_num+=1;
    3 Q0 @  f8 l8 z) f' G9 n% P: L! a
  60.                 if(total_num==5)                        
    5 @. n& x- [( y  _: u/ n. B6 e
  61.                 {
      B9 C8 ^5 z0 l" A
  62.                         printf("关闭中断.............\r\n");
    4 a" a1 D; a7 H. w$ X7 u' W
  63.                         portDISABLE_INTERRUPTS();                                      // 关闭中断
    # h/ S, _* {2 Y) u+ o
  64.                         delay_xms(5000);                                                                                        // 延时5s4 ^7 H4 t( K, `" x, Z9 y
  65.                         printf("打开中断.............\r\n");          // 打开中断# M; q3 ~9 D0 }4 w4 N* M
  66.                         portENABLE_INTERRUPTS();
    7 u7 t; \3 X# v6 _
  67.                 }+ d, M# @& F+ R& n: v0 ~
  68.                 LED0=~LED0;
    % K2 ], {- t" F3 R
  69.                 vTaskDelay(1000);8 e/ N& S* P' t6 E  F* T
  70.         }* O" U5 A( M- H
  71. }
复制代码

5 {, F  ]+ R9 N: D% u: a4 H5. 实验结果5 m3 j% i6 L/ I& F- v% |
& |0 E+ M. g* A( I! q
20210313225858796.png # _  O& @  \9 G, d6 n- z

1 P% n4 T) X/ Q5 r. t# L  s运行一开始,TIM3和TIM5都有输出,当运行5次后,关闭中断,这时只有TIM3有输出(因为优先级为4,高于configMAX_SYSCALL_INTERRUPT_PRIORITY),而TIM5优先级为5,与configMAX_SYSCALL_INTERRUPT_PRIORITY相等,被关闭了。待5s之后,重新打开中断,此时TIM5恢复运行。
/ Q2 u4 M0 }# B- D! l
6 p* Y/ I. G! M/ j  M6 L" e最后回顾下一个知识点,configMAX_SYSCALL_INTERRUPT_PRIORITY值在哪里定义的?在FreeRTOSConfig.h文件里!
. P/ W6 `$ }) \! e6 m) B. o$ _! r5 y* |
6 P7 S2 z- Z+ v7 k! g) D; B 2021031323043547.png # t0 k2 w( D; ~6 _9 |

. V9 R9 ?0 B% e2 o如果将configMAX_SYSCALL_INTERRUPT_PRIORITY改为4或更小,则TIM3也会被关闭。8 a+ n# ]- m! O6 }
————————————————
' _' N9 x  a0 q版权声明:天亮继续睡
' l2 ~* `" Y5 j
, {; N% q* ?7 c* o! W: r
赞 收藏 评论0 发布时间:2022-11-17 16:47

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版