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

【经验分享】STM32 FreeRTOS中断示例

[复制链接]
STMCU小助手 发布时间:2022-6-17 14:48
01. 概述
在FreeRTOS中优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断会被屏蔽掉,高于的就不会。我们使用两个定时器,一个优先级为4,一个优先级为5,两个定时器每隔1秒通过串口输出一串字符串。然后在某个任务中关闭中断一段时间,查看两个定时器的输出情况。

02. 函数设计
设计两个任务start_task()和interrupt_task(),这两个任务的功能如下:

start_task():创建另外一个任务。

interrupt_task():中断测试任务,任务中会调用FreeRTOS的关中断函数将中断关闭一段时间。

03. 程序设计与分析
任务设置

  1. //任务优先级
  2. #define START_TASK_PRIO                        1
  3. //任务堆栈大小        
  4. #define START_STK_SIZE                         256  
  5. //任务句柄
  6. TaskHandle_t StartTask_Handler;
  7. //任务函数
  8. void start_task(void *pvParameters);

  9. //任务优先级
  10. #define INTERRUPT_TASK_PRIO                2
  11. //任务堆栈大小        
  12. #define INTERRUPT_STK_SIZE                 256  
  13. //任务句柄
  14. TaskHandle_t INTERRUPTTask_Handler;
  15. //任务函数
  16. void interrupt_task(void *p_arg);
复制代码

主函数设计
  1. int main(void)
  2. {
  3.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
  4.         delay_init(168);                                        //初始化延时函数
  5.         uart_init(115200);                                     //初始化串口
  6.         LED_Init();                                                //初始化LED端口
  7.         TIM3_Int_Init(10000-1,8400-1);                //初始化定时器3,定时器周期1S
  8.         TIM5_Int_Init(10000-1,8400-1);                //初始化定时器5,定时器周期1S
  9.         
  10.         //创建开始任务
  11.     xTaskCreate((TaskFunction_t )start_task,            //任务函数
  12.                 (const char*    )"start_task",          //任务名称
  13.                 (uint16_t       )START_STK_SIZE,        //任务堆栈大小
  14.                 (void*          )NULL,                  //传递给任务函数的参数
  15.                 (UBaseType_t    )START_TASK_PRIO,       //任务优先级
  16.                 (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
  17.     vTaskStartScheduler();          //开启任务调度
  18. }
复制代码

任务函数设计

  1. //开始任务任务函数
  2. void start_task(void *pvParameters)
  3. {
  4.     taskENTER_CRITICAL();           //进入临界区
  5.     //创建中断测试任务
  6.     xTaskCreate((TaskFunction_t )interrupt_task,                          //任务函数
  7.                 (const char*    )"interrupt_task",                         //任务名称
  8.                 (uint16_t       )INTERRUPT_STK_SIZE,                //任务堆栈大小
  9.                 (void*          )NULL,                                                //传递给任务函数的参数
  10.                 (UBaseType_t    )INTERRUPT_TASK_PRIO,                //任务优先级
  11.                 (TaskHandle_t*  )&INTERRUPTTask_Handler);         //任务句柄
  12.         vTaskDelete(StartTask_Handler); //删除开始任务
  13.     taskEXIT_CRITICAL();            //退出临界区
  14. }

  15. //中断测试任务函数
  16. void interrupt_task(void *pvParameters)
  17. {
  18.         static u32 total_num=0;
  19.     while(1)
  20.     {
  21.                 total_num+=1;
  22.                 if(total_num==5)
  23.                 {
  24.                         printf("关闭中断.............\r\n");
  25.                         portDISABLE_INTERRUPTS();                                //关闭中断
  26.                         delay_xms(5000);                                                //延时5s
  27.                         printf("打开中断.............\r\n");        //打开中断
  28.                         portENABLE_INTERRUPTS();
  29.                 }
  30.         LED0=~LED0;
  31.         vTaskDelay(1000);
  32.     }
  33. }  
复制代码

04. 中断初始化

  1. //通用定时器3中断初始化
  2. //arr:自动重装值。
  3. //psc:时钟预分频数
  4. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
  5. //Ft=定时器工作频率,单位:Mhz
  6. //这里使用的是定时器3!
  7. void TIM3_Int_Init(u16 arr,u16 psc)
  8. {
  9.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  10.         NVIC_InitTypeDef NVIC_InitStructure;
  11.         
  12.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
  13.         
  14.         TIM_TimeBaseInitStructure.TIM_Period = arr;         //自动重装载值
  15.         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
  16.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  17.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  18.         
  19.         TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
  20.         
  21.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
  22.         TIM_Cmd(TIM3,ENABLE); //使能定时器3
  23.         
  24.         NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
  25.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x04; //抢占优先级4
  26.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00; //子优先级0
  27.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  28.         NVIC_Init(&NVIC_InitStructure);
  29. }

  30. //通用定时器5中断初始化
  31. //arr:自动重装值。
  32. //psc:时钟预分频数
  33. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
  34. //Ft=定时器工作频率,单位:Mhz
  35. //这里使用的是定时器5!
  36. void TIM5_Int_Init(u16 arr,u16 psc)
  37. {
  38.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  39.         NVIC_InitTypeDef NVIC_InitStructure;
  40.         
  41.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);        //使能TIM5时钟
  42.         
  43.         TIM_TimeBaseInitStructure.TIM_Period = arr;                 //自动重装载值
  44.         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;                  //定时器分频
  45.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  46.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  47.         
  48.         TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);        //初始化TIM5
  49.         
  50.         TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);                         //允许定时器5更新中断
  51.         TIM_Cmd(TIM5,ENABLE);                                                                 //使能定时器5
  52.         
  53.         NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;                 //定时器5中断
  54.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x05;         //抢占优先级5
  55.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;                 //子优先级0
  56.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  57.         NVIC_Init(&NVIC_InitStructure);
  58. }

  59. //定时器3中断服务函数
  60. void TIM3_IRQHandler(void)
  61. {
  62.         if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
  63.         {
  64.                 printf("TIM3输出.......\r\n");
  65.         }
  66.         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
  67. }


  68. //定时器5中断服务函数
  69. void TIM5_IRQHandler(void)
  70. {
  71.         if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //溢出中断
  72.         {
  73.                 printf("TIM5输出.......\r\n");
  74.         }
  75.         TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清除中断标志位
  76. }
复制代码

05. 程序设计
main.c文件

  1. //任务优先级
  2. #define START_TASK_PRIO                        1
  3. //任务堆栈大小        
  4. #define START_STK_SIZE                         256  
  5. //任务句柄
  6. TaskHandle_t StartTask_Handler;
  7. //任务函数
  8. void start_task(void *pvParameters);

  9. //任务优先级
  10. #define INTERRUPT_TASK_PRIO                2
  11. //任务堆栈大小        
  12. #define INTERRUPT_STK_SIZE                 256  
  13. //任务句柄
  14. TaskHandle_t INTERRUPTTask_Handler;
  15. //任务函数
  16. void interrupt_task(void *p_arg);

  17. int main(void)
  18. {
  19.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
  20.         delay_init(168);                                        //初始化延时函数
  21.         uart_init(115200);                                     //初始化串口
  22.         LED_Init();                                                //初始化LED端口
  23.         TIM3_Int_Init(10000-1,8400-1);                //初始化定时器3,定时器周期1S
  24.         TIM5_Int_Init(10000-1,8400-1);                //初始化定时器5,定时器周期1S
  25.         
  26.         //创建开始任务
  27.     xTaskCreate((TaskFunction_t )start_task,            //任务函数
  28.                 (const char*    )"start_task",          //任务名称
  29.                 (uint16_t       )START_STK_SIZE,        //任务堆栈大小
  30.                 (void*          )NULL,                  //传递给任务函数的参数
  31.                 (UBaseType_t    )START_TASK_PRIO,       //任务优先级
  32.                 (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
  33.     vTaskStartScheduler();          //开启任务调度
  34. }

  35. //开始任务任务函数
  36. void start_task(void *pvParameters)
  37. {
  38.     taskENTER_CRITICAL();           //进入临界区
  39.     //创建中断测试任务
  40.     xTaskCreate((TaskFunction_t )interrupt_task,                          //任务函数
  41.                 (const char*    )"interrupt_task",                         //任务名称
  42.                 (uint16_t       )INTERRUPT_STK_SIZE,                //任务堆栈大小
  43.                 (void*          )NULL,                                                //传递给任务函数的参数
  44.                 (UBaseType_t    )INTERRUPT_TASK_PRIO,                //任务优先级
  45.                 (TaskHandle_t*  )&INTERRUPTTask_Handler);         //任务句柄
  46.         vTaskDelete(StartTask_Handler); //删除开始任务
  47.     taskEXIT_CRITICAL();            //退出临界区
  48. }

  49. //中断测试任务函数
  50. void interrupt_task(void *pvParameters)
  51. {
  52.         static u32 total_num=0;
  53.     while(1)
  54.     {
  55.                 total_num+=1;
  56.                 if(total_num==5)
  57.                 {
  58.                         printf("关闭中断.............\r\n");
  59.                         portDISABLE_INTERRUPTS();                                //关闭中断
  60.                         delay_xms(5000);                                                //延时5s
  61.                         printf("打开中断.............\r\n");        //打开中断
  62.                         portENABLE_INTERRUPTS();
  63.                 }
  64.         LED0=~LED0;
  65.         vTaskDelay(1000);
  66.     }
  67. }  
复制代码

timer.c文件


  1. //通用定时器3中断初始化
  2. //arr:自动重装值。
  3. //psc:时钟预分频数
  4. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
  5. //Ft=定时器工作频率,单位:Mhz
  6. //这里使用的是定时器3!
  7. void TIM3_Int_Init(u16 arr,u16 psc)
  8. {
  9.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  10.         NVIC_InitTypeDef NVIC_InitStructure;
  11.         
  12.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
  13.         
  14.         TIM_TimeBaseInitStructure.TIM_Period = arr;         //自动重装载值
  15.         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
  16.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  17.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  18.         
  19.         TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
  20.         
  21.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
  22.         TIM_Cmd(TIM3,ENABLE); //使能定时器3
  23.         
  24.         NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
  25.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x04; //抢占优先级4
  26.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00; //子优先级0
  27.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  28.         NVIC_Init(&NVIC_InitStructure);
  29. }

  30. //通用定时器5中断初始化
  31. //arr:自动重装值。
  32. //psc:时钟预分频数
  33. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
  34. //Ft=定时器工作频率,单位:Mhz
  35. //这里使用的是定时器5!
  36. void TIM5_Int_Init(u16 arr,u16 psc)
  37. {
  38.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  39.         NVIC_InitTypeDef NVIC_InitStructure;
  40.         
  41.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);        //使能TIM5时钟
  42.         
  43.         TIM_TimeBaseInitStructure.TIM_Period = arr;                 //自动重装载值
  44.         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;                  //定时器分频
  45.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  46.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  47.         
  48.         TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure);        //初始化TIM5
  49.         
  50.         TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);                         //允许定时器5更新中断
  51.         TIM_Cmd(TIM5,ENABLE);                                                                 //使能定时器5
  52.         
  53.         NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;                 //定时器5中断
  54.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x05;         //抢占优先级5
  55.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x00;                 //子优先级0
  56.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  57.         NVIC_Init(&NVIC_InitStructure);
  58. }

  59. //定时器3中断服务函数
  60. void TIM3_IRQHandler(void)
  61. {
  62.         if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
  63.         {
  64.                 printf("TIM3输出.......\r\n");
  65.         }
  66.         TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
  67. }


  68. //定时器5中断服务函数
  69. void TIM5_IRQHandler(void)
  70. {
  71.         if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //溢出中断
  72.         {
  73.                 printf("TIM5输出.......\r\n");
  74.         }
  75.         TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //清除中断标志位
  76. }
复制代码




收藏 评论0 发布时间:2022-6-17 14:48

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版