04-信号与量(二值信号量)

信号与量(二值信号量)

  • 信号与量
    1. 信号用于 通知
    2. 量 用于 表示资源的个数
    根据"量"的不同,可分为二状态信号量 和 计数型信号量
  • 共享资源(全局变量)同一时间不被并发调用
    在这里插入图片描述

二值信号量(拿卡-还卡场景)

在这里插入图片描述

释放Give与取走Take信号量(主语是我程序)

  • Create:系统创建一个二值信号量,即创建’一张卡’
  • Take:当前程序取走这一个资源
	if (xSemaphoreTake(myBinarySem01Handle, portMAX_DELAY) == pdTRUE) {
            // 信号量获取成功,打印 hello
            printf("task01\r\n");
        }
  • Give:当前程序释放这一个资源
if (xSemaphoreGive(myBinaryHandle) == pdTRUE)
					printf("二值信号量放入成功\r\n");
				else
					printf("二值信号量放入失败\r\n");
			}

场景一任务同步:数据采集 优先于 数据上传

  • 创建顺序是01 02 03 04
    1. 两个任务:任务二先于任务一执行
    2. 即任务二是采集数据,而任务一是上传数据,保证上传的数据都是最新的
      在这里插入图片描述

采集上传OneNET平台:1:温度 + 2:浓度–>> 3:上传数据

在这里插入图片描述

void StartTask01_ONENET(void const * argument)
{
  /* USER CODE BEGIN StartTask01_ONENET */
  /* Infinite loop */
  for(;;)
  {
		if (xSemaphoreTake(myBinarySem01Handle, portMAX_DELAY) == pdTRUE &&
            xSemaphoreTake(myBinarySem02Handle, portMAX_DELAY) == pdTRUE) {
            // 两个信号量都获取成功,开始上传数据
            printf(" Tem = %.2f°C, CO2= %.2f ppm\r\n", temperature, co2Concentration);
           	printf("\r\n");
						}
		  osDelay(1);
  }

场景二资源互斥:同一时间下,全局变量只能被同一人拿到

OnePrinter打印机设备gloabal_value或者

  • 只有一台打印机设备
    1. 任务一:打印数学资料 使用打印机
    2. 任务二:打印语文资料 使用打印机
      (类似于两个人同时拉肚子,抢厕所)

使用打印机,打印数学试卷

在这里插入图片描述

使用打印机,打印英语试卷

在这里插入图片描述

场景三事件通知:外部中断触发,相当于一个标志位

外部中断通过flag或者信号量通知另一个任务

  • 二值信号量用于 :中断事件发送时,唤醒任务
    1. take:需要一个二值信号量.相当于减1
    2. give:生成一个二值信号量,相当于加1
串口中断业务逻辑代码:唤醒任务一

在这里插入图片描述

任务一

串口相关

串口重定向

#include "stdio.h"
//重定向printf
int fputc(int ch,FILE *f)
{
  uint8_t temp[1]={ch};
  HAL_UART_Transmit(&huart1,temp,1,2);
  return ch;
}

串口中断Rx与Tx中断处理函数

  • 业务代码 和 开启串口中断代码在uart.c里全部实现

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

uart.c里:开启uart_X中断

// 定义接收缓冲区和变量
#define BUFFER_SIZE 4  // 统一接收缓冲区大小
uint8_t rx_buffer[BUFFER_SIZE];    // 接收缓冲区
uint8_t KEY1_Value = 0;  // KEY1状态值
uint8_t KEY2_Value = 0;  // KEY2状态值


	//开uart1中断
	if (HAL_UART_Receive_IT(&huart1, rx_buffer, BUFFER_SIZE) != HAL_OK) {
     Error_Handler();
 }


找到所需中断回调函数

在这里插入图片描述

uart.c里:编写对应业务流程


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        // 判断接收到的数据
        if(rx_buffer[0] == 'K' && rx_buffer[1] == 'E' && rx_buffer[2] == 'Y')
        {
            if(rx_buffer[3] == '1')
            {
                KEY1_Value = 1;
                printf("KEY1 Pressed\r\n");  // 可选的调试输出
            }
            else if(rx_buffer[3] == '2')
            {
                KEY2_Value = 1;
                printf("KEY2 Pressed\r\n");  // 可选的调试输出
            }
        }
        
        // 重新启动接收
        HAL_UART_Receive_IT(&huart1, rx_buffer, 4);
    }
}

其他问题

为什么信号量是是队列的一种?

freertos的main.c里while循环业务失效?

  • 在FreeRTOS中,==主函数(main)在启动调度器后就不会再执行while循环了。==如果你想实现一个业务流程,应该创建一个新的任务。
    在这里插入图片描述

在哪里创建二值信号量?

  • 二值信量是在CubeMX里卡片自动生成的,一般位于MX_FREERTOS_Init(void) 代码里
    在这里插入图片描述
    在这里插入图片描述

freertos二值信号量初始默认是什么状态?

  • 默认情况下,当创建成功二值信号量时,第一次使用默认是不可用状态,并且必须通过xSemaphoreGive(xBinarySemaphore)使信号量初始为可用状态

为什么串口中断里释放二值信号量导致系统卡死?

在这里插入图片描述

/* USER CODE BEGIN 1 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART1)
    {
        // 判断接收到的数据
        if(rx_buffer[0] == 'K' && rx_buffer[1] == 'E' && rx_buffer[2] == 'Y')
        {
            if(rx_buffer[3] == '1')
            {
                KEY1_Value = 1;
            // printf("KEY1 Pressed\r\n");  // 可选的调试输出
          //xSemaphoreGive(myBinarySem01Handle);
			BaseType_t xHigherPriorityTaskWoken = pdFALSE;
            xSemaphoreGiveFromISR(myBinarySem01Handle, &xHigherPriorityTaskWoken);
                if (xHigherPriorityTaskWoken == pdTRUE) {
                    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
                }
				           	  
            } 
        // 重新启动接收
        HAL_UART_Receive_IT(&huart1, rx_buffer, 4);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值