当前位置: 首页 > 工具软件 > Task-Board > 使用案例 >

FreeRTOS外部中断干扰Task运行问题

姜鸿畴
2023-12-01

在基于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 */

 类似资料: