リアルタイムOSなしで周期的な処理を追加する件についてです
組込みの開発現場では指定した時間が経過すると指定した処理を実行するという仕組みはよく使われます。一般的にはリアルタイムOSを使用して周期タスクとして登録するのですがそんなに難しく作りたくないという人向けにC言語のソースコードを公開します。 今回の処理は1秒毎に処理するタスクと5秒毎に処理するタスクを2つ登録していますが多少の変更だけで処理数を増やせるようにしています。
#include<stdio.h> #include<stdint.h> #include<windows.h> #define CYCLIC_TIME 10 //基本周期は10ms #define NO_INTEG_TIME 0 //遅延時間 #define CYC_REG 2 //登録したい処理数 enum cyc_ID { cyc_one = 0, cyc_two }; typedef struct { uint8_t nExeFlg[CYC_REG]; //実行フラグ uint16_t nPeriod[CYC_REG]; //実行したい周期 uint16_t nIntegTime[CYC_REG]; //経過時間 void (*nFunc[CYC_REG])(void); //実行する関数 }CYCLIC_T; //周期的に実行する処理その1 void Func1(void) { printf("earth\n"); } //周期的に実行する処理その2 void Func2(void) { printf("sun\n"); } //起動周期の初期化と経過時間の初期化 void SetCycPeriod(CYCLIC_T* cyclic, uint8_t nID, uint16_t nP, uint16_t nI) { cyclic->nExeFlg[nID] = 0; cyclic->nPeriod[nID] = nP * CYCLIC_TIME; //起動したい周期の初期化 cyclic->nIntegTime[nID] = nI; //経過時間の初期化 } //関数の登録 void SetCycFunction(CYCLIC_T* cyclic, uint8_t nID, void(*nF)) { cyclic->nFunc[nID] = nF; } //時間のカウント void SetIntegTime(CYCLIC_T* cyclic) { uint8_t i; //登録した数だけ実行 for (i = 0; i < CYC_REG; i++) { cyclic->nIntegTime[i] += CYCLIC_TIME; } } //経過時間のチェック void ChkTimeCnt(CYCLIC_T* cyclic) { uint8_t i; //登録した数だけ実行 for (i = 0; i < CYC_REG; i++) { if (cyclic->nIntegTime[i] % cyclic->nPeriod[i] == 0) { cyclic->nIntegTime[i] = 0; //経過時間の初期化 cyclic->nExeFlg[i] = 1; //関数起動フラグを立てる } } } //登録した関数の実行 void ExeFunction(CYCLIC_T* cyclic) { uint8_t i; //登録した数だけ実行 for (i = 0; i < CYC_REG; i++) { if (cyclic->nExeFlg[i] == 1) { cyclic->nFunc[i](); //関数の実行 cyclic->nExeFlg[i] = 0; //必ず初期化 } } } int main(void) { CYCLIC_T cyc; //周期の初期化 SetCycPeriod(&cyc, cyc_one, 1000 / CYCLIC_TIME, NO_INTEG_TIME); SetCycPeriod(&cyc, cyc_two, 5000 / CYCLIC_TIME, NO_INTEG_TIME); //関数の定義 SetCycFunction(&cyc, cyc_one, Func1); SetCycFunction(&cyc, cyc_two, Func2); for (;;) { Sleep(CYCLIC_TIME); //時間のカウント SetIntegTime(&cyc); //経過時間のチェック ChkTimeCnt(&cyc); //登録関数の実行 ExeFunction(&cyc); } }