FreeRTOS中断管理

一、中断相关介绍

在STM32中,一共有五种中断分配方式,如下所示:

我们在使用FreeRTOS时,需要将中断配置为组4,通过调用

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

即可完成设置。

在FreeRTOS中断中,有以下特点:

  1. 低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数
  2. 建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理(调用函数HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);)
  3. 中断优先级数值越小越优先,任务优先级数值越大越优先

 二、使用示例

本实验会使用两个定时器,一个优先级为4,一个优先级为6,注意:系统所管理的优先级范围:5~15, 现象:两个定时器每1s,打印一段字符串,当关中断时,停止打印,开中断时持续打印。

在btim.c中定义两个定时器,TIM6和TIM7,分别定时1s中断,其中TIM6抢占优先级为6,TIM7为4

#include "./BSP/LED/led.h"
#include "./BSP/TIMER/btim.h"
#include "./SYSTEM/usart/usart.h"


TIM_HandleTypeDef g_timx_handle;  /* 定时器句柄 */
TIM_HandleTypeDef g_tim7_handle;  /* 定时器句柄 */

/**
 * @brief       基本定时器TIMX定时中断初始化函数
 * @note
 *              基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
 *              基本定时器的时钟为APB1时钟的2倍, 而APB1为36M, 所以定时器时钟 = 72Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值。
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
    g_timx_handle.Instance = BTIM_TIMX_INT;                      /* 通用定时器X */
    g_timx_handle.Init.Prescaler = psc;                          /* 设置预分频系数 */
    g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 递增计数模式 */
    g_timx_handle.Init.Period = arr;                             /* 自动装载值 */
    HAL_TIM_Base_Init(&g_timx_handle);

    HAL_TIM_Base_Start_IT(&g_timx_handle);    /* 使能定时器x及其更新中断 */
}

/* TIM7初始化函数 */
void btim_tim7_int_init(uint16_t arr, uint16_t psc)
{
    g_tim7_handle.Instance = BTIM_TIM7_INT;                      /* 通用定时器X */
    g_tim7_handle.Init.Prescaler = psc;                          /* 设置预分频系数 */
    g_tim7_handle.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 递增计数模式 */
    g_tim7_handle.Init.Period = arr;                             /* 自动装载值 */
    HAL_TIM_Base_Init(&g_tim7_handle);

    HAL_TIM_Base_Start_IT(&g_tim7_handle);    /* 使能定时器x及其更新中断 */
}

/**
 * @brief       定时器底层驱动,开启时钟,设置中断优先级
                此函数会被HAL_TIM_Base_Init()函数调用
 * @param       htim:定时器句柄
 * @retval      无
 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        BTIM_TIMX_INT_CLK_ENABLE();                     /* 使能TIM6时钟 */
        HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 6, 0); /* 抢占6,子优先级0,组2 */
        HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn);         /* 开启ITM3中断 */
    }
    if (htim->Instance == BTIM_TIM7_INT)
    {
        BTIM_TIM7_INT_CLK_ENABLE();                     /* 使能TIM7时钟 */
        HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 4, 0); /* 抢占4,子优先级0,组2 */
        HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn);         /* 开启ITM3中断 */
    }
}

/**
 * @brief       定时器TIMX中断服务函数
 * @param       无
 * @retval      无
 */
void BTIM_TIMX_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_timx_handle); /* 定时器中断公共处理函数 */
}

/* TIM7中断服务函数 */
void BTIM_TIM7_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_tim7_handle); /* 定时器中断公共处理函数 */
}

/**
 * @brief       定时器更新中断回调函数
 * @param       htim:定时器句柄
 * @retval      无
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        printf("TIM6优先级为6的正在运行!\r\n");
    }
    if (htim->Instance == BTIM_TIM7_INT)
    {
        printf("TIM7优先级为4的正在运行!!!\r\n");
    }
}




main函数中调用初始化,和freertos_demo();

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./MALLOC/malloc.h"
#include "./BSP/TIMER/btim.h"

#include "freertos_demo.h"


int main(void)
{

    HAL_Init();                         /* 初始化HAL库 */
    sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    delay_init(72);                     /* 延时初始化 */
    usart_init(115200);                 /* 串口初始化为115200 */
    led_init();                         /* 初始化LED */
    key_init();                         /* 初始化按键 */
    my_mem_init(SRAMIN);                /* 初始化内部SRAM内存池 */
    btim_tim7_int_init(9999, 7199);
    btim_timx_int_init(9999, 7199);
    freertos_demo();
}

在任务1中,进行freertos中断的开和关,观察串口打印数据的变化。

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/******************************************************************************************************/
/*FreeRTOS配置*/
/* START_TASK 任务配置 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t start_task_hander;
void start_task( void * pvParameters );

/* TASK1 任务配置 */
#define TASK1_PRIO         4
#define TASK1_STACK_SIZE   128
TaskHandle_t task1_hander;
void task1( void * pvParameters );

/******************************************************************************************************/

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",//任务名字
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,//堆栈大小
                (void *                 )   NULL,//入口参数
                (UBaseType_t            )   START_TASK_PRIO,//任务优先级
                (TaskHandle_t *         )   &start_task_hander);//任务句柄

    vTaskStartScheduler();//开启任务调度器
}

void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();//进入临界区
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",//任务名字
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,//堆栈大小
                (void *                 )   NULL,//入口参数
                (UBaseType_t            )   TASK1_PRIO,//任务优先级
                (TaskHandle_t *         )   &task1_hander);//任务句柄
    vTaskDelete(NULL);//删除开始任务
    taskEXIT_CRITICAL();//退出临界区
}

/* 任务一:LED0每500ms翻转一次 */
void task1( void * pvParameters )
{
    uint8_t task1_num = 0;
    while(1)
    {
        if (++task1_num == 5)
        {
            task1_num = 0;
            printf("关中断!!\r\n");
            portDISABLE_INTERRUPTS();
            delay_ms(5000);
            printf("开中断!!\r\n");
            portENABLE_INTERRUPTS();
        }
        vTaskDelay(1000);
    }
}

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值