概要
Arduinoで使える シリアル入力コマンドパーサーのテンプレートです。
ポイント
コマンドと、そのコマンドに対応する関数をペアにしてリスト化しています。
注意事項
- 関数ポインタを受け入れがたい人にはお勧めしません
- 備忘録的な記事なので、細かい解説は割愛させていただきます
ソースコード
- "on+改行"を入力するとLedOn()関数が呼ばれてLEDが点灯
- "off+改行"を入力するとLedOff()関数が呼ばれてLEDが消灯
- "reset+改行"を入力するとReset()関数が呼ばれてリセットベクタに飛びます
void LedOn(){
Serial.println("LED is ON");
digitalWrite(LED_BUILTIN, HIGH);
}
void LedOff(){
Serial.println("LED is OFF");
digitalWrite(LED_BUILTIN, LOW);
}
void Reset(){
asm volatile("jmp 0"); //リセットベクタ(0番地)に飛ぶ
}
//======================================================================
//
//======================================================================
typedef void (*pFunc)(void);
//コマンド文字列と関数ポインタをセットにした構造体
struct Command {
String name; //コマンド文字列
pFunc action; //対応する関数へのポインタ
};
//----------------------------------
//コマンドと対応する関数のリスト
//----------------------------------
Command CommandList[] = {
{"on" , &LedOn},
{"off", &LedOff},
{"reset", &Reset},
};
const int CommandCount = sizeof(CommandList) / sizeof(CommandList[0]); // コマンドの数
String SerialBuffer = "";//シリアル受信バッファ
//==================================================================
//初期設定
//==================================================================
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
Serial.begin(115200);//
Serial.println("--- START PROGRAM ---");
}
//==================================================================
//メインループ
//==================================================================
void loop() {
CommandCheck();
}
//-------------------------------------------------------------------------------
//シリアルコマンドのチェック
// シリアル受信した文字を文字列に詰めていく、改行コードが来たらコマンド解析を実行
//-------------------------------------------------------------------------------
void CommandCheck() {
while(Serial.available()>0){
char rx = Serial.read();//1バイト読込
Serial.write(rx);//エコーバック
if (rx == '\n' || rx == '\r') {// 改行コードでコマンドパース実行
CommandParse(SerialBuffer);
SerialBuffer = ""; // バッファをクリア
return;
}
SerialBuffer += rx; //バッファに追加
}//while
}
//-------------------------------------------------------------------------------
//コマンド解析
// 受信コマンドとコマンドリストをループしながら比較、一致したら関数ポインタで関数を呼ぶ
//-------------------------------------------------------------------------------
void CommandParse(String command) {
command.trim(); // 前後の空白を削除
for (int i = 0; i < CommandCount; i++) {
if (command.equalsIgnoreCase(CommandList[i].name)) {
(void) (*CommandList[i].action)(); // 対応する関数を呼び出し
return;
}
}//for
Serial.println("Unknown command.");
}