Zephyr下ESP32S3的串口通信功能

SDK下载参考前面的“Zephyr下ESP32S3开发环境搭建(Linux篇)”

1.关于UART0

在下面路径下对应UART0的配置

./drivers/serial/CMakeLists.txt:34:zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c)

./drivers/serial/uart_efinix_sapphire.c

调出配置界面命令

west build -b esp32s3_devkitm/esp32s3/procpu samples/subsys/shell/shell_module -d build_111 -t menuconfig

UART0功能可以参见samples/subsys/shell/shell_module里面可以进行部分命令交互

2.关于UART1

对应PIN脚定义如下:

下面介绍Zephyr下ESP32S3的UART1功能对应源码实现:

工程结构

文件CMakeLists.txt内容如下

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(uart1)

target_sources(app PRIVATE src/main.c)

文件prj.conf文件内容如下

CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_USE_RUNTIME_CONFIGURE=y
CONFIG_TEST_USERSPACE=y

文件boards/esp32s3_devkitm_procpu.overlay内容如下

&uart1 {
	status = "okay";
	current-speed = <115200>;
	pinctrl-0 = <&uart1_default>;
	pinctrl-names = "default";
};

文件src/main.c内容如下

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>

#include <string.h>

/* change this to any other UART peripheral if desired */
#define UART_DEVICE_NODE DT_NODELABEL(uart1)

#define MSG_SIZE 32

/* queue to store up to 10 messages (aligned to 4-byte boundary) */
K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 10, 4);

static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);

/* receive buffer used in UART ISR callback */
static char rx_buf[MSG_SIZE];
static int rx_buf_pos;

/*
 * Read characters from UART until line end is detected. Afterwards push the
 * data to the message queue.
 */
void serial_cb(const struct device *dev, void *user_data)
{
	uint8_t c;

	if (!uart_irq_update(uart_dev)) {
		return;
	}

	if (!uart_irq_rx_ready(uart_dev)) {
		return;
	}

	/* read until FIFO empty */
	while (uart_fifo_read(uart_dev, &c, 1) == 1) {
		if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
			/* terminate string */
			rx_buf[rx_buf_pos] = '\0';

			/* if queue is full, message is silently dropped */
			k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);

			/* reset the buffer (it was copied to the msgq) */
			rx_buf_pos = 0;
		} else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
			rx_buf[rx_buf_pos++] = c;
		}
		/* else: characters beyond buffer size are dropped */
	}
}

/*
 * Print a null-terminated string character by character to the UART interface
 */
void print_uart(char *buf)
{
	int msg_len = strlen(buf);

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(uart_dev, buf[i]);
	}
}

int main(void)
{
	char tx_buf[MSG_SIZE];

	if (!device_is_ready(uart_dev)) {
		printk("UART device not found!");
		return 0;
	}

	/* configure interrupt and callback to receive data */
	int ret = uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);
	if (ret < 0) {
		if (ret == -ENOTSUP) {
			printk("Interrupt-driven UART API support not enabled\n");
		} else if (ret == -ENOSYS) {
			printk("UART device does not support interrupt-driven API\n");
		} else {
			printk("Error setting UART callback: %d\n", ret);
		}
		return 0;
	}
	uart_irq_rx_enable(uart_dev);

	print_uart("Hello! I'm your echo bot.\r\n");
	print_uart("Tell me something and press enter:\r\n");

	/* indefinitely wait for input from the user */
	while (k_msgq_get(&uart_msgq, &tx_buf, K_FOREVER) == 0) {
		print_uart("Echo: ");
		print_uart(tx_buf);
		print_uart("\r\n");
	}
	return 0;
}

运行结果如下

Zephyr环境下,ESP32S3的定时器功能是其重要组成部分。Zephyr作为一个可扩展的实时操作系统,为ESP32S3的定时器提供了良好的开发支持。 ESP32S3本身具备多个硬件定时器,这些定时器在Zephyr环境中可以被灵活配置和使用。在Zephyr里,定时器可以用于多种场景,例如周期性任务调度、延时操作等。 从硬件层面来看,ESP32S3的定时器具有不同的工作模式,如单次触发模式和周期触发模式。在单次触发模式下,定时器启动后,在设定的时间到达时触发一次事件;而周期触发模式则会按照设定的时间间隔周期性地触发事件。 在Zephyr代码中,开发者可以通过一系列的API来控制ESP32S3的定时器。例如,使用`k_timer_init`函数来初始化一个定时器,该函数需要传入定时器对象、超时回调函数、以及可选的周期回调函数。以下是一个简单的示例代码: ```c #include <zephyr.h> #include <device.h> #include <devicetree.h> #include <drivers/timer.h> // 定时器超时回调函数 void timer_timeout(struct k_timer *timer_id) { // 在这里处理定时器超时事件 } // 定时器周期回调函数 void timer_periodic(struct k_timer *timer_id) { // 在这里处理定时器周期事件 } // 定义一个定时器对象 K_TIMER_DEFINE(my_timer, timer_timeout, timer_periodic); void main(void) { // 初始化定时器 k_timer_init(&my_timer, timer_timeout, timer_periodic); // 启动定时器,设置为周期触发模式,周期为1000ms k_timer_start(&my_timer, K_MSEC(1000), K_MSEC(1000)); while (1) { // 主循环可以处理其他任务 k_sleep(K_MSEC(100)); } } ``` 通过这些API,开发者可以方便地对定时器进行初始化、启动、停止等操作。同时,Zephyr还提供了对定时器时间精度的控制,开发者可以根据具体需求设置定时器的时间间隔,以满足不同的应用场景。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值