# Rust + MicroBit 按钮调试代码

- Link: https://www.ixiqin.com/2020/03/29/rust-microbit-button-debugging-code/
- Published: 2020-03-29T12:34:48+08:00
- Author: 白宦成

```php
    #![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) });
            }
        });
    }

    Code language: PHP (php)
    ```
