<前の記事 : 次の記事>
GPIO出力
GPIO出力のわかりやすい例はpico-exampleのblinkではなくblink-simpleだ。LEDをチカっとさせるだけなのにちょっと冗長な書き方ではあるが、初期化して出力を決めて1か0を出力するだけだ。
今回のデモボードにはGP6からGP13まで8つのLEDをつないである。これを流れるように点灯させてみよう。
#include "pico/stdlib.h"
int main() {
uint32_t cnt=1;
for(int i = 6; i < 14; i++) {
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
}
while (true) {
gpio_put_masked(0xff << 6, cnt<< 6);
cnt=(cnt<<1) & 0xff;
if(cnt == 0) cnt = 1;
sleep_ms(125);
}
}
変数cntのビットが立っているところがLEDを点灯させる。1灯だけならgpio_putでいいが、gpio_put_maskedを使うと同期的に一度にセットできる。
インターバルタイマー
上のコードではsleep_msで点灯タイミングを決めているが、インターバルタイマーで点灯タイミングを制御する場合が以下のようになる。
#include "pico/stdlib.h"
#include "hardware/timer.h"
#include "hardware/sync.h"
repeating_timer_t timer;
bool repeating_timer_callback(struct repeating_timer *t) {
static uint32_t cnt = 1;
gpio_put_masked(0xFF << 6, cnt << 6);
cnt=(cnt<<1) & 0xff;
if(cnt == 0) cnt = 1;
return true;
}
int main() {
for(int i = 6; i < 14; i++) {
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
}
add_repeating_timer_us(-62500, repeating_timer_callback, NULL, &timer);
while (true) __wfe();
}
- タイマーを使うために
hardware/timer.hをインクルード repeating_timer_tとしてtimerを用意repeating_timer_callback関数を書く- 初期化の際に
add_repeating_timer_usを呼ぶ
インターバルの値を負にすると指定時間毎の呼び出し、正にすると処理が終わってから次の呼び出しまでの時間になる。なおメインの無限ループwhile(true) __wfe();は省電力ループであり、while(true):とすると普通に全力ループになる。この__wfe();を使うためだけにhardware/sync.hをインクルードしているわけで、使っても使わなくてもあまり変わらないかもしれない。
GPIO入力
アクティブハイのタッチスイッチをGP14に繋いで、押している時と押してない時で8連LEDが流れる方向を変えてみる。物理スイッチの場合はプルアップの必要があるが、タッチスイッチは単純にhighまたはlowを出すのでシンプルだ。
#include "pico/stdlib.h"
int main() {
uint32_t cnt=1;
bool dir=false;
for(int i = 6; i < 14; i++) {
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
}
gpio_init(14);
gpio_set_dir(14, GPIO_IN);
while (true) {
dir=gpio_get(14);
gpio_put_masked(0xff << 6, cnt<< 6);
cnt=(dir)?(cnt<<1)&0xff:(cnt>>1)&0xff;
if(cnt==0) cnt=(dir)?1:0x80;
sleep_ms(125);
}
}
物理スイッチを使ってプルアップまたはプルダウンしたい時はgpio_pull_upまたはgpio_pull_upを使う。ちなみにどっちでもない場合はgpio_disable_pullsなんだが、ちょっとわかりにくくないか?
スイッチ状態を調べるにはgpio_getを使えば良くて、boolを返してくるので方向dirに直接入れられる。
スイッチ割り込み
なんでもかんでも割り込みにするのは良くないかもしれないが、スイッチ割り込みはよく使う方だろう。昇りエッジで正方向、降りエッジで反対方向に8連LEDが流れるようにした。ソフトウェアではスイッチの状態を一度も読んでない。物理スイッチの場合はチャタリングで酷いことになりそうだ。
#include "pico/stdlib.h"
bool dir=false;
void gpio_callback(uint gpio, uint32_t events) {
if (gpio == 14) {
if (events & GPIO_IRQ_EDGE_RISE) dir=true;
if (events & GPIO_IRQ_EDGE_FALL) dir=false;
}
}
int main() {
uint32_t cnt=1;
for(int i=6;i<14;i++) {
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
}
gpio_init(14);
gpio_set_dir(14, GPIO_IN);
gpio_set_irq_enabled_with_callback(
14,
GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL,
true,
&gpio_callback
);
while (true) {
gpio_put_masked(0xff << 6, cnt<< 6);
cnt=(dir)?(cnt<<1)&0xff:(cnt>>1)&0xff;
if(cnt==0) cnt=(dir)?1:0x80;
sleep_ms(125);
}
}
要はgpio_callback関数を用意してgpio_set_irq_enabled_callback(長い)を作法に基づいて設定してやればいいだけだ。タイマー割り込みをこれに加えてもいい。
長くなったので今回はここまで。
<前の記事 : 次の記事>
投稿者の人気記事

-
akira.kei
さんが
昨日の1:27
に
編集
をしました。
(メッセージ: 初版)
-
akira.kei
さんが
昨日の11:36
に
編集
をしました。
ログインしてコメントを投稿する