シリーズ:実験シリーズ(フェーズ2)
対応ロードマップ:フェーズ2 / E2-03
今回の役割:E2-02で作った1msの時刻を使い、delayに頼らずに一定周期で処理を実行する基本形を作る。
1. 目的
今回は、1msごとに増えるカウンタを使って、500msたったらLEDを切り替える 実験を行います。
これにより、delay で待つのではなく、時間を数えて周期的に動く処理 の基本を作るのが目的です。
2. 前提・環境
- 評価ボード:RTK7EKA8M2S00001BE
- 開発環境:e² studio + FSP
- 前提
- E1-02:点滅周期を変える(定数→変数)ができている
- E2-01:delayの限界を体験(他処理できない)ができている
- E2-02:タイマで1ms毎にカウントアップするストップウォッチを作る ができている
- 今回使うもの
- 評価ボード本体
- オンボードLED
- 今回の考え方
- E2-02 で作った 1msごとに増えるカウンタ を使う
- そのカウンタを見て、「500msたったらLEDを反転する」という処理を書く
3. 今回の変更点
3-1. 配線変更
- なし
- 評価ボードのオンボードLEDをそのまま使います
3-2. 設定変更
- なし(E2-02のまま)
- 1ms周期のタイマ設定をそのまま使います
3-3. コード変更
E1-02 では、R_BSP_SoftwareDelay() を使ってLEDを点滅させました。
E2-02 では、1msごとに増える時刻を作りました。
今回はその2つを合わせて、LED点滅を delay ではなくタイマを使って動かす 形に変えます。
4. 手順
4-1. まず今回やりたいことを日本語で整理する
今回は次の流れです。
- タイマの割り込みで、1msごとにカウンタを増やす
- 繰り返しの処理(メインループ)中には止まらず、ずっと繰り返す
- 500ms たっていたら、LEDを反転する
- カウンタを0クリアして、これを繰り返す
ここで大事なのは、「500ms待つ」のではなく、「500msたったかどうかを確認する」 ことです。
4-2. 考え方:delay と何が違うか
delay(500ms) を使うと、その 500ms の間、CPUは待ち続けます。
一方で今回のやり方は、繰り返しの処理を続けながら
- まだ500msたっていない → 今回は何もしない
- 500ms経過した → LEDを切り替える
という形にします。
つまり、CPUは「止まって待つ」のではなく、タイマを見て判断する ようになります。
4-3. 今回の考え方
今回は、LED用として 500msカウンタ を1つ持ちます。
- 1msごとに
g_blink_count_msを増やす - 500になったらLEDを反転する
- 反転したら
g_blink_count_msを0に戻す
この形なら、
- 1msが500回たまる
- だから500msたった
と考えられます。
4-4. FSP設定を確認する
今回は E2-02 の設定をそのまま使います。
E2-02で設定した概要は次の通りです。
- FSP Configurator(
configuration.xml)を開く - 1ms周期のタイマが設定されていることを確認する
- コールバック関数が設定されていることを確認する
- 「Generate Project Content」を実行する
※今回はタイマ設定の追加ではなく、E2-02で作った1msタイマを使って周期処理を作ること です。
5. コード
5-1. 考え方
今回のコードでやることは、次の4つです。
- 1msタイマのコールバックで
g_blink_count_msを 1msごとに増やす - 繰り返し処理(メインループ)で
g_blink_count_msを読む - 500ms経過していたらLEDを反転する
g_blink_count_msを0クリアして、次の500msをカウントする
5-2. コード例
※オンボードLEDのピン名は、これまでの実験で使っているものに合わせてください。
※下の例では、以前と同じく BSP_IO_PORT_06_PIN_00 を使っています。
※タイマ名やコールバック名は、FSPで生成された名前に合わせて読み替えてください。
#include "hal_data.h"
#include <stdbool.h>
#include <stdint.h>
volatile uint32_t g_blink_count_ms = 0;
volatile bool g_blink_500ms_flag = false;
void timer0_callback(timer_callback_args_t * p_args)
{
FSP_PARAMETER_NOT_USED(p_args);
g_blink_count_ms++;
if (g_blink_count_ms >= 500)
{
g_blink_count_ms = 0;
g_blink_500ms_flag = true;
}
}
void hal_entry(void)
{
fsp_err_t err;
bool led_on = false;
/* 1msタイマ開始 */
err = R_AGT_Open(&g_timer0_ctrl, &g_timer0_cfg);
if (FSP_SUCCESS != err)
{
while (1)
{
}
}
err = R_AGT_Start(&g_timer0_ctrl);
if (FSP_SUCCESS != err)
{
while (1)
{
}
}
while (1)
{
if (g_blink_500ms_flag)
{
g_blink_500ms_flag = false;
led_on = !led_on;
if (led_on)
{
R_BSP_PinWrite(BSP_IO_PORT_06_PIN_00, BSP_IO_LEVEL_HIGH);
}
else
{
R_BSP_PinWrite(BSP_IO_PORT_06_PIN_00, BSP_IO_LEVEL_LOW);
}
}
/* ここは空でもよい
将来はこの中にボタン監視やログ出力などを追加できる */
}
}5-3. このコードで見てほしいポイント
1) g_blink_count_ms は500msを数えるカウンタ
この変数は、1msごとに1ずつ増えます。
そして 500 になったら、
- 500msたった
- だからLEDを切り替えてよい
と判断します。
2) 500になったら0へ戻す
今回は初心者向けに分かりやすくするため、
500msカウンタ方式 にしています。
つまり、
- 0から数える
- 500になったら動く
- また0から数える
という形です。
3) 割り込みの中ではLEDを直接切り替えない
今回は、割り込みの中では
- カウントを増やす
- 500msたったらフラグを立てる
だけにしています。
実際のLED切り替えはメインループ側で行います。
6. 実行結果
- オンボードLEDが 約500msごとに点灯/消灯 した
delayを使っていないのに、一定周期で点滅した- メインループが止まっていないので、今後ここへ別の処理を足せる形になった
7. 今回わかったこと
今回の実験で一番大事なのは、次の1点です。
- 時間になったら動く、という書き方にすると、待ち時間でもプログラム全体が止まらない
8. ハマりポイント/原因と対策
8-1. LEDがまったく点滅しない
原因
- タイマが開始できていない
- コールバック関数が呼ばれていない
- LEDピン名が違う
対策
R_AGT_Open()とR_AGT_Start()の戻り値を確認するtimer0_callback()が正しく登録されているか確認する- これまでの実験と同じオンボードLEDピンを使っているか確認する
8-2. LEDが1回だけ変わって止まる
原因
- フラグをfalseにしていない
- カウンタを0クリアしていない
- コールバックが継続して呼ばれていない
対策
g_blink_500ms_flag = false;が記述されているか確認するg_blink_count_ms = 0;が記述されているか確認するg_blink_count_msが増え続けているかデバッガで見る
8-3. g_blink_count_ms が増えない
原因
- タイマの開始に失敗している
- コールバック名がFSP設定と合っていない
- 割り込み設定が入っていない
対策
- FSPで生成されたタイマ名が
g_timer0か確認する - コールバック名が
timer0_callbackになっているか確認する - Generate後の名前とコード中の名前が一致しているか確認する
8-4. 周期が不安定に見える
原因
- タイマ周期が1msになっていない
- ほかの重い処理を入れている
対策
- E2-02 の設定が 1ms周期になっているか見直す
- まずはLED反転だけの最低限のシンプルなコードで確認する
9. 次回やること
次は、E2-04 複数周期タスク(例:A=100ms / B=700ms) に進みます。
1つの時刻を使って、複数の周期処理を同時に動かす形へ広げます。
10. 関連リンク
- E2-01 delayの限界を体験(他処理できない)(リンク)
- E2-02 タイマで1ms毎にカウントアップするストップウォッチを作る(リンク)
- E2-04 複数周期タスク(例:A=100ms/B=700ms)(リンク)
- 基礎:組み込み開発とは(リンク)
- 基礎:マイコン(RA8M2):はじめに読む(リンク)
- 基礎:C言語のはじめ(LED点滅で必要なところだけ)(リンク)