中断优先级特点:
a.低于configMAX_SYSCALL_INTERRUPT_PRIORITY(5)优先级的中断才允许调用FreeTOS的API函数(所以中断优先级应该在5~15之间)
b.建议把只设置抢占优先级,子优先级设为零
c.中断优先级数值越小越优先,任务优先级数值越大越优先
定时器驱动步骤
1.定义定时器结构体(也就是句柄)
2.定时器的初始化和使能
3.设置中断优先级和时钟使能
4.中断服务函数
5.回调函数
中断管理实验两个任务功能:
1.start_task 用来创建task1任务
2.task1 中断测试任务,通过调用开关中断函数体现对中断的管理作用
两个重要函数:
关闭中断函数:portDISABLE_INTERRUPTS() 无参无返回值
开启中断函数:portENABLE_INTERRUPTS() 无参无返回值
中断管理代码
//btim.c
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/btim.h"
#include "./SYSTEM/usart/usart.h"
TIM_HandleTypeDef g_timx_handler; /* 定时器参数句柄 */
TIM_HandleTypeDef g_tim7_handler; /* 定时器7参数句柄 */
/**
* @brief 基本定时器TIMX定时中断初始化函数
* @note
* 基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
* 基本定时器的时钟为APB1时钟的2倍, 而APB1为42M, 所以定时器时钟 = 84Mhz
* 定时器溢出时间计算方法: 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_handler.Instance = BTIM_TIMX_INT; /* 定时器x */
g_timx_handler.Init.Prescaler = psc; /* 分频 */
g_timx_handler.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
g_timx_handler.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_timx_handler);
HAL_TIM_Base_Start_IT(&g_timx_handler); /* 使能定时器x和定时器更新中断 */
}
//TIM7初始化
void btim_tim7_int_init(uint16_t arr, uint16_t psc)
{
g_tim7_handler.Instance = BTIM_TIM7_INT; /* 定时器x */
g_tim7_handler.Init.Prescaler = psc; /* 分频 */
g_tim7_handler.Init.CounterMode = TIM_COUNTERMODE_UP; /* 递增计数模式 */
g_tim7_handler.Init.Period = arr; /* 自动装载值 */
HAL_TIM_Base_Init(&g_tim7_handler);
HAL_TIM_Base_Start_IT(&g_tim7_handler); /* 使能定时器7和定时器更新中断 */
}
/**
* @brief 定时器底层驱动,开启时钟,设置中断优先级
此函数会被HAL_TIM_Base_Init()函数调用
* @param 无
* @retval 无
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == BTIM_TIMX_INT)
{
BTIM_TIMX_INT_CLK_ENABLE(); /* 使能TIMx时钟 */
HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 6, 0); /* 抢占6,子优先级0 */
HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn); /* 开启ITMx中断 */
}
if (htim->Instance == BTIM_TIM7_INT)
{
BTIM_TIM7_INT_CLK_ENABLE(); /* 使能TIM7时钟 */
HAL_NVIC_SetPriority(BTIM_TIM7_INT_IRQn, 4, 0); /* 抢占4,子优先级0 */
HAL_NVIC_EnableIRQ(BTIM_TIM7_INT_IRQn); /* 开启ITM7中断 */
}
}
/**
* @brief 基本定时器TIMX中断服务函数
* @param 无
* @retval 无
*/
void BTIM_TIMX_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_timx_handler); /* 定时器回调函数 */
}
//TIM7中断服务函数
void BTIM_TIM7_INT_IRQHandler(void)
{
HAL_TIM_IRQHandler(&g_tim7_handler); /* 定时器回调函数 */
}
/**
* @brief 回调函数,定时器中断服务函数调用,中断后的实现都在回调函数中写
* @param 无
* @retval 无
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == BTIM_TIMX_INT)
{
printf("TIM6优先级为6的正在运行!!!\r\n");
}else if(htim->Instance == BTIM_TIM7_INT)
{
printf("TIM7优先级为4的正在运行!!!\r\n");
}
}
//btim.h
#ifndef __BTIM_H
#define __BTIM_H
#include "./SYSTEM/sys/sys.h"
/******************************************************************************************/
/* 基本定时器 定义 */
/* TIMX 中断定义
* 默认是针对TIM6/TIM7
* 注意: 通过修改这4个宏定义,可以支持TIM1~TIM8任意一个定时器.
*/
#define BTIM_TIMX_INT TIM6
#define BTIM_TIMX_INT_IRQn TIM6_DAC_IRQn
#define BTIM_TIMX_INT_IRQHandler TIM6_DAC_IRQHandler
#define BTIM_TIMX_INT_CLK_ENABLE() do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0) /* TIM6 时钟使能 */
#define BTIM_TIM7_INT TIM7
#define BTIM_TIM7_INT_IRQn TIM7_IRQn
#define BTIM_TIM7_INT_IRQHandler TIM7_IRQHandler
#define BTIM_TIM7_INT_CLK_ENABLE() do{ __HAL_RCC_TIM7_CLK_ENABLE(); }while(0) /* TIM6 时钟使能 */
/******************************************************************************************/
void btim_timx_int_init(uint16_t arr, uint16_t psc); /* 基本定时器 定时中断初始化函数 */
void btim_tim7_int_init(uint16_t arr, uint16_t psc); /* 基本定时器 定时中断初始化函数 */
#endif
任务管理代码
//freertos_demo.c
#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_handler;
void start_task(void * pvParameters);
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1(void* pv);
/******************************************************************************************************/
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task,
(char* ) "start_task",
(unsigned portSHORT) START_TASK_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) START_TASK_PRIO,
(TaskHandle_t* ) &start_task_handler );
vTaskStartScheduler();
}
void start_task(void* pvPara)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate((TaskFunction_t ) task1,
(char* ) "task1",
(unsigned portSHORT) TASK1_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK1_PRIO,
(TaskHandle_t* ) &task1_handler );
vTaskDelete(NULL);
taskEXIT_CRITICAL(); //退出临界区
}
//任务一 测试中断管理效果,中断7的优先级高应该无法被关闭,中断6可以
void task1(void* pv)
{
uint16_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(500); //这个延迟函数会调用中断,提前打开中断,所以上面用delay
}
}
//freertos_demo.h
#ifndef __FREERTOS_DEMO_H
#define __FREERTOS_DEMO_H
void freertos_demo(void);
#endif
main.c
#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 "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"
#include "./BSP/TIMER/btim.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
sram_init(); /* SRAM初始化 */
btim_timx_int_init(10000-1,8400-1);//定时器6初始化,407开发板168M时钟进行2分频,再设置分频系数8400,重装载值:84000000/8400=10000
btim_tim7_int_init(10000-1,8400-1);//定时器7初始化
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
my_mem_init(SRAMEX); /* 初始化外部SRAM内存池 */
my_mem_init(SRAMCCM); /* 初始化内部CCM内存池 */
freertos_demo();
}