【瑞萨RA × Zephyr评测】LED、按键和UART

电子说

1.4w人已加入

描述

硬件: Renesas FPB-RA6E2 + 板载 LED 和按键
目标: 实现按键控制 LED 的开关状态,并通过 UART 输出按键事件日志,验证 GPIO 和串口通信功能。


1. 硬件连接与引脚定义

包含 GPIO 输入输出功能与 UART 数据传输引脚。

功能物理引脚 (Pin)信号定义接线说明
按键输入P304Digital In (SW0)板载按键无需接线
LED 输出P207Digital Out (LED0)板载 LED 无需接线
UART 发送P411UART TX连接到调试器
UART 接收P410UART RX连接到调试器

2. 软件环境配置


2.1 Device Tree Overlay (app.overlay)

必须明确指定 GPIO 和 UART 的物理引脚绑定,并开启外设状态。

chosen {
    zephyr,console = &uart0;    /* in externalzephyrboardsrenesasfpb_ra6e2fpb_ra6e2.dts:22 */
    zephyr,shell-uart = &uart0; /* in externalzephyrboardsrenesasfpb_ra6e2fpb_ra6e2.dts:23 */
};

/* GPIO 配置 */
leds {
    compatible = "gpio-leds";
    led1: led1 {
        gpios = < &ioport2 7 GPIO_ACTIVE_HIGH >;
        label = "LED1";
    };
    led2: led2 {
        gpios = < &ioport2 6 GPIO_ACTIVE_HIGH >;
        label = "LED2";
    };
};

buttons {
    compatible = "gpio-keys";
    button0: s1 {
    gpios = < &ioport3 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW) >;
    label = "Push button switch 1";
        zephyr,code = < INPUT_KEY_0 >;
    };
};

/* UART 配置 */
&uart0 {
    status = "okay";
    pinctrl-0 = < &uart0_default >;
    pinctrl-names = "default";
    current-speed = < 115200 >; /* 波特率设置 */
};
};
};

2.2 Kconfig 配置 (prj.conf)

确保启用了 GPIO 和 UART 驱动支持。

CONFIG_GPIO=y
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y

3. 代码逻辑分析

3.1 主程序代码(main.c)

/*
 * Copyright (c) 2016 Open-RnD Sp. z o.o.
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * NOTE: If you are looking into an implementation of button events with
 * debouncing, check out `input` subsystem and `samples/subsys/input/input_dump`
 * example instead.
 */

#include < zephyr/kernel.h >
#include < zephyr/device.h >
#include < zephyr/drivers/gpio.h >
#include < zephyr/sys/util.h >
#include < zephyr/sys/printk.h >
#include < inttypes.h >

#define SLEEP_TIME_MS	1

/*
 * Get button configuration from the devicetree sw0 alias. This is mandatory.
 */
#define SW0_NODE	DT_ALIAS(sw0)
#if !DT_NODE_HAS_STATUS_OKAY(SW0_NODE)
#error "Unsupported board: sw0 devicetree alias is not defined"
#endif
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios,
							      {0});
static struct gpio_callback button_cb_data;

/*
 * The led0 devicetree alias is optional. If present, we'll use it
 * to turn on the LED whenever the button is pressed.
 */
static struct gpio_dt_spec led = GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios,
						     {0});

void button_pressed(const struct device *dev, struct gpio_callback *cb,
		    uint32_t pins)
{
	printk("Button pressed at %" PRIu32 "n", k_cycle_get_32());
}

int main(void)
{
	int ret;

	if (!gpio_is_ready_dt(&button)) {
		printk("Error: button device %s is not readyn",
		       button.port- >name);
		return 0;
	}

	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret != 0) {
		printk("Error %d: failed to configure %s pin %dn",
		       ret, button.port- >name, button.pin);
		return 0;
	}

	ret = gpio_pin_interrupt_configure_dt(&button,
					      GPIO_INT_EDGE_TO_ACTIVE);
	if (ret != 0) {
		printk("Error %d: failed to configure interrupt on %s pin %dn",
			ret, button.port- >name, button.pin);
		return 0;
	}

	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);
	printk("Set up button at %s pin %dn", button.port- >name, button.pin);

	if (led.port && !gpio_is_ready_dt(&led)) {
		printk("Error %d: LED device %s is not ready; ignoring itn",
		       ret, led.port- >name);
		led.port = NULL;
	}
	if (led.port) {
		ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT);
		if (ret != 0) {
			printk("Error %d: failed to configure LED device %s pin %dn",
			       ret, led.port- >name, led.pin);
			led.port = NULL;
		} else {
			printk("Set up LED at %s pin %dn", led.port- >name, led.pin);
		}
	}

	printk("Press the buttonn");
	if (led.port) {
		while (1) {
			/* If we have an LED, match its state to the button's. */
			int val = gpio_pin_get_dt(&button);

			if (val >= 0) {
				gpio_pin_set_dt(&led, val);
			}
			k_msleep(SLEEP_TIME_MS);
		}
	}
	return 0;
}

3.2 核心流程

程序采用中断驱动的方式,实现了按键事件捕获与 LED 状态切换,同时通过 UART 输出日志。

  1. 初始化阶段
    • 配置 GPIO 引脚:P002 设置为输入模式,启用内部上拉电阻;P003 设置为输出模式。
    • 配置 UART:波特率 115200,8N1 格式。
    • 注册按键中断回调函数。
  2. 运行时逻辑
    • 按键按下时触发中断,切换 LED 状态(开/关)。
    • 在中断回调中,记录按键事件并通过 UART 输出日志。
    • 主循环保持空闲,等待中断触发。

3.1 关键 API 使用

以下是代码中使用的关键 API:

  • GPIO 初始化与控制
    gpio_pin_configure(gpio_dev, PIN_BTN, GPIO_INPUT | GPIO_PULL_UP);
    gpio_pin_configure(gpio_dev, PIN_LED, GPIO_OUTPUT);
    
  • UART 数据发送
    printk(str, args...);
    
  • 中断注册与处理
    gpio_pin_interrupt_configure(gpio_dev, PIN_BTN, GPIO_INT_EDGE_TO_ACTIVE);
    gpio_init_callback(&btn_cb, button_pressed, BIT(PIN_BTN));
    gpio_add_callback(gpio_dev, &btn_cb);
    

4. 实验现象与数据分析

4.1 串口日志 (UART Output)

终端应显示如下数据流:

Button pressed at 91714454
Button pressed at 228051750
Button pressed at 342154106
Button pressed at 431864898
Button pressed at 514931258
...

4.2 板载 LED 行为

  • 初始状态:LED 关闭。
  • 每次按键按下,LED 状态翻转(开/关)。
  • 视觉效果:LED 应与按键动作同步,无明显延迟。

5. 测评总结

本程序成功演示了 Renesas RA6E2 在 Zephyr RTOS 下的 GPIO 和 UART 外设控制。通过按键事件驱动 LED 状态切换,并实时记录日志到 UART,直观地展示了嵌入式系统中“输入-处理-输出”的基本工作流程。代码结构清晰,适配了最新的驱动 API,适用于初学者学习和开发者快速验证硬件功能。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分