FreeRTOS教程——二值信号量(四)

二值信号量

信号量简介

目的:共享资源访问、与任务同步

信号量类型:二值信号量、计数型信号量、互斥信号量、递归互斥信号量

本质上是一种只包含一个项数的队列

二值信号量

0 和 1,一种内核机制。 内核同步,资源共享。

极简例子

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED0_TASK_PRIO		2
//任务堆栈大小	
#define LED0_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO		3
//任务堆栈大小	
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//延时函数初始化	  
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	 
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
xSemaphoreHandle Sempore_Bin = NULL;
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
		// 创建二值信号量
		Sempore_Bin = xSemaphoreCreateBinary();
		if(Sempore_Bin != NULL) printf("创建成功\r\n");
		else printf("创建失败\r\n");

    //创建LED0任务
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //创建LED1任务
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//LED0任务函数 
void led0_task(void *pvParameters)
{
    u8 key= 0;
		while(1){
			printf("%d\r\n",key);
			key++;
			if(key == 10){
				if(Sempore_Bin!=NULL&&key==10){
				if (xSemaphoreGive(Sempore_Bin)==pdTRUE) 
					printf("释放成功\r\n");
				else
					printf("释放失败\r\n");
				}
			}
			vTaskDelay(1000);
		}
}   

//LED1任务函数
void led1_task(void *pvParameters)
{
		while(1){
			if(xSemaphoreTake(Sempore_Bin, 10)== pdTRUE)
				printf("获取成功\r\n");
			else
				printf("获取失败\r\n");
			vTaskDelay(1000);
		}
}

中断与二值信号量实验

主要函数

if (xSemaphoreGiveFromISR(Sempore_Bin, &xHigherPrioityTaskWoken)==pdTRUE) 
if(xSemaphoreTake(Sempore_Bin, 10)== pdTRUE){}
delay_xms(10);//消抖

主要代码

// exit.c
void EXTIX_Init(void){
 		EXTI_InitTypeDef EXTI_InitStructure;
 		NVIC_InitTypeDef NVIC_InitStructure;
  	KEY_Init();	 //	按键端口初始化
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	//使能复用功能时钟
    //GPIOA.0	  中断线以及中断初始化配置 上升沿触发 PA0  WK_UP
 	  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); 
		EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	
		EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
  	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  	EXTI_Init(&EXTI_InitStructure);		//根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//使能按键WK_UP所在的外部中断通道
  	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x06;	//抢占优先级2, 
  	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;					//子优先级3
  	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;								//使能外部中断通道
  	NVIC_Init(&NVIC_InitStructure);
}

extern xSemaphoreHandle Sempore_Bin;
//外部中断0服务程序 
void EXTI0_IRQHandler(void)
{
	delay_xms(10);//消抖
	BaseType_t xHigherPrioityTaskWoken;
	if(WK_UP==1)
	{
		printf("按下按键\r\n");
		if(Sempore_Bin!=NULL){
				if (xSemaphoreGiveFromISR(Sempore_Bin, &xHigherPrioityTaskWoken)==pdTRUE) 
					printf("释放成功\r\n");
				else
					printf("释放失败\r\n");
				}
	}
	EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位  
}

//main.c
void led0_task(void *pvParameters)
{
		u8 key_sum= 0;
		while(1){
				if(xSemaphoreTake(Sempore_Bin, 10)== pdTRUE){
					printf("接受成功\r\n");
					key_sum++;
					printf("按键被按下%d次",key_sum);
				}
				else{
					// printf("释放失败\r\n");
				}
				vTaskDelay(10);
	  }
} 

你可能感兴趣的:(lot,单片机,c语言,嵌入式硬件)