测试二值信号量
前言:
先准备一个带有freertos的工程,没有的话可以参考我以前的博客------>点我跳转
测试的方法是
创建二值信号量 > 任务来获取信号量 > 按键释放信号量
按键释放有两种方法:查询点平法和外部中断法。
废话少说,开搞
电平查询法
我们用的按键是GPIO_PIN_13
main函数
#include "gd32f4xx.h"
#include "gd32f450i_eval.h"
#include <stdio.h>
#include "systick.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
void CrateTask(void *pvParameters);
void task_a(void *pvParameters);
void task_b(void *pvParameters);
TaskHandle_t StartTask_Handler; //任务句柄
xSemaphoreHandle xSemaphore = NULL; //二值信号量
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
gd_eval_key_init(KEY_TAMPER, KEY_MODE_GPIO); //KEY_MODE_GPIO 查询点平的模式
gd_eval_com_init(EVAL_COM0); //初始化串口
vSemaphoreCreateBinary(xSemaphore); //新建二值信号量
if(xSemaphore != NULL) //判断是否创建成功
printf("二值信号量创建成功!\r\n");
xTaskCreate(CrateTask ,"CrateTask" , 256, NULL, 1, &StartTask_Handler); //创建任务
vTaskStartScheduler(); //开启任务调度
}
void CrateTask(void *pvParameters){
taskENTER_CRITICAL(); //打开临阶段
xTaskCreate(task_a , "task_a" ,128 ,NULL , 2 ,0); //创建任务A
xTaskCreate(task_b , "task_b" ,128 ,NULL , 2 ,0); //创建任务B
vTaskDelete(StartTask_Handler); //删除创建任务
taskEXIT_CRITICAL(); //关闭临界段
}
void task_a(void *pvParameters)
{
while(1){
/* check if the tamper key is pressed */
if(RESET == gd_eval_key_state_get(KEY_TAMPER)){ //消除按键抖动
vTaskDelay(50);
if(RESET == gd_eval_key_state_get(KEY_TAMPER)){
vTaskDelay(50);
if(RESET == gd_eval_key_state_get(KEY_TAMPER)){
xSemaphoreGive( xSemaphore); //释放二值信号量
}
}
}
vTaskDelay(250);
}
}
void task_b(void *pvParameters)
{
while(1){
if(pdTRUE == xSemaphoreTake( xSemaphore, 500 )) //获取信号量
{
printf("获取成功!\r\n");
}else{
printf("等待take!\r\n");
}
vTaskDelay(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM0, (uint8_t)ch);
while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
return ch;
}
这样我们在main函数里面直接创建了二值信号量,然后有一个任务每隔1s获取信号量,我们可以通过按键来释放信号量。
外部按键中断法
main函数
#include "gd32f4xx.h"
#include "gd32f450i_eval.h"
#include <stdio.h>
#include "systick.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
void task(void *pvParameters);
xSemaphoreHandle xSemaphore = NULL;
portBASE_TYPE xHigherPriorityTaskWoken = pdTRUE; //解除比当前中断优先级高的任务的阻塞态
/*
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
gd_eval_key_init(KEY_TAMPER, KEY_MODE_EXTI); //KEY_MODE_EXTI 外部按键中断模式
gd_eval_com_init(EVAL_COM0); //初始化串口
vSemaphoreCreateBinary(xSemaphore); //创建二值信号量
if(xSemaphore != NULL) //判断信号量是否创建成功
printf("信号量创建成功!\r\n");
else
printf("信号量创建失败!\r\n");
xTaskCreate(task , "task" ,128 ,NULL , 2 ,0); //创建任务
vTaskStartScheduler(); //开启任务调度
}
void task(void *pvParameters)
{
while(1){
if(pdTRUE == xSemaphoreTake( xSemaphore, 500 )) //获取二值信号量
printf("获取成功!\r\n");
else
printf("等待take!\r\n");
vTaskDelay(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(EVAL_COM0, (uint8_t)ch);
while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TBE));
return ch;
}
gd32f4xx_it.c在最后添加下面的代码
extern xSemaphoreHandle xSemaphore;
extern portBASE_TYPE xHigherPriorityTaskWoken;
void EXTI10_15_IRQHandler (void) //按键的中断函数
{
xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); //释放二值信号量
exti_interrupt_flag_clear(EXTI_13); //清除中断标志位
}