2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FreeRTOS理解その2(ボタン押下によるタスク切換えその1)

Last updated at Posted at 2020-07-11

FreeRTOS実習その2

その1と記載せずだったが、こちらの続き。最初にお断りしておくが、ステキなプログラムではない(改善の余地あり)。

やること

ボタンを押したらタスクが切り替わるプログラムの実現。

使ったもの

スイッチサイエンスさん経由で購入したNucleo-F303RE。ユーザー用ボタンが最初から搭載されているので、、、という単純な理由。

コード

タスク関連宣言

ボタン押下を扱うタスクとLEDオンオフを扱うタスク2つ。

# include <STM32FreeRTOS.h>

const uint8_t Led = LED_BUILTIN;
const uint8_t Btn = USER_BTN;

TaskHandle_t TaskButton_Handler;
TaskHandle_t TaskBlink1_Handler;
TaskHandle_t TaskBlink0_Handler;

void TaskButton(void *pvParameters);
void TaskBlink1(void *pvParameters);
void TaskBlink0(void *pvParameters);

Arduino環境でおなじみ部分

タスク生成など。


void setup() {
  Serial.begin(9600);  
  while (!Serial) {}

  pinMode(Led, OUTPUT);

  xTaskCreate(TaskButton, "Button", 128, NULL, 2, &TaskButton_Handler);
  xTaskCreate(TaskBlink1, "Blink1", 128, NULL, 1, &TaskBlink1_Handler);
  xTaskCreate(TaskBlink0, "Blink0", 128, NULL, 1, &TaskBlink0_Handler);    

  vTaskStartScheduler(); 
}  

void loop() {
  // Empty. Things are done in Tasks.
}

ボタン押下を扱うタスク

void TaskButton(void *pvParameters) {
  (void) pvParameters;
  int pressed = 0;
  
  pinMode(Btn, INPUT);
  vTaskSuspend(TaskBlink1_Handler);  
  vTaskSuspend(TaskBlink0_Handler);  
  for (;;) {
    if (pressed == 0) {
      if (digitalRead(Btn) == LOW){
        Serial.println("Button Pushed for Blink1");
        pressed = 1;
        vTaskSuspend(TaskBlink0_Handler); 
        vTaskResume(TaskBlink1_Handler);
      }
    } else { // pressed == 1
      if (digitalRead(Btn) == LOW){
        Serial.println("Button Pushed for Blink0");
        pressed = 0;
        vTaskSuspend(TaskBlink1_Handler); 
        vTaskResume(TaskBlink0_Handler); 
      }
    }
    vTaskDelay(500/portTICK_PERIOD_MS); // wait for 500ms
  }
}

最初にvTaskSuspend()で2つのLEDタスクを止めてしまう。ボタンが押されたら、2つのタスクを交互に眠らし(vTaskSuspend())、起こす(vTaskResume())。

LEDタスク

2つのタスクの違いは、LED点滅の間隔が異なるだけ。

void TaskBlink1(void *pvParameters) {
  (void) pvParameters;

  for (;;) {
    digitalWrite(Led, HIGH);
    delay(500);
    digitalWrite(Led, LOW);
    delay(500);
    Serial.println("Blink1");
    vTaskDelay(1);
  }
}

void TaskBlink0(void *pvParameters) {
  (void) pvParameters;
  
  for (;;) {
    digitalWrite(Led, HIGH);
    delay(1000);
    digitalWrite(Led, LOW);
    delay(1000);
    Serial.println("Blink0");
    vTaskDelay(1);
  }
}

ボタン押下タスクへの切換えの余地を残すため、vTaskDelay()を用いている。

実験

コンソール上では下記のような感じ。ボタンを押すと切り替わっている。
1stTry.PNG

しかし、、

このプログラムではボタンのチャタリングを防ぐことはできず、ボタンスイッチを押しても(特にすぐに押して離す場合)タスクが切り替わらないことがある。これを解決するのは次回(その3)にて。

参考

FreeRTOS API群

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?