OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3584|回复: 3

FreeRTOS关不了外部中断

[复制链接]
回帖奖励 30 金钱 回复本帖可获得 10 金钱奖励! 每人限 2 次(中奖概率 70%)

8

主题

13

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2018-2-10
在线时间
20 小时
发表于 2019-4-17 15:28:15 | 显示全部楼层 |阅读模式
本帖最后由 wzjlymL 于 2019-4-17 16:43 编辑

我初始化了3个按键,两个用来触发外部中断,一个用来关闭中断,外部中断优先级1个是4,一个是6,我的FreeRTOS配置最大优先级为5,但是按下关闭中断那个按键后,2个外部中断还是可以触发,求大神解答?谢谢!代码如下:
[mw_shl_code=c,true]#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include <stdio.h>
#include "exti.h"
#include "FreeRTOS.h"
#include "task.h"

/*声明任务函数*/
void vTask1( void *pvParameters );
void Interrupt_Task1( void *pvParameters );

TaskHandle_t INTE_Hander;
int main()
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//中断优先级分组
        GPIOX_Init();        //LED灯GPIO初始化
        Key_Init();                //按键初始化
        Usart1_MY_Init();//串口初始化
        EXTIX_Init();                        //外部中断初始化
        
        /*创建任务*/
        xTaskCreate(vTask1,"vTask1",128,NULL,2,&INTE_Hander);   

        /* 启动任务调度器,开始执行任务 */
  vTaskStartScheduler();
        
}

/*任务1 LED1灯进行闪烁并通过串口打印*/
void vTask1( void *pvParameters )
{
        /*创建任务*/
        xTaskCreate(Interrupt_Task1,"Interrupt_Task1",128,NULL,3,NULL);
        
  while(1)
  {
                printf("Task is running! \r\n");
    GPIO_ToggleBits(GPIOF,GPIO_Pin_9);
                vTaskDelay( 100 / portTICK_RATE_MS );
  }
        
}

/*KEY0按下 关闭中断*/
void Interrupt_Task1( void *pvParameters )
{
        while(1)
        {
                if((GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0))
                {
                        portDISABLE_INTERRUPTS();
                        printf("中断关闭!\r\n");
                }
                vTaskDelay( 100 / portTICK_RATE_MS );
        }
}

/*外部中断3服务程序*/
void EXTI3_IRQHandler(void)
{
        if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)
        {
                        printf("KEY1发生中断\r\n");
        }         
         EXTI_ClearITPendingBit(EXTI_Line3);  //清除LINE3上的中断标志位  
}

/*外部中断2服务程序*/
void EXTI2_IRQHandler(void)
{
        if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0)
        {
                        printf("KEY2发生中断\r\n");
        }         
         EXTI_ClearITPendingBit(EXTI_Line2);  //清除LINE2上的中断标志位  
}





[/mw_shl_code]

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

164

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
204
金钱
204
注册时间
2019-4-2
在线时间
4 小时
发表于 2019-4-24 09:25:33 | 显示全部楼层
回复 支持 反对

使用道具 举报

51

主题

2165

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10652
金钱
10652
注册时间
2017-4-14
在线时间
2780 小时
发表于 2019-4-24 11:27:24 | 显示全部楼层

回帖奖励 +10 金钱

FreeRTOS配置最大优先级为5  portDISABLE_INTERRUPTS();应该能关掉6 的关不掉4的  只是关外部中断可以直接配置XTI_InitStructure.EXTI_LineCmd = DISABLE;  全部关可以试试sys里面的关中断
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2018-11-21
在线时间
6 小时
发表于 2019-4-30 12:48:40 | 显示全部楼层

回帖奖励 +10 金钱

关于这个问题,我前两天学习时有遇到过,本人FreeRTOS的新手一枚,混迹论坛纯属学习,不正指出还望大神不惜赐教。

正式解答:本人觉着出现上述原因是由于题主调用vTaskDelay()函数引起的,
原子的教程中在移植FreeRTOS的时候修改了很多,对delay函数也修改了,题主细心点看教材就可以发现。
首先vTaskDelay()函数使用的是FreeRTOS的SysTick(中断向量号为最低15),
在关闭FreeRTOS函数后,重新调用vTaskDelay()会激活FreeRTOS的SysTick,任务调度也就开始了。
会导致刚关闭中断就立马打开的现象,导致误以为关不上中断。
我用的是STM32CubeMX配置的FreeRTOS,
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{

        if(tim_baseHandle->Instance == TIM3)
        {
                /* USER CODE BEGIN TIM3_MspInit 0 */

                /* USER CODE END TIM3_MspInit 0 */
                /* TIM3 clock enable */
                __HAL_RCC_TIM3_CLK_ENABLE();

                /* TIM3 interrupt Init */
                HAL_NVIC_SetPriority(TIM3_IRQn, 4, 0);
                HAL_NVIC_EnableIRQ(TIM3_IRQn);
                /* USER CODE BEGIN TIM3_MspInit 1 */
                HAL_TIM_Base_Start_IT(&htim3); //使能定时器3和定时器3更新中断:TIM_IT_UPDATE
                /* USER CODE END TIM3_MspInit 1 */
        }
        else if(tim_baseHandle->Instance == TIM4)
        {
                /* USER CODE BEGIN TIM4_MspInit 0 */

                /* USER CODE END TIM4_MspInit 0 */
                /* TIM4 clock enable */
                __HAL_RCC_TIM4_CLK_ENABLE();

                /* TIM4 interrupt Init */
                HAL_NVIC_SetPriority(TIM4_IRQn, 5, 0);
                HAL_NVIC_EnableIRQ(TIM4_IRQn);
                /* USER CODE BEGIN TIM4_MspInit 1 */
                HAL_TIM_Base_Start_IT(&htim4); //使能定时器4和定时器4更新中断:TIM_IT_UPDATE
                /* USER CODE END TIM4_MspInit 1 */
        }
}



void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
        /* USER CODE BEGIN Callback 0 */

        /* USER CODE END Callback 0 */
        if (htim->Instance == TIM5)
        {
                HAL_IncTick();  // TIM5作为HAL库的TimeBase,用于延时处理或者超时处理,其中断向量号为0
        }
        /* USER CODE BEGIN Callback 1 */
        if (htim->Instance == TIM3)
        {
                printf("TIM3 输出.......\r\n");
        }
        if (htim->Instance == TIM4)
        {
                printf("TIM4 输出.......\r\n");
        }
        /* USER CODE END Callback 1 */
}


下面说说重点:
/* USER CODE BEGIN Header_StartInterruptTask */
/**
* @brief Function implementing the InterruptTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartInterruptTask */
void StartInterruptTask(void const * argument)
{
        /* USER CODE BEGIN StartInterruptTask */
        static uint32_t total_num = 0;
        /* Infinite loop */
        for(;;)
        {
                total_num += 1;
                if(total_num == 5)
                {
                        printf("关闭中断.............\r\n");
                        portDISABLE_INTERRUPTS();        // 关闭中断,会关闭中断向量号 5-15 的所有中断,包括 FreeRTOS的 SysTick滴答(中断向量号为 15),
                                                                        // 关闭中断会引起其他所有任务停止运行(因为其受FreeRTOS的 调度 ,而 FreeRTOS的 调度基于 SysTick)
                                                                        // 其中TIM3中断向量设置为 4(不受FreeRTOS中断管理)关不上,TIM4为中断向量设置为 5(受FreeRTOS中断管理)会被关闭
                       
                        HAL_Delay(5000);                        // 延时 5s( HAL_Delay函数采用的 TimeBase为 TIM5,中断向量为 0,不受Freertos中断管理)
                                                                        // 如果此处调用 osDelay函数,会引发上述被关闭的中断重新开启,因为 osDelay函数调用了 vTaskDelay,
                                                                        // 也就是说 SysTick被重新激活了,任务调度也就开始了。
                                                                        // 会导致刚关闭中断就立马打开的现象,导致误以为关不上中断
                       
                        printf("打开中断.............\r\n");       
                        portENABLE_INTERRUPTS();     // 打开中断(其中TIM3中断向量设置为 4(不受FreeRTOS中断管理),TIM4为 5(受FreeRTOS中断管理))
                }
                osDelay(1000);
        }
        /* USER CODE END StartInterruptTask */
}






解决办法,不调用 vTaskDelay,如果使用hal库,就调用HAL_Delay,如果使用原子的方法,就调用原子封装的延时函数。




希望能帮到您!!!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 03:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表