02-freertos移植

一丶多任务

创建任务的配置

其中优先级多种:
osPriorityNormal(正常优先级)用于大多情况
osPriorityRealtime(实时优先级)用于中断响应
在这里插入图片描述

CubeMX代码生成Progect步骤

在这里插入图片描述

代码里:任务回调函数实现业务需求

在这里插入图片描述

二丶小实验:手动创建和删除任务

一个按键控制两种状态

  • 按键按下实现状态的翻转本质:
    1. 要么是自带的标志位
    2. 要么是My自定义flag的标志位
    在这里插入图片描述

创建与删除

osThreadDef(taskLED1, StartTaskLED1, osPriorityNormal, 0, 128);
taskLED1Handle = osThreadCreate(osThread(taskLED1), NULL);
printf("任务1创建完成\r\n");
osThreadTerminate(taskLED1Handle);
taskLED1Handle = NULL;
printf("删除任务1\r\n");

暂停与恢复

osThreadSuspend(taskLED2Handle);
printf("任务2已暂停\r\n");
osThreadResume(taskLED2Handle);
printf("任务2已恢复\r\n");

实验避坑:无实验现象

  • 重新烧录完程序,一定要重新按下单片机的复位键
  • 使用printf调试信息时,一定要注意重定向printf
    1. CubeMX开启串口功能
    2. printf重定向uart1:勾选MicroLib,添加下面内容
#include "stdio.h"
int fputc(int ch, FILE *f) {
    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}

三丶任务相关概念

任务状态

任务四种状态

  • 任务的四种状态:就绪态 运行态 阻塞态 挂起态

  • 挂起状态:
  1. 相当于4399小游戏里的"暂停键",此时你可以跑去上厕所
  2. 你手动暂停,也需要手动重新开启
  3. 挂起与恢复:vTaskSuspend() 是挂起 ,xTaskResume()恢复

任务调度

  • 开启任务调度,其本质是vTaskStartScheduler()函数
    在这里插入图片描述

任务遵循两个调度规则

  1. 多任务系统下:每个任务都有优先级,当优先级不同时优先执行最紧急的事情(不同等级,等级高先执行)
  2. 如果两个任务优先级相同:每个任务依次分配一个时间片,随机的轮流执行每一个任务((相同等级,轮流执行))

在这里插入图片描述
在这里插入图片描述

四丶多任务常见问题

动态创建与静态创建任务有什么区别?

  1. 静态创建需要手动分配栈空间和TCB任务块
    // 静态分配任务栈
    static StackType_t xStack[configMINIMAL_STACK_SIZE];
    // 静态分配任务控制块
    static StaticTask_t xTaskBuffer;
  1. 任务名: 任务回调函数+传入参数+句柄
  2. 其他:栈+ 优先级+ 任务栈 +任务控制块(句柄)
   xTaskCreateStatic(
        vTaskFunction,       // 任务函数
        "Task Name",         // 任务名称
        configMINIMAL_STACK_SIZE,  // 栈大小
        NULL,               // 参数
        tskIDLE_PRIORITY+1, // 优先级
        xStack,             // 任务栈
        &xTaskBuffer        // 任务控制块
    );

推挽输出和开漏输出区别?

  1. 推挽输出,内部有一个MOS管,驱动能力强,有大电流:用于驱动蜂鸣器
  2. 开漏输出,用于总线通信,例如IIC通信协议.

最多可以创建4个任务,否则报错?

在这里插入图片描述

为什么不用接线-GND模拟按键按下和解决方案?

  • 按键检测:检测 按下 松开的过程
    当使用数据线GND模拟时,松开过程可能会错误,导致程序现象错乱,思维混乱

  • 解决方法:
    采用外部中断,检测下降沿的方法

五丶开启EXTI外部中断的步骤

  • 在CubeMX里:开启中断和设置中断模式
  • 在代码里:重构HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    //delay_ms(20);
    if (GPIO_Pin == GPIO_PIN_12)                                    //检测到B键按下
    {
        if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_RESET) 
        printf("A按下\r\n");
        buttonA_flag = true;
    }
    else if (GPIO_Pin == GPIO_PIN_13)                                //检测到A键按下
    {
        if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_13) == GPIO_PIN_RESET)
	     printf("B按下\r\n");
         buttonB_flag = true;
    }

在这里插入图片描述

中断回调函数里:尽量不添加延时和循环

  • 中断回调里最好不要添加延时和循环函数
while( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12) == GPIO_PIN_R); 这个作用类似于按键不松手场景

六丶开启Uart中断的步骤

步骤

  1. 在CubeMX:开启串口和串口中断enable
  2. 在代码里:重构串口中断回调函数(可以区分不同的串口中断,可区分串口的发送与接收)
    不同的串口中断,使用同一个中断回调函数在这个函数里亦可区分是发送还是接收
// UART1接收完成中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
第一步,区分是哪个串口中断
    if (huart->Instance == USART1)
    {
       第二步,区分串口是发送中断 还是 接收中断
    }
    else if (huart->Instance == USART2)
    {
       
    }
    else if (huart->Instance == USART3)
    {
       
}

在这里插入图片描述

场景:接收中断下buffer[2]不同,执行不同动作

在这里插入图片描述
在这里插入图片描述

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)
    {
        if (Uart1_Rx_Cnt >= 255) // 溢出判断
        {
            Uart1_Rx_Cnt = 0;
            memset(Uart1_RxBuff, 0x00, sizeof(Uart1_RxBuff));
            HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出(大于256)\r\n", strlen("数据溢出(大于256)\r\n"), 0xFFFF);
        }
        else
        {
            Uart1_RxBuff[Uart1_Rx_Cnt++] = aRxBuffer_Uart1; // 接收数据转存
           
           //
           //
           //
           //这个else里实现:串口接收中断的业务逻辑
           //
           //  
        }
        HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer_Uart1, 1); // 再开启接收中断
    }
     else if (huart->Instance == USART3)
    {
        // 如果不需要对UART3做特殊处理,可保持默认的接收处理逻辑或者添加类似的溢出等简单处理
        if (Uart3_Rx_Cnt >= 255) 
        {
            Uart3_Rx_Cnt = 0;
            memset(Uart3_RxBuff, 0x00, sizeof(Uart3_RxBuff));
            HAL_UART_Transmit(&huart3, (uint8_t *)"数据溢出(大于256)\r\n", strlen("数据溢出(大于256)\r\n"), 0xFFFF);
        }
        else
        {
            Uart3_RxBuff[Uart3_Rx_Cnt++] = aRxBuffer_Uart3;
            // 可根据实际需求添加更多针对UART3接收数据的处理逻辑
        }
        HAL_UART_Receive_IT(&huart3, (uint8_t *)&aRxBuffer_Uart3, 1);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值