Rust + MicroBit 按钮调试代码

#![no_main]
#![no_std]

use panic_halt;

use microbit::hal::nrf51::{interrupt, GPIOTE, UART0};
use microbit::hal::prelude::*;
use microbit::hal::serial;
use microbit::hal::serial::BAUD115200;

use cortex_m::interrupt::Mutex;
use cortex_m::peripheral::Peripherals;
use cortex_m_rt::entry;

use core::cell::RefCell;
use core::fmt::Write;
use core::ops::DerefMut;

static GPIO: Mutex<RefCell<Option<GPIOTE>>> = Mutex::new(RefCell::new(None));
static TX: Mutex<RefCell<Option<serial::Tx<UART0>>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    if let (Some(p), Some(mut cp)) = (microbit::Peripherals::take(), Peripherals::take()) {
        // 引入两个版本的外设
        cortex_m::interrupt::free(move |cs| {
            /* 开启外部设备的 GPIO 中断 */
            cp.NVIC.enable(microbit::Interrupt::GPIOTE);

            microbit::NVIC::unpend(microbit::Interrupt::GPIOTE);

            /* 切分 GPIO 口,方便使用 */
            let gpio = p.GPIO.split();

            /* 将 Button 的 IO 口作为输入 IO 口 */
            let _ = gpio.pin26.into_floating_input();
            let _ = gpio.pin17.into_floating_input();

            /* 当 GPIO 17 ( A 键)出现了下降沿的时候,触发中断 */
            p.GPIOTE.config[0]
                .write(|w| unsafe { w.mode().event().psel().bits(17).polarity().hi_to_lo() });
            p.GPIOTE.intenset.write(|w| w.in0().set_bit());
            p.GPIOTE.events_in[0].write(|w| unsafe { w.bits(0) });

            /* 当 GPIO 26 (B键)出现了下降沿的时候,触发中断 */
            p.GPIOTE.config[1]
                .write(|w| unsafe { w.mode().event().psel().bits(26).polarity().hi_to_lo() });
            p.GPIOTE.intenset.write(|w| w.in1().set_bit());
            p.GPIOTE.events_in[1].write(|w| unsafe { w.bits(0) });

            *GPIO.borrow(cs).borrow_mut() = Some(p.GPIOTE);

            /* 根据需要,设置 GPIO 口作为输入输出口 */
            let tx = gpio.pin24.into_push_pull_output().downgrade();
            let rx = gpio.pin25.into_floating_input().downgrade();

            /* 将准备的 GPIO 口作为串口来使用 */
            let (mut tx, _) = serial::Serial::uart0(p.UART0, tx, rx, BAUD115200).split();

            let _ = write!(
                tx,
                "\n\rWelcome to the buttons demo. Press buttons A and/or B for some action.\n\r",
            );
            *TX.borrow(cs).borrow_mut() = Some(tx);
        });
    }

    loop {
        continue;
    }
}

// 定义一个中断(如果函数出现了错误,就会触发中断),当我从按钮按下接收到了一个中断,这个函数就会被调用。
#[interrupt]
fn GPIOTE() {
    /* 进入中断内部的内容 */
    cortex_m::interrupt::free(|cs| {
        if let (Some(gpiote), &mut Some(ref mut tx)) = (
            GPIO.borrow(cs).borrow().as_ref(),
            TX.borrow(cs).borrow_mut().deref_mut(),
        ) {
            let buttonapressed = gpiote.events_in[0].read().bits() != 0; // 识别出 A 键按下
            let buttonbpressed = gpiote.events_in[1].read().bits() != 0; // 识别出 B 键按下

            /* 将按钮打印到串口中 */
            let _ = write!(
                tx,
                "Button pressed {}\n\r",
                match (buttonapressed, buttonbpressed) {
                    (false, false) => "",
                    (true, false) => "A",
                    (false, true) => "B",
                    (true, true) => "A + B",
                }
            );

            /* 清空事件 */
            gpiote.events_in[0].write(|w| unsafe { w.bits(0) });
            gpiote.events_in[1].write(|w| unsafe { w.bits(0) });
        }
    });
}

作者:Bestony

Generalist, contact me at bestony@linux.com

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注