Zephyr移植精英板第十五章 按键输入实验
思路依然是看说明文档和例程,本文仅提供参考,务必自己从翻文档开始,自己完成实验结果。
一、新建新工程
参考下图指令复制上一个工程到lab_3,中间build 报错,因为没清除上一个工程的build,清除掉重编译即可。
二、参考驱动和驱动说明文档修改设备树文件
注意研读以下说明文档的“顶层节点属性”部分。我这里选择轮询模式。
设备树参考:
/dts-v1/; #include <st/f1/stm32f103Xe.dtsi> #include <st/f1/stm32f103z(c-d-e)tx-pinctrl.dtsi> #include <zephyr/dt-bindings/input/input-event-codes.h> / { model = "alientek jingying stm32f103ze board"; compatible = "alientek,stm32f103ze"; chosen { zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; }; aliases { leds = &leds; buzzer = &buzzer; }; // 格式:【标签:】节点名 { 属性 }; leds: leds { compatible = "gpio-leds"; led_0: led_0 { gpios = <&gpiob 5 GPIO_ACTIVE_LOW>; label = "LED 0"; }; led_1: led_1 { gpios = <&gpioe 5 GPIO_ACTIVE_LOW>; label = "LED 1"; }; }; buzzer: buzzer { compatible = "gpio-buzzer"; gpios = <&gpiob 8 GPIO_ACTIVE_HIGH>; status = "okay"; }; buttons { compatible = "gpio-keys"; debounce-interval-ms = <50>; // 同时是轮询周期 polling-mode; zephyr,suspend-action = "none"; //系统进入休眠(suspend)的时候,这个按键对应的 GPIO 引脚,驱动什么都不改,保持休眠前的配置原样不动。 key_up { gpios = <&gpioa 0 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; zephyr,code = <INPUT_KEY_UP>; }; key0 { gpios = <&gpioe 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; zephyr,code = <INPUT_KEY_0>; }; key1 { gpios = <&gpioe 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; zephyr,code = <INPUT_KEY_1>; }; }; }; &clk_lsi { status = "okay"; }; &clk_hse { clock-frequency = <DT_FREQ_M(8)>; status = "okay"; }; &pll { mul = <9>; clocks = <&clk_hse>; status = "okay"; }; &rcc { clocks = <&pll>; clock-frequency = <DT_FREQ_M(72)>; ahb-prescaler = <1>; apb1-prescaler = <2>; apb2-prescaler = <1>; }; &usart1 { pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; pinctrl-names = "default"; current-speed = <115200>; status = "okay"; }; &usart2 { pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; pinctrl-names = "default"; current-speed = <115200>; status = "okay"; }; &usart3 { pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; pinctrl-names = "default"; current-speed = <115200>; }; &i2c1 { pinctrl-0 = <&i2c1_scl_remap1_pb8 &i2c1_sda_remap1_pb9>; pinctrl-names = "default"; status = "okay"; clock-frequency = <I2C_BITRATE_FAST>; }; &spi1 { pinctrl-0 = <&spi1_sck_master_pa5 &spi1_miso_master_pa6 &spi1_mosi_master_pa7>; pinctrl-names = "default"; cs-gpios = <&gpiob 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; status = "okay"; }; &spi2 { pinctrl-0 = <&spi2_nss_master_pb12 &spi2_sck_master_pb13 &spi2_miso_master_pb14 &spi2_mosi_master_pb15>; pinctrl-names = "default"; status = "okay"; }; &timers1 { st,prescaler = <10000>; status = "okay"; pwm1: pwm { status = "okay"; pinctrl-0 = <&tim1_ch1_pwm_out_pa8>; pinctrl-names = "default"; }; }; &timers2 { st,prescaler = <255>; status = "okay"; pwm2: pwm { status = "okay"; pinctrl-0 = <&tim2_ch2_pwm_in_pa1>; pinctrl-names = "default"; }; }; &iwdg { status = "okay"; }; &rtc { clocks = <&rcc STM32_CLOCK(APB1, 28)>, <&rcc STM32_SRC_LSI RTC_SEL(2)>; status = "okay"; }; &adc12_common { status = "okay"; }; &die_temp { status = "disabled"; }; &dma1 { status = "okay"; };我删除了原来与pa0冲突的引脚,同时让temp休眠,因为要用到冲突的adc。
三、参考例程 编写main.c 和 prj.conf
参考例程如下:
对上一章例程进行修改:
main.c:
#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/sys/printk.h> #include <zephyr/drivers/led.h> #include <zephyr/drivers/buzzer.h> #include <zephyr/input/input.h> #define BUZZER_NODE DT_ALIAS(buzzer) BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(BUZZER_NODE), "No default buzzer specified in DT"); #define LED_DEV_NODE DT_PATH(leds) BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(LED_DEV_NODE), "leds node not found"); // 边沿缓存 static uint8_t last_key_up = 0; static uint8_t last_key0 = 0; static uint8_t last_key1 = 0; // 独立状态变量 static bool buzzer_en = false; static bool led0_on = false; static bool led1_on = false; static void button_input_cb(struct input_event *evt, void *user_data) { if (evt->type != INPUT_EV_KEY) { return; } switch (evt->code) { case INPUT_KEY_UP: if (last_key_up == 0 && evt->value == 1) { buzzer_en = !buzzer_en; } last_key_up = evt->value; break; case INPUT_KEY_0: if (last_key0 == 0 && evt->value == 1) { led0_on = !led0_on; led1_on = !led1_on; } last_key0 = evt->value; break; case INPUT_KEY_1: if (last_key1 == 0 && evt->value == 1) { led1_on = !led1_on; } last_key1 = evt->value; break; default: break; } } INPUT_CALLBACK_DEFINE(NULL, button_input_cb, NULL); int main(void) { const struct device *buzzer = DEVICE_DT_GET(BUZZER_NODE); const struct device *leds_dev = DEVICE_DT_GET(LED_DEV_NODE); if (!device_is_ready(buzzer)) { return -ENODEV; } if (!device_is_ready(leds_dev)) { return -ENODEV; } while (1) { if (buzzer_en) { buzzer_beep(buzzer, BUZZER_DURATION_FOREVER); } else { buzzer_stop(buzzer); } if (led0_on) { led_on(leds_dev, 0); } else { led_off(leds_dev, 0); } if (led1_on) { led_on(leds_dev, 1); } else { led_off(leds_dev, 1); } k_msleep(50); } return 0; }prj.conf:
# Copyright (c) 2021 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 # # This file contains selected Kconfig options for the application. CONFIG_SENSOR=y CONFIG_GPIO=y CONFIG_INPUT=y CONFIG_LED=y CONFIG_BUZZER=y CONFIG_PRINTK=y CONFIG_LOG=y个人学习笔记,水平有限,内容仅供参考,欢迎评论区交流指正。