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

Использование драйвера

Как мы уже говорили в главе 5, embedded-hal предоставляет абстракции, с помощью которых можно писать не зависящий от платформы код для работы с оборудованием. Фактически все методы, которыми мы пользовались для работы с оборудованием в главе LED-рулетка и вплоть до этой главы, были методами трейтов, определённых в embedded-hal. Теперь впервые по-настоящему воспользуемся трейтами, которые предоставляет embedded-hal.

Писать драйвер для LSM303AGR под каждую платформу, которую поддерживает встраиваемый Rust (и под новые, которые могут появиться), было бы бессмысленно. Чтобы этого избежать, драйвер можно написать так, чтобы он принимал обобщённые типы, реализующие трейты embedded-hal, — тогда получается не зависящая от платформы версия драйвера. К счастью, это уже сделано в крейте lsm303agr. Поэтому чтение реальных значений акселерометра и магнитометра теперь почти работает по принципу «подключи и пользуйся» (плюс немного чтения документации). На странице crates.io уже есть всё, что нужно, чтобы читать данные акселерометра, — но для Raspberry Pi. Нам остаётся адаптировать этот пример под наш чип:

Посмотрите пример кода для Raspberry Pi под Linux на той странице.

Поскольку мы уже знаем, как создать объект, реализующий трейты embedded_hal::blocking::i2c, из предыдущего раздела, адаптировать пример просто (examples/show-accel.rs):

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

use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};

use microbit::{
    hal::{twim, Timer},
    pac::twim0::frequency::FREQUENCY_A,
};

use lsm303agr::{AccelMode, AccelOutputDataRate, Lsm303agr};

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

    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };
    let mut timer0 = Timer::new(board.TIMER0);

    // Код из документации
    let mut sensor = Lsm303agr::new_with_i2c(i2c);
    sensor.init().unwrap();
    sensor
        .set_accel_mode_and_odr(
            &mut timer0,
            AccelMode::HighResolution,
            AccelOutputDataRate::Hz50,
        )
        .unwrap();
    loop {
        if sensor.accel_status().unwrap().xyz_new_data() {
            let (x, y, z) = sensor.acceleration().unwrap().xyz_mg();
            // RTT вместо обычного print
            rprintln!("Acceleration: x {} y {} z {}", x, y, z);
        }
    }
}

Как и в предыдущем фрагменте, попробовать эту программу можно так:

$ cargo embed --example show-accel

Кроме того, если немного подвигать micro:bit (физически), вы увидите, как меняются выводимые значения ускорения.