皆さん こんにちは。
今回はタイマーを使ってみます。
タイマーの例が こちら に出ていたので参考にしてみました。
hardware_timerの方にはインターバルタイマーのAPIらしきものが見当たりませんでした。
今回は High Level APIs の中の pico_time の repeating_timer を使います。
High Level API ということで2つのヘッダをインクルードする必要があるようです。
#include <stdio.h>
#include "pico/stdlib.h"
プロジェクトをつくる
プロジェクトのつくり方や、VSCodeの起動方法等については省略します。
それぞれについて、わからない方は ラズピコ VSCode + Picoprobe でデバッグ環境を構築する の記事をご覧になってください。
ちょっと手順がややこしいので慣れるまで辛抱してください。
Project Name: picoTimer
Console Options の Console over UART のチェックをはずす
IDE Options の Create VSCode project をチェックする
Debugger: は PicoProbe を選択する

VSCodeを起動する
起動後、何かファイルが開いてたら File – Close Folder で閉じた後、File – Open Folder から picoTimer のフォルダーを辿って選択します。
こちらの環境では C:\Users\m3925\Documents\Pico\pico-project-generator\picoTimer です。
m3925の部分は皆さんのユーザー名に置き換えてください。
vscode関連の json ファイルは前回作成済のプロジェクトのものをドラッグ&ドロップでコピー&ペーストすると楽ができます。
ソースコードを書く
VSCodeのツリーから picoTimer.c を選択して次のように編集し、保存します。
#include <stdio.h>
#include "pico/stdlib.h"
#define LED_PIN 25
bool repeating_timer_callback(struct repeating_timer *t) {
gpio_put(LED_PIN, 1);
busy_wait_ms(1000);
gpio_put(LED_PIN, 0);
return true;
}
int main()
{
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, true);
struct repeating_timer timer;
add_repeating_timer_ms(-2000, repeating_timer_callback, NULL, &timer);
while (true) {
;
}
return 0;
}
デバッグ開始
それでは接続に問題がないことを確認した後、Run – Start Debugging を選択します。
main()のところでカーソルが停止するので、F5キーを押してプログラムを動作させます。
正しく動作すると、LEDが1秒周期で点滅します。
解説
今回出てきたAPIは add_repeating_timer_ms() です。
第1引数:間隔をmsec単位で指定します。この時数値にマイナスの符号をつけると、関数の始まりから次の始まりまでの間隔指定になります。
また符号をつけないと、関数の終わりから次の始まりまでの間隔指定になります。
第2引数:repeating_timer_callback_t型の関数を指定します。
*repeating_timer_callback_t型は以下の通りに宣言されている関数ポインタです。
typedef bool(* repeating_timer_callback_t) (repeating_timer_t *rt)
第3引数:コールバックが使うためにrepeating_timer構造体に格納するために渡すユーザーデータ(ポインタ型)
ここでは使わないので NULL を指定しています。
第4引数:repeating_timer構造体変数へのポインタ。
この変数はrepeating_timerより寿命が長くなければなりません。
関数が終了してしまうようなスタック変数に割り当てないように注意してください。
(ここで main()関数は終了しないので問題なし)
プログラムが終了してしまわないように、while(true)で動かし続けておきます。
Lチカの動作は割り込みサービスルーチンのみが実行することになります。
add_repeating_timer_us() というμsecバージョンの関数もあるようです。
高速のタイマーを使いたい場合に試してみてください。
インターバルをかえてみる
add_repeating_timer_ms()の第1引数を 2000 に変更して(マイナスの符号をとって)動作させてみます。
プログラムを動作させると、点灯の期間が1秒消灯の期間が2秒になりました。
符号がない場合には、関数の終わりから次の始まりまでの間隔指定になることがわかりました。
通常は始まりから始まりのインターバルで使うものと思われますが、その時にマイナスの符号をつけることが何だかピンときません。
それから動作確認のためにコールバック関数の中で、busy_wait_ms()を使っていますが、通常は割り込みサービスルーチン内で時間待ちをしないように設計してください。
いかがでしたか?
うまく動作しましたか?
お疲れさまでした。