FreeRTOS-03中断测试

根据正点原子FreeRTOS视频整理

单片机:STM32F207VC

FreeRTOS源码版本:v10.0.1

portDISABLE_INTERRUPTS();  /*关中断*/
portENABLE_INTERRUPTS();  /*开中断*/

 

工程列表:

 

实验说明:

1. 定时器3控制一个灯闪烁,抢占优先级为4;定时器5控制一个灯闪烁,抢占优先级为5.

2. InterruptTask()函数,一段时间后关闭中断,过一段时间再开启中断,如此反复。

3. 实验现象应该是,关闭中断后,优先级为4的灯继续闪烁,优先级为5的灯停止闪烁;

    开启中断后,2个灯都在闪烁。

 

1. main.c

  1 /*
  2  * 实验说明:
  3  * 1. 定时器3控制一个灯闪烁,抢占优先级为4;定时器4控制1个灯闪烁,抢占优先级为5.
  4  * 2. InterruptTask()函数,一段时间后关闭中断,过一段时间再开启中断,如此反复。
  5  * 备注:
  6  * 1. portDISABLE_INTERRUPTS();关中断
  7  * 2. portENABLE_INTERRUPTS();开中断
  8  * 3. 关中断后,优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的任务,会被关掉。
  9  * 4. 数值越大,优先级越低。
 10  */
 11 #include "main.h"
 12 #include "gpio.h"
 13 #include "delay.h"
 14 #include "sys.h"
 15 #include "timer.h"
 16 
 17 #include "stm32f2xx_gpio.h"
 18 
 19 #include "FreeRTOS.h"
 20 #include "task.h"
 21 
 22 #define START_TASK_PRIO             1     /*任务优先级*/
 23 #define START_STK_SIZE              128   /*任务堆栈大小*/
 24 TaskHandle_t StartTask_Handle;            /*任务句柄*/
 25 void StartTask(void *pvParameters);       /*任务函数*/
 26 
 27 #define INTERRUPT_TASK_PRIO         2
 28 #define INTERRUPT_STK_SIZE          256
 29 TaskHandle_t InterruptTask_Handle;
 30 void InterruptTask(void *pvParameters);
 31 
 32 
 33 
 34 /***** 声明 *****/
 35 static void SystemInitial(void);
 36 
 37 
 38 void StartTask(void *pvParameters)
 39 {
 40   taskENTER_CRITICAL();           /*进入临界区*/
 41   
 42   xTaskCreate((TaskFunction_t )InterruptTask,             /*任务函数*/
 43                             (const char *   )"InterruptTask",              /*任务名称*/
 44                             (uint16_t       )INTERRUPT_STK_SIZE,        /*任务堆栈大小*/
 45                             (void *         )NULL,                      /*传递给任务函数的参数*/
 46                             (UBaseType_t    )INTERRUPT_TASK_PRIO,       /*任务优先级*/
 47                             (TaskHandle_t   )&InterruptTask_Handle);    /*任务句柄*/             
 48 
 49   vTaskDelete(StartTask_Handle);    /*删除开始任务*/
 50   taskEXIT_CRITICAL();              /*推出临界区*/
 51 } 
 52 
 53 void InterruptTask(void *pvParameters)
 54 {
 55   static uint8_t i = 0;
 56   
 57   while (1)
 58   {
 59     i++;
 60     if (5==i)
 61     {
 62       portDISABLE_INTERRUPTS();
 63     }
 64     else if (10 == i)
 65     {
 66       i = 0;
 67       portENABLE_INTERRUPTS();
 68     }
 69     else
 70       ;
 71     
 72     DelayXms(1000);
 73   }
 74 }
 75 
 76 static void SystemInitial(void)
 77 {
 78   /*组4,16级抢占优先级,无响应优先级*/
 79   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
 80   
 81   DelayInitial();
 82   GPIO_Initial();
 83   TimerInitial();
 84 }
 85 
 86 int main(void)
 87 {
 88   SystemInitial();
 89  
 90   
 91   /*创建开始任务*/
 92   xTaskCreate((TaskFunction_t )StartTask,           /*任务函数*/
 93                             (const char *   )"StartTask",            /*任务名称*/
 94                             (uint16_t       )START_STK_SIZE,      /*任务堆栈大小*/
 95                             (void *         )NULL,                /*传递给任务函数的参数*/
 96                             (UBaseType_t    )START_TASK_PRIO,     /*任务优先级*/
 97                             (TaskHandle_t   )&StartTask_Handle);  /*任务句柄*/             
 98               
 99   /*开启任务调度*/
100   vTaskStartScheduler();
101 }
102 
103 /***************************END OF FILE***************************/
View Code

2. main.h

 1 /**/
 2 #ifndef __MAIN_H__
 3 #define __MAIN_H__
 4 
 5 
 6 
 7 
 8 #endif    /*__MAIN_H__*/
 9 
10 /***************************END OF FILE***************************/
View Code

3. sys.c

 1 /**/
 2 #include "sys.h"
 3 #include "stdio.h"
 4 
 5 #pragma import(__use_no_semihosting)             
 6 //标准库需要的支持函数                 
 7 struct __FILE 
 8 { 
 9     int handle; 
10 
11 }; 
12 
13 FILE __stdout;       
14 //定义_sys_exit()以避免使用半主机模式    
15 void _sys_exit(int x) 
16 { 
17     x = x; 
18 } 
19 //重定义fputc函数 
20 int fputc(int ch, FILE *f)
21 {      
22     // while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
23    // USART1->DR = (u8) ch;      
24     return ch;
25 }
26 
27 
28 /***************************END OF FILE***************************/
View Code

4. sys.h

 1 /**/
 2 #ifndef __SYS_H__
 3 #define __SYS_H__
 4 
 5 /*0不支持OS,1支持OS*/
 6 #define SYSTEM_SUPPORT_OS        1        /*定义系统文件夹是否支持OS*/
 7 
 8 #endif    /*__SYS_H__*/
 9 
10 /***************************END OF FILE***************************/
View Code

5. delay.c

  1 /**/
  2 #include "delay.h"
  3 #include "sys.h"
  4 /*如果需要使用OS,则包括下面的头文件即可*/
  5 #if SYSTEM_SUPPORT_OS
  6 #include "FreeRTOS.h"                      
  7 #include "task.h" 
  8 #endif
  9 
 10 __IO uint32_t TimingDelay;
 11 
 12 //////////////////////////
 13 static uint8_t  fac_us = 0;
 14 //////////////////////////
 15 
 16 /***** 声明 *****/
 17 extern void xPortSysTickHandler(void);
 18 
 19 /*systick中断服务函数,使用FreeRTOS时用到*/
 20 void SysTick_Handler(void)
 21 {    
 22     TimingDelayDecrement();
 23     
 24     if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)   /*系统已运行*/
 25     {
 26       xPortSysTickHandler();    
 27     }
 28 }
 29 
 30 
 31 void DelayInitial(void)
 32 {
 33   /*
 34      * SystemCoreClock / 1000      1ms中断一次
 35      * SystemCoreClock / 100000    10us中断一次
 36      * SystemCoreClock / 1000000   1us中断一次
 37      */
 38   if (SysTick_Config(SystemCoreClock / 1000))
 39   {
 40     while (1);
 41   }
 42   /*关闭systick timer定时器*/
 43   /*    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;*/
 44 
 45   /*使能滴答定时器*/
 46   SysTick->CTRL |=   SysTick_CTRL_ENABLE_Msk;  
 47 }
 48 
 49 void DelayNus(uint32_t nus)
 50 {
 51   uint32_t ticks;
 52   uint32_t told, tnow, tcnt = 0;
 53   uint32_t reload = SysTick->LOAD;
 54   
 55   fac_us = SystemCoreClock / 1000000;
 56   ticks = nus * fac_us;
 57   told  = SysTick->VAL;
 58   
 59   while (1)
 60   {
 61     tnow = SysTick->VAL;
 62     if (tnow != told)
 63     {
 64       if (tnow < told) 
 65       {
 66         tcnt += told - tnow;
 67       }
 68       else
 69       {
 70         tcnt += reload - tnow + told;
 71       }
 72       told = tnow;
 73       if (tcnt >= ticks)  break;      
 74     }
 75   }
 76 }
 77 
 78 /*不会引起调度*/
 79 void DelayXms(uint32_t nms)
 80 {
 81   uint32_t i;
 82   
 83   for (i=0;i<nms;++i)
 84   {
 85     DelayNus(1000);
 86   }
 87 }
 88 
 89 /*
 90  * 本函数在中断函数中调用,滴答定时器中断一次调用一次。
 91  */
 92 void TimingDelayDecrement(void)
 93 {
 94     if (TimingDelay != 0x00)
 95     {
 96         TimingDelay--;
 97     }
 98 }
 99 
100 /*
101  * TimingDelay值在TimingDelayDecrement函数中递减
102  */
103 void DelayNms(uint32_t nTimes)
104 {
105     TimingDelay = nTimes;
106     
107     while (TimingDelay!=0);   //等待计数停止
108 }
109 
110 /***************************END OF FILE***************************/
View Code

6. delay.h

 1 /**/
 2 #ifndef __DELAY_H__
 3 #define __DELAY_H__
 4 
 5 #include "stm32f2xx.h"
 6 
 7 #include <stdint.h>
 8 
 9 extern void DelayInitial(void);
10 extern void TimingDelayDecrement(void);
11 extern void DelayNms(uint32_t nTimes);
12 
13 /////////////////////////
14 extern void DelayXms(uint32_t nms);
15 /////////////////////////
16 
17 #endif    /*__DELAY_H__*/
18 /***************************END OF FILE***************************/
View Code

7. gpio.c

 1 /**/
 2 #include "gpio.h"
 3 
 4 /***** 声明 *****/
 5 static void GPIO_LED_Configuration(void);
 6 
 7 
 8 void GPIO_Initial(void)
 9 {
10   GPIO_LED_Configuration();
11 }
12 
13 
14 static void GPIO_LED_Configuration(void)
15 {
16   GPIO_InitTypeDef    GPIO_InitStructure;
17   
18   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
19   
20   GPIO_InitStructure.GPIO_Pin     = LED_POWER | LED_RUN | LED_ALARM;
21   GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_OUT;
22   GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
23   GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
24   GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_NOPULL;
25   GPIO_Init(GPIOE, &GPIO_InitStructure);  
26   
27   LED_Power_On();
28   LED_Run_Off();
29   LED_Alarm_Off();
30 }
31 
32 /***************************END OF FILE***************************/
View Code

8. gpio.h

 1 /**/
 2 #ifndef __GPIO_H__
 3 #define __GPIO_H__
 4 
 5 #include "stm32f2xx_gpio.h"
 6 
 7 #define LED_POWER         GPIO_Pin_2    /*PE2*/
 8 #define LED_RUN           GPIO_Pin_3    /*PE3*/
 9 #define LED_ALARM         GPIO_Pin_4    /*PE4*/
10 
11 #define LED_Power_On()    GPIO_ResetBits(GPIOE, LED_POWER)
12 #define LED_Power_Off()   GPIO_SetBits(GPIOE, LED_POWER)
13 #define LED_Run_On()      GPIO_ResetBits(GPIOE, LED_RUN)
14 #define LED_Run_Off()     GPIO_SetBits(GPIOE, LED_RUN)
15 #define LED_Alarm_On()    GPIO_ResetBits(GPIOE, LED_ALARM)
16 #define LED_Alarm_Off()   GPIO_SetBits(GPIOE, LED_ALARM)
17 
18 
19 extern void GPIO_Initial(void);
20 
21 #endif  /*__GPIO_H__*/
22 /***************************END OF FILE***************************/
View Code

9. timer.c

  1 /**/
  2 #include "timer.h"
  3 #include "gpio.h"
  4 #include "stm32f2xx_tim.h"
  5 
  6 /***** 声明 *****/
  7 static void Timer3Init(void);
  8 static void Timer4Init(void);
  9 
 10 void TimerInitial(void)
 11 {
 12   Timer3Init();
 13   Timer4Init();
 14 }
 15 
 16 /*timer3:APB1  30MHz*/
 17 static void Timer3Init(void)
 18 {
 19   TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
 20   NVIC_InitTypeDef          NVIC_InitStructure;
 21   
 22   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 23     
 24     TIM_TimeBaseStructure.TIM_Prescaler     = 30000-1;            /*预分频系数,30MHz/30000=1KHz*/    
 25     TIM_TimeBaseStructure.TIM_Period        = 1000-1;             /*计数值,每计1000个数,产生一次中断. 1000*(1/1KHz) = 1s */
 26     TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up; /*设置计数器模式为向上计数模式*/
 27     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       /*设置时钟分频系数,TIM_CKD_DIV1不分频*/
 28     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);               /*初始化*/
 29    
 30     TIM_Cmd(TIM3, ENABLE);        /*使能TIM4外设。在使用外设时,不仅要使能其时钟,还要调用此函数使能外设才可以正常使用*/
 31         
 32     TIM_ClearFlag(TIM3, TIM_FLAG_Update);       /*清除溢出中断标志*/
 33   
 34   TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);  /*开启中断*/
 35   
 36   
 37   /*4级抢占优先级,0级响应优先级*/
 38   NVIC_InitStructure.NVIC_IRQChannel                    = TIM3_IRQn;
 39   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 4;
 40   NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 0;
 41   NVIC_InitStructure.NVIC_IRQChannelCmd                 = ENABLE;
 42   
 43   NVIC_Init(&NVIC_InitStructure);
 44 }
 45 
 46 
 47 /*timer4:APB1  30MHz*/
 48 static void Timer4Init(void)
 49 {
 50   TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
 51   NVIC_InitTypeDef          NVIC_InitStructure;
 52   
 53   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
 54     
 55   TIM_TimeBaseStructure.TIM_Prescaler     = 30000-1;              /*预分频系数,30MHz/30000=1KHz*/    
 56     TIM_TimeBaseStructure.TIM_Period        = 1000-1;               /*计数值,每计1000个数,产生一次中断. 1000*(1/1KHz) = 1s */
 57     TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;   /*设置计数器模式为向上计数模式*/
 58     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;         /*设置时钟分频系数,TIM_CKD_DIV1不分频*/
 59     TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);                 /*初始化*/
 60    
 61     TIM_Cmd(TIM4, ENABLE);        /*使能TIM4外设。在使用外设时,不仅要使能其时钟,还要调用此函数使能外设才可以正常使用*/
 62         
 63     TIM_ClearFlag(TIM4, TIM_FLAG_Update);       /*清除溢出中断标志*/
 64   
 65   TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);  /*开启中断*/
 66   
 67   
 68   /*5级抢占优先级,0级响应优先级*/
 69   NVIC_InitStructure.NVIC_IRQChannel                    = TIM4_IRQn;
 70   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 5;
 71   NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 0;
 72   NVIC_InitStructure.NVIC_IRQChannelCmd                 = ENABLE;
 73   
 74   NVIC_Init(&NVIC_InitStructure);
 75 }
 76 
 77 /*Timer3中断服务函数*/
 78 void TIM3_IRQHandler(void)
 79 {
 80   if (TIM_GetITStatus(TIM3, TIM_IT_Update)==SET)    /*溢出中断*/
 81   {
 82     GPIOE->ODR ^= LED_RUN;
 83   }
 84   TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
 85 }
 86 
 87 
 88 /*Timer4中断服务函数*/
 89 void TIM4_IRQHandler(void)
 90 {
 91   if (TIM_GetITStatus(TIM4, TIM_IT_Update)==SET)    /*溢出中断*/
 92   {
 93     GPIOE->ODR ^= LED_ALARM;
 94   }
 95   TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
 96 //  TIM_ClearFlag(TIM4, TIM_FLAG_Update);       /*清除溢出中断标志*/
 97 }
 98 
 99 
100 /***************************END OF FILE***************************/
View Code

10. timer.h

1 /**/
2 #ifndef __TIMER_H__
3 #define __TIMER_H__
4 
5 extern void TimerInitial(void);
6 
7 #endif    /*__TIMER_H__*/
8 
9 /***************************END OF FILE***************************/
View Code

说明:

main.c文件InterruptTask()函数中,如果延时用DelayNms()函数,
在执行portDISABLE_INTERRUPTS()函数后,会无法进入到滴答定时器,
导致portENABLE_INTERRUPTS()函数无法执行。

  

posted @ 2018-07-13 10:50  seifguo  阅读(939)  评论(0编辑  收藏  举报