在基于FreeRTOS系统下,进行按键的外部中断时,如果我们按键中断触发方式为低电平的话,在我们按下按键的时候,会一直进入中断,FreeRTOS的Task就无法进行,所以要将按键的中断触发方式改为边沿触发检测
由外部中断对FreeRTOS的影响触发,不管是哪种中断都会影响FreeRTOS的Task运行情况,中断的优先级是高于Task的,所以在进行中断处理的时候一定要快进快出,尽量不在中断中做过多的处理
如下实验使用RT1052平台,按键中断源为下降沿触发,使用定时器进行软件消抖(该开发板有进行硬件消抖,但是还是没办法保证可完全消抖)
具体代码如下:
/*main.c*/
/*******************************************************************************
| File Name: main.c
| Description:
|-------------------------------------------------------------------------------
| (c)This software is the proprietary of HASCOVISION.
|-------------------------------------------------------------------------------
| Initials Name Company
|-------------------------------------------------------------------------------
|
|-------------------------------------------------------------------------------
| R E V I S I O N H I S T O R Y
|-------------------------------------------------------------------------------
| Date Version Author Description
|-------------------------------------------------------------------------------
|
|-------------------------------------------------------------------------------
| History
| <No.> <author> <time> <description>
| 2022-09-19 11:26:53 Primary edition
|******************************************************************************/
/*******************************************************************************
| Other Header File Inclusion
|******************************************************************************/
#include "fsl_debug_console.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
#include "task.h"
#include "bsp_led.h"
#include "bsp_nvic.h"
#include "bsp_key_it.h"
#include "bsp_lpuart.h"
#include "bsp_gpt.h"
/*******************************************************************************
| variables Declaration
|******************************************************************************/
//定义任务句柄
static TaskHandle_t hstPrv_vMainAppTaskCreate = NULL;
//定义LED任务句柄
TaskHandle_t hstLED = NULL;
//定义软件定时器句柄
static TimerHandle_t hstSwtmr1 = NULL;
//定义当前不同按键标志位
BaseType_t g_xKeySwitch = pdTRUE;//pdTRUE--WAKUP pdFALSE--MODE
//定义一个全局变量查看存储位置
__attribute__((section("section_for_test")))
char arfortest[] = "hello the world!";
int na = 10;
int nb = 20;
/*******************************************************************************
| 宏 Declaration
|******************************************************************************/
/*******************************************************************************
| Function Declaration
|******************************************************************************/
static void Prv_vMainBSPInit(void);
static void Prv_vMainAppTaskCreate(void *parameter);
static void Prv_vMainLEDTask(void *parameter);
static void Prv_vMainSwtmr1Callback(void *pvParameters);
/*******************************************************************************
| main函数
|******************************************************************************/
/*******************************************************************************
| Function name : main
| Called by :
| Preconditions :
| Input Parameters :
| Return Value :
| Description :
| History
| <No.> <author> <time> <description>
| Primary edition
|******************************************************************************/
int main(void)
{
Prv_vMainBSPInit();
PRINTF("\r\n arfortest:%s\r\n",arfortest);
BaseType_t xReturn = pdPASS;
xReturn = xTaskCreate( (TaskFunction_t) Prv_vMainAppTaskCreate,//任务入口函数
(char *)"Prv_vMainAppTaskCreate",//任务名字
(uint16_t)512,//任务栈大小
(void *)NULL,
(UBaseType_t)1,//任务优先级
(TaskHandle_t *)&hstPrv_vMainAppTaskCreate);//任务控制块指针
if(pdPASS == xReturn)//任务创建成功
{
vTaskStartScheduler();//启动任务,开启调度
}
else
{
return -1;
}
while(1)
{
}
}
/*******************************************************************************
| Function name : Prv_vMainBSPInit
| Called by :
| Preconditions :
| Input Parameters :
| Return Value :
| Description :
| History
| <No.> <author> <time> <description>
| Primary edition
|******************************************************************************/
static void Prv_vMainBSPInit(void)
{
/* 初始化内存保护单元 */
BOARD_ConfigMPU();
/* 初始化开发板引脚 */
BOARD_InitPins();
/* 初始化开发板时钟 */
BOARD_BootClockRUN();
/* 初始化调试串口 */
BOARD_InitDebugConsole();
/*设置外部中断优先级分组*/
Set_NVIC_PriorityGroup(Group_3);
/* 打印系统时钟 */
PRINTF("\r\n");
//PRINTF("*****欢迎进入RT1052世界*****\r\n");
PRINTF("CPU: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_CpuClk));
PRINTF("AHB: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_AhbClk));
PRINTF("SEMC: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SemcClk));
PRINTF("SYSPLL: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllClk));
PRINTF("SYSPLLPFD0: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd0Clk));
PRINTF("SYSPLLPFD1: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd1Clk));
PRINTF("SYSPLLPFD2: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk));
PRINTF("SYSPLLPFD3: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd3Clk));
/*初始化SysTick*/
SysTick_Config(SystemCoreClock / configTICK_RATE_HZ);
//硬件BSP初始化流程放在此函数中
//LED端口初始化
LED_GPIO_Config();
//KEY端口初始化
vKeyItKey_IT_GPIO_Config();
//串口初始化
UART_Config();
//定时器初始化
vGpt_GPT_Config();
// vGpt_GPT_SetStart_Timer(1000);
}
/*******************************************************************************
| Function name : Prv_vMainAppTaskCreate
| Called by :
| Preconditions :
| Input Parameters :
| Return Value :
| Description :所有的用户任务都在这里面创建
| History
| <No.> <author> <time> <description>
| Primary edition
|******************************************************************************/
static void Prv_vMainAppTaskCreate(void *parameter)
{
BaseType_t xReturn = pdPASS;
//进入临界区
taskENTER_CRITICAL();
//创建Prv_vMainLEDTask任务
xReturn = xTaskCreate( (TaskFunction_t)Prv_vMainLEDTask,//任务入口函数
(char *)"Prv_vMainLEDTask",//任务名字
(uint16_t)512,//任务栈大小 128*4
(void *)NULL,
(UBaseType_t)3,//任务优先级
(TaskHandle_t *)&hstLED);//任务控制块指针
if(pdPASS == xReturn)
{
PRINTF("Prv_vMainLEDTask created successfully!\r\n");
}
else
{
PRINTF("Prv_vMainLEDTask created fail!\r\n");
}
//创建定时器1
hstSwtmr1 = xTimerCreate((const char *)"AutoReloadTimer",
(TickType_t)(pdMS_TO_TICKS(1000)),
(UBaseType_t)(pdTRUE),
(void *)1,
(TimerCallbackFunction_t)(Prv_vMainSwtmr1Callback));
if(NULL != hstSwtmr1)
{
xTimerStart(hstSwtmr1,0);
}
vTaskDelete(hstPrv_vMainAppTaskCreate);//删除Prv_vMainAppTaskCreate任务
taskEXIT_CRITICAL();//退出临界区
}
/*******************************************************************************
| Function name : Prv_vMainLEDTask
| Called by :
| Preconditions :
| Input Parameters :
| Return Value :
| Description :等待按键任务通知
| History
| <No.> <author> <time> <description>
| Primary edition
|******************************************************************************/
static void Prv_vMainLEDTask(void *parameter)
{
uint32_t un_value = 0;
while(1)
{
if(pdTRUE == xTaskNotifyWait( 0x03,//进入函数前清除低2位
0x03,//退出函数前清除低2位
&un_value,//接收值
portMAX_DELAY))
{
switch (un_value)
{
case keyit_CORE_BOARD_WAUP_NOTIFY_VALUE:
g_xKeySwitch = pdTRUE;
vGpt_GPT_SetStart_Timer(20);
break;
case keyit_CORE_BOARD_MODE_NOTIFY_VALUE:
// RGB_GREEN_LED_TOGGLE;
g_xKeySwitch = pdFALSE;
vGpt_GPT_SetStart_Timer(20);
break;
case LPUART1_NOTIFY_VALUE:
Uart_SendByte(DEBUG_UARTx,g_ucCh);
break;
default:
break;
}
}
}
}
/*******************************************************************************
| Function name : Prv_vMainSwtmr1Callback
| Called by :
| Preconditions :
| Input Parameters :
| Return Value :
| Description :软件定时器1回调函数
| History
| <No.> <author> <time> <description>
| Primary edition
|******************************************************************************/
static void Prv_vMainSwtmr1Callback(void *pvParameters)
{
// PRINTF("Timer1\r\n");
CORE_BOARD_LED_TOGGLE;
}
/********************************END OF FILE****************************/
/*bsp_key_it.c*/
/**
******************************************************************
* @file bsp_key_it.c
* @author fire
* @version V1.0
* @date 2021-xx-xx
* @brief 按键应用函数接口(中断模式)
******************************************************************
* @attention
*
*
*
*
*
******************************************************************
*/
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#include "pad_config.h"
#include "bsp_nvic.h"
#include "bsp_key_it.h"
#include "FreeRTOS.h"
#include "task.h"
/******************************************************************
* 变量定义
******************************************************************/
extern TaskHandle_t hstLED;
/******************************************************************
* 宏
******************************************************************/
/* 按键中断检测引脚的PAD配置 */
#define keyit_KEY_PAD_CONFIG_DATA (padCFG_SRE_0_SLOW_SLEW_RATE| \
padCFG_DSE_0_OUTPUT_DRIVER_DISABLED| \
padCFG_SPEED_2_MEDIUM_100MHz| \
padCFG_ODE_0_OPEN_DRAIN_DISABLED| \
padCFG_PKE_1_PULL_KEEPER_ENABLED| \
padCFG_PUE_1_PULL_SELECTED| \
padCFG_PUS_3_22K_OHM_PULL_UP| \
padCFG_HYS_1_HYSTERESIS_ENABLED)
/* 配置说明 : */
/* 转换速率: 转换速率慢
驱动强度: 关闭
速度配置 : medium(100MHz)
开漏配置: 关闭
拉/保持器配置: 使能
拉/保持器选择: 上下拉
上拉/下拉选择: 22K欧姆上拉
滞回器配置: 开启 (仅输入时有效,施密特触发器,使能后可以过滤输入噪声)*/
/******************************************************************
* 声明
******************************************************************/
static void Prv_vKeyItKey_IOMUXC_MUX_Config(void);
static void Prv_vKeyItKey_IOMUXC_PAD_Config(void);
static void Prv_vKeyItKey_GPIO_Mode_Config(void);
static void Prv_vKeyItKey_Interrupt_Config(void);
/******************************************************************
* 函数代码
******************************************************************/
/**
* @brief 初始化按键相关IOMUXC的MUX复用配置
* @param 无
* @retval 无
*/
static void Prv_vKeyItKey_IOMUXC_MUX_Config(void)
{
/* 设置按键引脚的复用模式为GPIO,不使用SION功能 */
IOMUXC_SetPinMux(keyit_CORE_BOARD_WAUP_KEY_IOMUXC, 0U);
IOMUXC_SetPinMux(keyit_CORE_BOARD_MODE_KEY_IOMUXC, 0U);
}
/**
* @brief 初始化按键相关引脚PAD属性
* @param 无
* @retval 无
*/
static void Prv_vKeyItKey_IOMUXC_PAD_Config(void)
{
/* 设置按键引脚属性功能 */
IOMUXC_SetPinConfig(keyit_CORE_BOARD_WAUP_KEY_IOMUXC, keyit_KEY_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(keyit_CORE_BOARD_MODE_KEY_IOMUXC, keyit_KEY_PAD_CONFIG_DATA);
}
/**
* @brief 初始化按键相关的GPIO模式
* @param 无
* @retval 无
*/
static void Prv_vKeyItKey_GPIO_Mode_Config(void)
{
/* 配置为输入模式,低电平中断,后面通过GPIO_PinInit函数加载配置 */
gpio_pin_config_t stKeyConfig;
/** 核心板的按键,GPIO配置 **/
stKeyConfig.direction = kGPIO_DigitalInput; //输入模式
stKeyConfig.outputLogic = 1; //默认高电平(输入模式时无效)
// stKeyConfig.interruptMode = kGPIO_IntLowLevel;
stKeyConfig.interruptMode = kGPIO_IntFallingEdge; //设为低电平触发会影响FreeRTOS的Task任务运行情况,所以尽量使用边沿触发检测
/* 初始化 KEY GPIO. */
GPIO_PinInit(keyit_CORE_BOARD_MODE_KEY_GPIO, keyit_CORE_BOARD_MODE_KEY_GPIO_PIN, &stKeyConfig);
GPIO_PinInit(keyit_CORE_BOARD_WAUP_KEY_GPIO, keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN, &stKeyConfig);
}
/**
* @brief 设置按键相关的GPIO模式
* @param 无
* @retval 无
*/
void vKeyItKey_GPIO_IRQMode_Config(gpio_interrupt_mode_t interruptMode)
{
/* 配置为输入模式,低电平中断,后面通过GPIO_PinInit函数加载配置 */
gpio_pin_config_t stKeyConfig;
/** 核心板的按键,GPIO配置 **/
stKeyConfig.direction = kGPIO_DigitalInput; //输入模式
stKeyConfig.outputLogic = 1; //默认高电平(输入模式时无效)
stKeyConfig.interruptMode = interruptMode;
/* 初始化 KEY GPIO. */
GPIO_PinInit(keyit_CORE_BOARD_WAUP_KEY_GPIO, keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN, &stKeyConfig);
}
/**
* @brief 初始化按键中断相关的内容
* @param 无
* @retval 无
*/
static void Prv_vKeyItKey_Interrupt_Config(void)
{
/* 开启GPIO引脚的中断 */
GPIO_PortEnableInterrupts(keyit_CORE_BOARD_WAUP_KEY_GPIO, 1U << keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN);
GPIO_PortEnableInterrupts(keyit_CORE_BOARD_MODE_KEY_GPIO, 1U << keyit_CORE_BOARD_MODE_KEY_GPIO_PIN);
/*设置中断优先级,*/
set_IRQn_Priority(keyit_CORE_BOARD_WAUP_KEY_IRQ,Group4_PreemptPriority_6, Group4_SubPriority_0);
set_IRQn_Priority(keyit_CORE_BOARD_MODE_KEY_IRQ,Group4_PreemptPriority_6, Group4_SubPriority_1);
/* 开启GPIO端口中断 */
EnableIRQ(keyit_CORE_BOARD_WAUP_KEY_IRQ);
EnableIRQ(keyit_CORE_BOARD_MODE_KEY_IRQ);
}
/**
* @brief 初始化控制KEY的IO
* @param 无
* @retval 无
*/
void vKeyItKey_IT_GPIO_Config(void)
{
/* 初始化GPIO复用、属性、模式及中断*/
Prv_vKeyItKey_IOMUXC_MUX_Config();
Prv_vKeyItKey_IOMUXC_PAD_Config();
Prv_vKeyItKey_GPIO_Mode_Config();
Prv_vKeyItKey_Interrupt_Config();
}
/********************中断服务函数**************************/
/**
* @brief GPIO 输入中断服务函数
* keyit_CORE_BOARD_WAUP_KEY_IRQHandler只是一个宏,
* 在本例中它指代函数名GPIO5_Combined_0_15_IRQHandler,
* 中断服务函数名是固定的,可以在启动文件中找到。
* @param 中断服务函数不能有输入参数
* @note 中断函数一般只使用标志位进行指示,完成后尽快退出,
* 具体操作或延时尽量不放在中断服务函数中
* @retval 中断服务函数不能有返回值
*
* 1、下降沿触发即发送全局变量
*
*/
void keyit_CORE_BOARD_WAUP_KEY_IRQHandler(void)
{
// /* 清除中断标志位 */
// GPIO_PortClearInterruptFlags(keyit_CORE_BOARD_WAUP_KEY_GPIO,
// 1U << keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN);
// /* 设置按键中断标志 */
// g_KeyDown[keyit_CORE_BOARD_WAUP_KEY_ID] = true;
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
uint32_t unReturn;
//进入临界段,临界段可以嵌套
unReturn = taskENTER_CRITICAL_FROM_ISR();
//清除中断标志位
GPIO_PortClearInterruptFlags(keyit_CORE_BOARD_WAUP_KEY_GPIO,1U<<keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN);
//标志全局变量或者写入消息队列中
xTaskNotifyFromISR(hstLED,keyit_CORE_BOARD_WAUP_NOTIFY_VALUE,eSetValueWithOverwrite,&pxHigherPriorityTaskWoken);
// xQueueSendFromISR(xTestQueue, &Send_Data1, pxHigherPriorityTaskWoken )
//如果是写入消息队列的,则如果需要进行一次任务切换
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken)
//退出临界段
taskEXIT_CRITICAL_FROM_ISR(unReturn);
/* 以下部分是为 ARM 的勘误838869添加的,
该错误影响 Cortex-M4, Cortex-M4F内核,
立即存储覆盖重叠异常,导致返回操作可能会指向错误的中断
CM7不受影响,此处保留该代码
*/
/* 原注释:Add for ARM errata 838869, affects Cortex-M4,
Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
/**
* @brief GPIO 输入中断服务函数
* keyit_CORE_BOARD_MODE_KEY_IRQHandler只是一个宏,
* 在本例中它指代函数名GPIO1_Combined_0_15_IRQHandler,
* 中断服务函数名是固定的,可以在启动文件中找到。
* @param 中断服务函数不能有输入参数
* @note 中断函数一般只使用标志位进行指示,完成后尽快退出,
* 具体操作或延时尽量不放在中断服务函数中
* @retval 中断服务函数不能有返回值
*/
void keyit_CORE_BOARD_MODE_KEY_IRQHandler(void)
{
// /* 清除中断标志位 */
// GPIO_PortClearInterruptFlags(keyit_CORE_BOARD_MODE_KEY_GPIO,
// 1U << keyit_CORE_BOARD_MODE_KEY_GPIO_PIN);
// /* 设置按键中断标志 */
// g_KeyDown[keyit_CORE_BOARD_MODE_KEY_ID] = true;
BaseType_t pxHigherPriorityTaskWoken = pdFALSE;
uint32_t ulReturn;
//进入临界段,临界段可以嵌套
ulReturn = taskENTER_CRITICAL_FROM_ISR();
//清除中断标志位
GPIO_PortClearInterruptFlags(keyit_CORE_BOARD_MODE_KEY_GPIO,1U<<keyit_CORE_BOARD_MODE_KEY_GPIO_PIN);
//标志全局变量或者写入消息队列中
xTaskNotifyFromISR(hstLED,keyit_CORE_BOARD_MODE_NOTIFY_VALUE,eSetValueWithOverwrite,&pxHigherPriorityTaskWoken);
// xQueueSendFromISR(xTestQueue, &Send_Data1, pxHigherPriorityTaskWoken )
//如果是写入消息队列的,则如果需要进行一次任务切换
portYIELD_FROM_ISR(pxHigherPriorityTaskWoken)
//退出临界段
taskEXIT_CRITICAL_FROM_ISR(ulReturn);
/* 以下部分是为 ARM 的勘误838869添加的,
该错误影响 Cortex-M4, Cortex-M4F内核,
立即存储覆盖重叠异常,导致返回操作可能会指向错误的中断
CM7不受影响,此处保留该代码
*/
/* 原注释:Add for ARM errata 838869, affects Cortex-M4,
Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
/*bsp_key_it.h*/
#ifndef __BSP_KEY_IT_H
#define __BSP_KEY_IT_H
#include "fsl_common.h"
#include "fsl_gpio.h"
/******************************************************************
* 宏
******************************************************************/
//WAUP按键
#define keyit_CORE_BOARD_WAUP_KEY_GPIO GPIO5
#define keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN (0U)
#define keyit_CORE_BOARD_WAUP_KEY_IOMUXC IOMUXC_SNVS_WAKEUP_GPIO5_IO00
#define keyit_CORE_BOARD_WAUP_KEY_NAME "CORE_BORE_WAUP_KEY"
#define keyit_CORE_BOARD_WAUP_KEY_ID 0
//中断相关,IRQ中断号及IRQHandler中断服务函数
#define keyit_CORE_BOARD_WAUP_KEY_IRQ GPIO5_Combined_0_15_IRQn
#define keyit_CORE_BOARD_WAUP_KEY_IRQHandler GPIO5_Combined_0_15_IRQHandler
//MODE按键
#define keyit_CORE_BOARD_MODE_KEY_GPIO GPIO1
#define keyit_CORE_BOARD_MODE_KEY_GPIO_PIN (5U)
#define keyit_CORE_BOARD_MODE_KEY_IOMUXC IOMUXC_GPIO_AD_B0_05_GPIO1_IO05
#define keyit_CORE_BOARD_MODE_KEY_NAME "CORE_BORE_MODE_KEY"
#define keyit_CORE_BOARD_MODE_KEY_ID 1
//中断相关,IRQ中断号及IRQHandler中断服务函数
#define keyit_CORE_BOARD_MODE_KEY_IRQ GPIO1_Combined_0_15_IRQn
#define keyit_CORE_BOARD_MODE_KEY_IRQHandler GPIO1_Combined_0_15_IRQHandler
//任务通知值
#define keyit_CORE_BOARD_WAUP_NOTIFY_VALUE 0
#define keyit_CORE_BOARD_MODE_NOTIFY_VALUE 1
/******************************************************************
* 声明
******************************************************************/
extern void vKeyItKey_IT_GPIO_Config(void);
extern void vKeyItKey_GPIO_IRQMode_Config(gpio_interrupt_mode_t interruptMode);
#endif /* __BSP_KEY_IT_H */
/*bsp_gpt.c*/
#include "bsp_nvic.h"
#include "bsp_gpt.h"
#include "bsp_led.h"
#include "bsp_key_it.h"
#include "fsl_gpio.h"
#include "fsl_debug_console.h"
#include "FreeRTOS.h"
#include "task.h"
void vGpt_GPT_Config(void)
{
gpt_config_t st_gptConfig;
/*设置GPT使用到的外部时钟*/
CLOCK_SetMux(kCLOCK_PerclkMux, gpt_EXAMPLE_GPT_CLOCK_SOURCE_SELECT);
CLOCK_SetDiv(kCLOCK_PerclkDiv, gpt_EXAMPLE_GPT_CLOCK_DIVIDER_SELECT);
/*初始化GPT*/
GPT_GetDefaultConfig(&st_gptConfig);
st_gptConfig.enableFreeRun = false;
GPT_Init(gpt_EXAMPLE_GPT, &st_gptConfig);
/* 设置时钟分频 */
GPT_SetClockDivider(gpt_EXAMPLE_GPT, gpt_GPT_DIVIDER);
/* 设置GPT定时器的计数值*/
//GPT_SetOutputCompareValue(gpt_EXAMPLE_GPT, kGPT_OutputCompare_Channel1, (uint32_t)(gpt_COUNTER_TIME(CounterNumber)));
/* 开启GPT2定时器比较通道1的中断 */
GPT_EnableInterrupts(gpt_EXAMPLE_GPT, kGPT_OutputCompare1InterruptEnable);
/*设置中断优先级,*/
set_IRQn_Priority(gpt_GPT_IRQ_ID,Group4_PreemptPriority_6, Group4_SubPriority_0);
/*使能中断*/
EnableIRQ(gpt_GPT_IRQ_ID);
/* 开启定时器 */
//GPT_StartTimer(gpt_EXAMPLE_GPT);
}
/**
* @brief 设置定时器计数值并启动定时器
* @param 无
* @retval 无
*/
void vGpt_GPT_SetStart_Timer(uint32_t CounterNumber)
{
/* 设置GPT定时器的计数值*/
GPT_SetOutputCompareValue(gpt_EXAMPLE_GPT, kGPT_OutputCompare_Channel1, (uint32_t)(gpt_COUNTER_TIME(CounterNumber)));
GPT_StartTimer(gpt_EXAMPLE_GPT);
}
/*定义中断服务函数*/
void gpt_EXAMPLE_GPT_IRQHandler(void)
{
// /* 清除中断标志位.*/
// GPT_ClearStatusFlags(gpt_EXAMPLE_GPT, kGPT_OutputCompare1Flag);
// i++;
// if(i%2)
// {
// RGB_BLUE_LED_OFF;
// }
// else
// {
// RGB_BLUE_LED_ON;
// }
uint32_t ulReturn;
//进入临界段,临界段可以嵌套
ulReturn = taskENTER_CRITICAL_FROM_ISR();
//清除中断标志位
GPT_ClearStatusFlags(gpt_EXAMPLE_GPT, kGPT_OutputCompare1Flag);
GPT_StopTimer(gpt_EXAMPLE_GPT);
if(pdTRUE == g_xKeySwitch)
{
//PRINTF("WAUP=%x\r\n",GPIO_ReadPinInput(keyit_CORE_BOARD_WAUP_KEY_GPIO,keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN));
if(0==GPIO_ReadPinInput(keyit_CORE_BOARD_WAUP_KEY_GPIO,keyit_CORE_BOARD_WAUP_KEY_GPIO_PIN))
{
RGB_RED_LED_TOGGLE;
}
else
{
//do nothing
}
}
else if(pdFALSE == g_xKeySwitch)
{
//PRINTF("MODE=%x\r\n",GPIO_ReadPinInput(keyit_CORE_BOARD_MODE_KEY_GPIO,keyit_CORE_BOARD_MODE_KEY_GPIO_PIN));
if(0==GPIO_ReadPinInput(keyit_CORE_BOARD_MODE_KEY_GPIO,keyit_CORE_BOARD_MODE_KEY_GPIO_PIN))
{
RGB_GREEN_LED_TOGGLE;
}
else
{
//do nothing
}
}
else
{
//do nothing
}
//退出临界段
taskEXIT_CRITICAL_FROM_ISR(ulReturn);
/* 以下部分是为 ARM 的勘误838869添加的,
该错误影响 Cortex-M4, Cortex-M4F内核,
立即存储覆盖重叠异常,导致返回操作可能会指向错误的中断
CM7不受影响,此处保留该代码
*/
/* 原注释:Add for ARM errata 838869, affects Cortex-M4,
Cortex-M4F Store immediate overlapping
exception return operation might vector to incorrect interrupt */
#if defined __CORTEX_M && (__CORTEX_M == 4U)
__DSB();
#endif
}
/*bsp_gpt.h*/
#ifndef __BSP_GPT_H__
#define __BSP_GPT_H__
#include "fsl_common.h"
#include "fsl_gpt.h"
#include "FreeRTOS.h"
#include "task.h"
/* 选择外部时钟源 */
/*
PERCLK_CLK_SEL
Selector for the perclk clock multiplexor
0 derive clock from ipg clk root
1 derive clock from osc_clk
*/
#define gpt_EXAMPLE_GPT_CLOCK_SOURCE_SELECT (0U)
/* 时钟源的时钟分频 */
/*
PERCLK_PODF Divider for perclk podf.
000000 divide by 1
000001 divide by 2
000010 divide by 3
000011 divide by 4
000100 divide by 5
000101 divide by 6
000110 divide by 7
111111 divide by 64
*/
#define gpt_EXAMPLE_GPT_CLOCK_DIVIDER_SELECT (0U) //不分频
/*GPT 时钟分频(1-4096)*/
#define gpt_GPT_DIVIDER 100
/* 得到GPT定时器的计数频率*/
#define gpt_EXAMPLE_GPT_CLK_FREQ ( (CLOCK_GetFreq(kCLOCK_IpgClk) / (gpt_EXAMPLE_GPT_CLOCK_DIVIDER_SELECT + 1U))/gpt_GPT_DIVIDER )
#define COUNGER_NUMBER ((gpt_TIME_ms/1000.0)*gpt_EXAMPLE_GPT_CLK_FREQ)
#define gpt_TIME_ms 1000
#define gpt_COUNTER_TIME(x) ((x/1000.0)*gpt_EXAMPLE_GPT_CLK_FREQ) //ms计数器
/*定义使用的GPT*/
#define gpt_EXAMPLE_GPT GPT2
/*中断号和中断服务函数宏定义*/
#define gpt_GPT_IRQ_ID GPT2_IRQn
#define gpt_EXAMPLE_GPT_IRQHandler GPT2_IRQHandler
extern BaseType_t g_xKeySwitch;
extern void vGpt_GPT_Config(void);
extern void vGpt_GPT_SetStart_Timer(uint32_t CounterNumber);
#endif /* __BSP_GPT_H */