Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

点滅します

遅延

ここでは、embedded-hal が提供する遅延抽象化について簡単に見ていきます。 その後、これを前の章で扱った GPIO 抽象化と組み合わせて、 最終的に LED を点滅させます。

embedded-hal は、プログラムの実行を遅らせるための 2 つの抽象化を提供しています: DelayUsDelayMs です。これらは本質的にはまったく同じように動作しますが、 遅延関数が受け取る単位が異なります。

MCU の内部には、「タイマー」と呼ばれるものがいくつか存在します。これらは時間に関するさまざまな処理を行えますが、 そのひとつとして、プログラムの実行を一定時間だけ単純に停止させることができます。たとえば、 1 秒ごとに何かを出力する非常にシンプルな遅延ベースのプログラムは、次のようになります:

#![deny(unsafe_code)]
#![no_main]
#![no_std]

use cortex_m_rt::entry;
use rtt_target::{rtt_init_print, rprintln};
use panic_rtt_target as _;
use microbit::board::Board;
use microbit::hal::timer::Timer;
use microbit::hal::prelude::*;

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let mut board = Board::take().unwrap();

    let mut timer = Timer::new(board.TIMER0);

    loop {
        timer.delay_ms(1000u16);
        rprintln!("1000 ms passed");
    }
}

ここでは panic 実装を panic_halt から panic_rtt_target に変更していることに注意してください。これにより、 Cargo.toml の RTT に関する 2 行のコメントを外し、 panic-halt の行をコメントアウトする必要があります。 これは、Rust では同時に 1 つの panic 実装しか使えないためです。

実際に出力を確認するには、Embed.toml を次のように変更する必要があります:

[default.general]
# micro:bit V2 の場合はこの行のコメントを外します
# chip = "nrf52833_xxAA" # uncomment this line for micro:bit V2
# micro:bit V1 の場合はこの行のコメントを外します
# chip = "nrf51822_xxAA" # uncomment this line for micro:bit V1

[default.reset]
halt_afterwards = false

[default.rtt]
enabled = true

[default.gdb]
enabled = false

そして、このコードを src/main.rs に書き込み、もう一度すばやく cargo embed を実行すると (前と同じフラグを再び使ってください)、 MCU から毎秒 “1000 ms passed” がコンソールに送られてくるはずです。

点滅

ここまでで、GPIO と遅延抽象化について新たに学んだ知識を組み合わせて、 micro:bit の背面にある LED を実際に点滅させる準備が整いました。できあがるプログラムは、 実際には上のものと、前のセクションで LED を点灯させたものを 組み合わせたものにすぎず、次のようになります:

#![deny(unsafe_code)]
#![no_main]
#![no_std]

use cortex_m_rt::entry;
use rtt_target::{rtt_init_print, rprintln};
use panic_rtt_target as _;
use microbit::board::Board;
use microbit::hal::timer::Timer;
use microbit::hal::prelude::*;

#[entry]
fn main() -> ! {
    rtt_init_print!();
    let mut board = Board::take().unwrap();

    let mut timer = Timer::new(board.TIMER0);

    board.display_pins.col1.set_low().unwrap();
    let mut row1 = board.display_pins.row1;

    loop {
        row1.set_low().unwrap();
        rprintln!("Dark!");
        timer.delay_ms(1_000_u16);
        row1.set_high().unwrap();
        rprintln!("Light!");
        timer.delay_ms(1_000_u16);
    }
}

このコードを src/main.rs に書き込み、最後に cargo embed を実行すると (適切なフラグを付けてください)、 点滅させる前に点灯した LED に加えて、LED が消灯から点灯へ、またはその逆へ切り替わるたびに 出力も表示されるはずです。