clear sky . 2024-08-11 22:29 采纳率: 23.1%
浏览 15
已结题

freertos中断使用队列传输后不能退出


#include "stm32f4xx.h"                  // Device header
#include "serial.h"
#include "delay.h"
#include "freertos.h"
#include "task.h"
#include "motor.h"
#include "lanya.h"
#include "VCC.h"
#include <stdio.h>
#include "queue.h"
#include "gunturretrotate.h"

#define GUNT_INFOR1 71 
#define GUNT_INFOR2 91
#define MORTOR_L_INFOR1 72
#define TarSped_L_Add 91
#define TarSped_L_Sub 92
#define TarSped_R_Add 123
#define TarSped_R_Sub 125

TaskHandle_t myTaskHandle_0;
TaskHandle_t myTaskHandle_1;
TaskHandle_t myTaskHandle_2;
TaskHandle_t myTaskHandle_3;
TaskHandle_t myTaskHandle_4;
TaskHandle_t myTaskHandle_5;
TaskHandle_t myTaskHandle_6;

QueueHandle_t xQueue;




/*资源使用说明*/
//B12:Motor_Standby
//F6: TIM10:gunturret_PWM_Init()

//F7: TIM11-Motor1_PWM_Init()
//B15:TIM12-Motor2_PWM_Init()






static void Task1();//电机速度控制
static void Task2();//炮塔旋转控制
static void Task3();

static void Task5();//俯仰角控制
static void Task6();//电机测速

int main(void)
{
//    VCC_Init();
    SystemInit();
    /*初始调试串口*/
    Serial_UART2_Init();
    Lanya_UART3_Init();
    /*初始电机IO口*/


    
    printf("123success\r\n");
    Motor_Standby();

    /*初始Motor1PWM-TIM11*/
    Motor1_PWM_Init();
    Motor1_PWM_Percent(50);
    Motor1_Speed_Detect();
    Motor1_DIR_Init(1);
    /*初始Motor2PWM-TIM12*/
    Motor2_PWM_Init();    
    Motor2_PWM_Percent(50);    
    Motor2_Speed_Detect();
    
    xQueue=xQueueCreate(10,sizeof(uint16_t));
    if(xQueue==NULL){
        printf("xQueue create failed\r\n");   
    }
    xTaskCreate(Task1,"motor_speed_control",     128,NULL,2,&myTaskHandle_1);
    xTaskCreate(Task2,"gunturret_rotate_control",128,NULL,2,&myTaskHandle_2);
    xTaskCreate(Task3,"coordinate_input",        128,NULL,2,&myTaskHandle_3);
    
    xTaskCreate(Task5,"                   ",     128,NULL,2,&myTaskHandle_5);
    xTaskCreate(Task6,"motor1_speed_read",       128,NULL,2,&myTaskHandle_6);
    
    vTaskStartScheduler();    
    
    
    
  while (1)
  {

      
  }
  
  
  return 0;
}

/*电机速度控制*//*mortor_speed_control*/
static void Task1(){
    /*State Engine*/
    //Status1:tarSped_L>=0&&tarSped_R>=0;
    //Status2:tarSped_L<0 &&tarSped_R<0 ;
    //Status3:tarSped_L>=0&&tarSped_R<0 ;
    static uint8_t statusx=0;
    static int16_t tarSped_L=0,tarSped_R=0;
    static int16_t currentSpeed=0;
    while(1){
               
    taskENTER_CRITICAL();
        
    //printf("task1\r\n");
        
    taskEXIT_CRITICAL();          
    
    uint16_t ReceiveValue=0;
        
    if(xQueueReceive(xQueue,&ReceiveValue,10)==pdTRUE){
        if(ReceiveValue==TarSped_L_Add){
            if((tarSped_L<2000)&&(tarSped_R>-2000)){/*限制目标速度范围*/
                tarSped_L+=20;                    
            }                
        }
            
        if(ReceiveValue==TarSped_L_Sub){
            if((tarSped_L>-2000)&&(tarSped_L<2000)){
                tarSped_L-=20;                  
            }
        }
            
        if(ReceiveValue==TarSped_R_Add){               
            if((tarSped_R<2000)&&(tarSped_R>-2000)){ /*限制目标速度范围*/
                tarSped_R+=20;                    
            }                
        }
            
        if(ReceiveValue==TarSped_R_Sub){
            if((tarSped_R<2000)&&(tarSped_R>-2000)){/*限制目标速度范围*/
                tarSped_R-=20;                    
            }                
        }
    }    
            
        //printf("tarSped_L=%d,tarSped_R=%d\r\n",tarSped_L,tarSped_R);
    
        /*status engine*/
        //status1:
     if(tarSped_L>=0||tarSped_R>=0){
        statusx=1;    
        Motor1_DIR_Init(statusx);    
        Motor2_DIR_Init(statusx);    
     }
        //status2:
     if(tarSped_L<0||tarSped_R>=0){
        statusx=2;    
        Motor1_DIR_Init(statusx);    
        Motor2_DIR_Init(statusx);      
     }
        //status3:
     if(tarSped_L>=0||tarSped_R<0){
        statusx=3;    
        Motor1_DIR_Init(statusx);    
        Motor2_DIR_Init(statusx);         
     }
     if(tarSped_L>=0||tarSped_R>=0){
        statusx=4;    
        Motor1_DIR_Init(statusx);    
        Motor2_DIR_Init(statusx);    
     }     
     
        
        
    vTaskDelay(20);
    }
}

/*炮塔旋转控制*//*gunturret_rotate_control*/
static void Task2(){
    while(1){
        static float rotateAnPercent=0;//占空比2.5%-12.5%
        uint16_t ReceiveValue=0;
        if(xQueueReceive(xQueue,&ReceiveValue,portMAX_DELAY)==pdTRUE){
                if(ReceiveValue==GUNT_INFOR1){
                    
                    if(rotateAnPercent<12.5){
                        rotateAnPercent+=0.5;
                    }
                                                    
                }
                
                if(ReceiveValue==GUNT_INFOR2){
                    
                    if(rotateAnPercent>2.5){
                    rotateAnPercent-=0.5;
                    }
                }
                
                Gunt_rotate_control(rotateAnPercent);
                
        }
    }
}

/*坐标输入函数*/
void static Task3(){//开始input,完成input
    static uint8_t inputLock=0;
    uint16_t ReceiveValue=0;
    char InputBuffer[7];
    uint8_t point=0;
    while(1){
        if(xQueueReceive(xQueue,&ReceiveValue,portMAX_DELAY)==pdTRUE){
            if(ReceiveValue=='/'){
                inputLock=1;
                printf("inputing..\r\n");
            }            
            
            if(inputLock==1){
                InputBuffer[point++]=ReceiveValue;
                
            }   
            
            for(uint8_t k=0;k<7;k++){
                printf("InputBuffer[%d]=%d",k,InputBuffer[k]);
            }
                
            if(ReceiveValue=='#'){                
            
                inputLock=0;
            }
        }
    vTaskDelay(20);
    }
}

void static Task5(){
    
    while(1){
        
        
        
        
        
     vTaskDelay(20);   
    }
    
}

/*读取电机1速度*/
void static Task6(){
    while(1){
        static int32_t motor1Speed=0,motor2Speed=0;
        static uint8_t percent=0;
        //motor1Speed=Read_Motor1_Speed();
        motor1Speed=Read_Motor2_Speed();
        taskENTER_CRITICAL();
        //printf("motor1Speed=%d\r\n",motor1Speed);
        //printf("motor2Speed=%d\r\n",motor2Speed);
        taskEXIT_CRITICAL();        
        
        percent=mortor_speedL_control(2000,motor1Speed,percent);
        
        Motor1_PWM_Init(percent);//进行逻辑修改,减少进入次数;
        
        vTaskDelay(200);
    }
        
}



/*蓝牙接收数据USART3*/
void USART3_IRQHandler(void){
        //'[' 91:TarSped_L_Add   '{' 123:TarSped_R_Add
        //']' 93:TarSped_R++   '}' 125:TarSped_R--
        //'(' 40:Rotate_L      ')' 41: Rotate_R
        static uint16_t LanyaValue=0;
        BaseType_t xHigherPriorityTaskWoken=pdFALSE;
        printf("handler\r\n");
        if(USART_GetITStatus(USART3,USART_IT_RXNE)==SET){
            USART_ClearITPendingBit(USART3,USART_IT_RXNE);
            printf("in\r\n");                
            LanyaValue=USART_ReceiveData(USART3);
            
            if(LanyaValue=='['||LanyaValue==']'||LanyaValue=='{'||LanyaValue=='}'
                ||LanyaValue=='('||LanyaValue==')'||LanyaValue=='/')
            {
            
                printf("LanyaValue=%d\r\n",LanyaValue);
            
                xQueueSendFromISR(xQueue,&LanyaValue,&xHigherPriorityTaskWoken);
                 
            }
            printf("out\r\n");
            
            
            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
        }
                        
}

上述代码
xQueueSendFromISR(xQueue,&LanyaValue,&xHigherPriorityTaskWoken)语句进入之后不能退出,为什么





  • 写回答

25条回答 默认 最新

  • 专家-皆知 2024-08-11 22:41
    关注

    参考免费微信小程序:皆我百晓生 作答,经由专家-皆知整理回复,如问题解决,望采纳;如仍有疑问,请评论回复。

    在你的代码中,xQueueSendFromISR(xQueue, &LanyaValue, &xHigherPriorityTaskWoken) 这行代码是用于从一个中断服务例程(ISR)向队列发送数据的。根据FreeRTOS的规定,这个函数应当总是能够安全地返回,除非存在一些特定的错误条件或使用不当。既然你提到程序在这里似乎卡住不退出,这可能是因为以下几个原因:

    1. 优先级反转问题:当尝试向队列发送消息时,如果高优先级的任务正在等待队列的空闲空间,并且这个任务的优先级高于当前中断处理程序的优先级,xQueueSendFromISR会请求上下文切换。但是,如果你的中断优先级配置得过高,可能导致无法立即执行更高优先级的任务,理论上不应造成死锁,但可能会引起响应延迟。检查并确保中断和任务的优先级配置合理,避免优先级倒挂。

    2. 队列满:尽管你设置了超时参数为portMAX_DELAY,意味着函数会一直等待直到有空间可用,但理论上它应该不会永久阻塞。确认队列大小设置是否足够应对数据产生速率,以及是否有其他地方未正确处理队列满的情况导致数据积压。

    3. 中断嵌套:确保在调用xQueueSendFromISR时没有更高级别的中断打断了这个过程。虽然中断嵌套通常不会直接导致此函数卡住,但如果中断处理不当,可能会引发其他间接问题。

    4. 参数传递错误:检查xQueueSendFromISR的第三个参数&xHigherPriorityTaskWoken是否被正确初始化,并且确保在中断服务例程结束前正确处理了这个标志。如果这个标志未被正确管理,可能会导致调度问题,尽管这不是直接导致函数不返回的原因。

    5. 编译器或库问题:确保使用的FreeRTOS库与你的开发环境兼容,且没有编译器优化导致的问题。

    解决方案建议

    • 检查中断优先级:确保中断和任务的优先级配置合理,避免优先级倒挂导致的响应延迟。
    • 监控队列状态:增加日志输出,在发送前后检查队列的状态(如使用uxQueueSpacesAvailable(xQueue)),确认队列是否经常接近满或已满。
    • 正确管理调度标志:确保在所有使用到xHigherPriorityTaskWoken的地方都正确处理了这个标志,包括在ISR的末尾调用portYIELD_FROM_ISR(xHigherPriorityTaskWoken)
    • 检查内存分配:虽然这不太可能是直接原因,但内存碎片或分配失败也可能间接影响队列操作,可以检查内存分配相关日志。
    • 更新库和固件:确保使用的FreeRTOS版本是最新的,并且与STM32的HAL库或其他底层驱动兼容。

    如果以上排查均未发现问题,可能需要通过更详细的日志、断点调试或者利用FreeRTOS提供的调试工具进一步分析程序执行流程,寻找具体原因。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 8月14日
  • 赞助了问题酬金15元 8月11日
  • 创建了问题 8月11日

悬赏问题

  • ¥15 CCF-CSP 2023 第三题 解压缩(50%)
  • ¥30 comfyui openpose报错
  • ¥20 Wpf Datarid单元格闪烁效果的实现
  • ¥15 图像分割、图像边缘提取
  • ¥15 sqlserver执行存储过程报错
  • ¥100 nuxt、uniapp、ruoyi-vue 相关发布问题
  • ¥15 浮窗和全屏应用同时存在,全屏应用输入法无法弹出
  • ¥100 matlab2009 32位一直初始化
  • ¥15 Expected type 'str | PathLike[str]…… bytes' instead
  • ¥15 三极管电路求解,已知电阻电压和三级关放大倍数