STM32CubeIDE+FreeRTOS计数信号量实验

使用计数信号量写个模拟停车场的实验,使用开发板板载的两个按键,KEY1按下表示停车,KEY2按下表示取车,初始有10个停车位。

新建工程RTOS_CountSem,

配置HCLK,使用内部晶振,频率为180MHZ(根据板子设置)

 配置两个按键KEY1和KEY2

将SYS中时基源(Timebase Source)改为除SysTick之外的任意定时器即可,如: 

 配置FreeRTOS,使用CMSIS_V1,先使能USE_COUNTING_SEMAPHORES

定义两个任务,一个是myTask_StopCar,负责检测KEY1是否按下,如果按下,且当前有剩余车位,将车位减1。另一个是myTask_GetCar,负责检测KEY2是否按下,如果按下,且当前车库有车,将车位加1.

       

 添加一个Counting Semaphores

Ctrl + S生成代码

修改代码,

1,在main.h中添加

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

2,在mian.c中添加

/* USER CODE BEGIN PFP */
int _write(int file , char *ptr,int len)
{
    int i = 0;
    for(i = 0;i<len;i++)
        ITM_SendChar((*ptr++));
    return len;
}
/* USER CODE END PFP */

...
...
...

/* USER CODE BEGIN 2 */
printf("starting...
");
/* USER CODE END 2 */

3,在main.c中修改3个任务入口函数的内容

/* USER CODE BEGIN Header_StartDefaultTask */
/**
  * @brief  Function implementing the defaultTask thread.
  * @param  argument: Not used 
  * @retval None
  */
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN 5 */
    int timeCount = 1;
  /* Infinite loop */
  for(;;)
  {
    printf("DefaultTask----time   %d
",timeCount++);
    osDelay(1000);
  }
  /* USER CODE END 5 */ 
}
/* USER CODE BEGIN Header_StartTaskStopCar */
/**
* @brief Function implementing the myTask_StopCar thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskStopCar */
void StartTaskStopCar(void const * argument)
{
  /* USER CODE BEGIN StartTaskStopCar */
  /* Infinite loop */
  for(;;)
  {
    if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1)
    {
        /*按键消抖*/
        osDelay(10);
        if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1)
        {
            while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1);//等待按键被按下
            /*如果按键1被按下*/
            if(osSemaphoreGetCount(myCountingSem01Handle) > 0)
            {
                /*如果还剩余车位*/
                osSemaphoreWait(myCountingSem01Handle, osWaitForever);
                printf("Parking successful, now the remaining parking space is %ld
",osSemaphoreGetCount(myCountingSem01Handle));
            }else
            {
                /*如果车位已全部用完*/
                printf("Parking failed. The parking lot is full.
");
            }
        }

    }
    osDelay(10);
  }
  /* USER CODE END StartTaskStopCar */
}
/* USER CODE BEGIN Header_StartTaskGetCar */
/**
* @brief Function implementing the myTask_GetCar thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTaskGetCar */
void StartTaskGetCar(void const * argument)
{
  /* USER CODE BEGIN StartTaskGetCar */
  /* Infinite loop */
  for(;;)
  {
          if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1)
        {
              osDelay(10);
              if(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1)
              {
                  while(HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) == 1);
                  /*如果按键1被按下*/
                if(!osSemaphoreRelease(myCountingSem01Handle))
                {
                    /*取车成功*/
                    printf("The car was taken successfully, now the remaining parking space is %ld
",osSemaphoreGetCount(myCountingSem01Handle));
                }else
                {
                    /*取车失败*/
                    printf("Failed to fetch the car, now the remaining parking space is %ld
",osSemaphoreGetCount(myCountingSem01Handle));
                }
              }

        }
        osDelay(10);
  }
  /* USER CODE END StartTaskGetCar */
}

修改完毕后点击 小锤子 构建工程,然后点击Debug,按如下步骤配置ITM调试

 

 全速运行之前一定要先点击SWV ITM data Console 页面中的红色圆圈

现象:

 

 分析:

DefaultTask 负责每秒输出一个当前的时间信息,表示此时时间为第几秒。

myTask_StopCar负责检测KEY1是否被按下,如果按下进行消抖和等待按键松开,然后进行停车操作,即获取计数信号量并打印停车成功,当前剩余车位数

myTask_GetCar负责检测KEY2是否被按下,如果按下进行消抖和等待按键松开,然后进行取车操作,即释放一个计数信号量,打印取车成功,当前剩余车位数

实现了不同任务对同一信号量的处理。

原文地址:https://www.cnblogs.com/tianxxl/p/12022505.html