GD32450i-EVAL测试二值信号量

  • Post author:
  • Post category:其他




测试二值信号量

前言:

先准备一个带有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);                             //清除中断标志位
}



版权声明:本文为qq_31278221原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。