[STM32] CubeMX を使用して FreeRTOS のボタンでタスクを制御する

FreeRTOS での操作で最も一般的なのは、タスクの作成、削除、一時停止、再開です。

この実験の目標:

1. タスク 1 を作成します。LED1 が 1 秒ごとに点滅し、シリアル ポート経由で印刷します。

2. タスク 2 を作成します。LED2 が 0.5 秒ごとに点滅し、シリアル ポート経由で印刷します。

3. タスク 3 の作成: タスク 1 から KEY1 までを作成および削除します。

ボタンを押した後、タスク 1 があればタスク 1 を削除し、タスク 1 がなければタスク 1 を作成します。

4. タスク 4 を作成します。KEY2 を通じてタスク 2 を一時停止および再開します。

ボタンを押すと、タスク 2 が実行中の場合はタスク 2 が一時停止され、タスク 2 が一時停止されたときにタスク 2 がタスク 2 を再開します。

実現方法:

時間厳守の Atom Explorer を使用し、メイン制御チップは STM32F407ZGT6 です。

1. 主な電気回路図は次のとおりです。

 

2、CubeMX 構成

1.FreeRTOSをセットアップする

2.usart1を設定します

ボーレート 115200

3. クロックを設定し、外部高速クロックを選択します

クロックツリーを次のように設定します

4. タイムベースを必ず変更してください

5. コードを生成する

3. コードを作成します (すべて freertos.c で記述されています)

1. シリアルポートのリダイレクト

#include <stdio.h>// 包含标准输入输出头文件
 
int fputc(int ch,FILE *f)
{
//采用轮询方式发送1字节数据,超时时间设置为无限等待
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,HAL_MAX_DELAY);
return ch;
}
int fgetc(FILE *f)
{
uint8_t ch;
// 采用轮询方式接收 1字节数据,超时时间设置为无限等待
HAL_UART_Receive( &huart1,(uint8_t*)&ch,1, HAL_MAX_DELAY );
return ch;
}

2. タスクを実現するコード

void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
  /* add mutexes, ... */
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
  /* add queues, ... */
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* definition and creation of LED1 */
  osThreadDef(LED1, led1, osPriorityNormal, 0, 128);
  LED1Handle = osThreadCreate(osThread(LED1), NULL);

  /* definition and creation of LED2 */
  osThreadDef(LED2, led2, osPriorityIdle, 0, 128);
  LED2Handle = osThreadCreate(osThread(LED2), NULL);

  /* definition and creation of KEY1 */
  osThreadDef(KEY1, key1, osPriorityIdle, 0, 128);
  KEY1Handle = osThreadCreate(osThread(KEY1), NULL);

  /* definition and creation of KEY2 */
  osThreadDef(KEY2, key2, osPriorityIdle, 0, 128);
  KEY2Handle = osThreadCreate(osThread(KEY2), NULL);

  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  /* USER CODE END RTOS_THREADS */

}

/* USER CODE BEGIN Header_led1 */
/**
  * @brief  Function implementing the LED1 thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_led1 */
void led1(void const * argument)
{
  /* USER CODE BEGIN led1 */
  /* Infinite loop */
  for(;;)
  {
		printf("led1\n\r");
		HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);
    osDelay(1000);
  }
  /* USER CODE END led1 */
}

/* USER CODE BEGIN Header_led2 */
/**
* @brief Function implementing the LED2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_led2 */
void led2(void const * argument)
{
  /* USER CODE BEGIN led2 */
  /* Infinite loop */
  for(;;)
  {
    printf("led2\n\r");
		HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
    osDelay(500);
  }
  /* USER CODE END led2 */
}

/* USER CODE BEGIN Header_key1 */
/**
* @brief Function implementing the KEY1 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_key1 */
void key1(void const * argument)
{
  /* USER CODE BEGIN key1 */
  /* Infinite loop */
  for(;;)
  {
    if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)==0)
		{
			osDelay(20);//防误触
			if(LED1Handle==NULL)
			{
				printf("key1==creat\n\r");
				osThreadDef(LED1, led1, osPriorityNormal, 0, 128);
				LED1Handle = osThreadCreate(osThread(LED1), (void*)"new task1");
				
			}
			else
			{
				vTaskDelete(LED1Handle);
				LED1Handle=NULL;
				printf("key1==delete\n\r");
			}
		}
  }
  /* USER CODE END key1 */
}

/* USER CODE BEGIN Header_key2 */
/**
* @brief Function implementing the KEY2 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_key2 */
void key2(void const * argument)
{
  /* USER CODE BEGIN key2 */
	char Flag=0;
  /* Infinite loop */
  for(;;)
  {
    if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==0)
		{
			osDelay(20);//防误触
			if(Flag==0)
			{
				printf("key2 suspend\n\r");
				vTaskSuspend(LED2Handle);
				Flag=1;
			}
			else
			{
				vTaskResume(LED2Handle);
				printf("key2  resume \n\r");
				Flag=0;
			}
		}
  }
  /* USER CODE END key2 */
}

/* Private application code --------------------------------------------------*/

注: タスクが削除されてもハンドルは削除されないため、手動でクリアする必要があります。

おすすめ

転載: blog.csdn.net/weixin_45015121/article/details/132218772