前面分享了日志打印的文章:【nRF7002DK】日志打印-电子产品世界论坛
这篇将分享学习如何通过通用异步收发设备控制开发套件上的发光二极管。我们将利用默认连接到nRF7002DK开发套件接口MCU的通用异步收发设备控制器,通过USB提供通用异步收发设备。将在异步模式下设置通用异步收发设备,以便每次有新数据时调用回调函数。我们将接收缓冲区大小设置为10字节,接收超时设置为100微秒。这意味着当接收到一个字节并且在100微秒后没有活动(没有新数据),或者接收到10个字节时,会生成一个UART_RX_RDY事件。
此次分享是在前面日志打印的基础之上实现。
【实现步骤】
1、通过在prj.conf中添加以下两行来启用串行驱动程序(通用异步收发设备驱动程序)
CONFIG_SERIAL=y CONFIG_UART_ASYNC_API=y
2、在main.c中包含UART驱动的头文件。
3、获取通用异步收发设备硬件的设备指针,验证是否准备就绪。
static struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
4、验证通用异步收发设备就绪。
if (!device_is_ready(uart)) { return -1; }
5、定义通用异步收发设备的应用程序回调函数。对于我们的简单LED应用程序,我们只对与通过通用异步收发设备接收数据相关的UART_RX_RDY和UART_RX_DISABLED事件进行处理。
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { switch (evt->type) { case UART_RX_RDY: if ((evt->data.rx.len) == 1) { if (evt->data.rx.buf[evt->data.rx.offset] == '1') { gpio_pin_toggle_dt(&led); } else if (evt->data.rx.buf[evt->data.rx.offset] == '2') { gpio_pin_toggle_dt(&led1); } } break; case UART_RX_DISABLED: uart_rx_enable(dev, rx_buf, sizeof rx_buf, RECEIVE_TIMEOUT); break; default: break; } }
6、通过调用函数uart_callback_set()注册通用异步收发设备回调函数
ret = uart_callback_set(uart, uart_cb, NULL); if (ret) { return 1; }
【实现效果】
下载到开发板后提示发送1或者2来翻转LED1或者LED2。
开发板上可以成功的对LED进行控制了。
附源码:
#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/drivers/gpio.h> #include <zephyr/logging/log.h> #include <zephyr/drivers/uart.h> LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG); void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins); static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data); #define SLEEP_TIME_MS 10*60*1000 #define MAX_NUMBER_FACT 10 #define RECEIVE_BUFF_SIZE 10 #define RECEIVE_TIMEOUT 100 #define LED0_NODE DT_ALIAS(led0) static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); #define LED1_NODE DT_ALIAS(led1) static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(LED1_NODE, gpios); #define BUTTON0_NODE DT_ALIAS(sw0) static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(BUTTON0_NODE, gpios); static struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0)); static uint8_t tx_buf[] = { "nRF Connect SDK Fundamentals Course\r\n" "Press 1-2 on your keyboard to toggle LEDS 1-2 on your development kit\r\n"}; static uint8_t rx_buf[RECEIVE_BUFF_SIZE] = {0}; static struct gpio_callback button_cb_data; int main(void) { int ret; if (!device_is_ready(led.port)) { return -1; } if (!device_is_ready(led1.port)) { return -1; } if(!device_is_ready(button.port)){ return -1; } if (!device_is_ready(uart)) { return -1; } ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); if (ret < 0) { return -1; } ret = gpio_pin_configure_dt(&led1, GPIO_OUTPUT_ACTIVE); if (ret < 0) { return -1; } ret = gpio_pin_configure_dt(&button, GPIO_INPUT); if (ret < 0) { return -1; } ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE); if (ret < 0) { printf("Error %d: failed to configure interrupt on pin %s\n", ret, button.port->name); return -1; } int exercise_num = 2; uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 'H', 'e', 'l', 'l', 'o', '!'}; LOG_INF("nRF Connect SDK Fundamentals"); LOG_INF("Exercise %d\n", exercise_num); LOG_DBG("A Log message in debug level"); LOG_WRN("A Log message in warning level"); LOG_ERR("A Log message in error level"); LOG_HEXDUMP_DBG(data, sizeof(data), "Data"); gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin)); gpio_add_callback(button.port, &button_cb_data); ret = uart_callback_set(uart, uart_cb, NULL); if (ret) { return 1; } ret = uart_tx(uart, tx_buf, sizeof(tx_buf), SYS_FOREVER_MS); if (ret) { return 1; } ret = uart_rx_enable(uart, rx_buf, sizeof rx_buf, RECEIVE_TIMEOUT); if (ret) { return 1; } while (1) { k_msleep(SLEEP_TIME_MS); // Put the main thread to sleep for 100ms for power } } void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { // gpio_pin_toggle_dt(&led); int i; long int factorial = 1; LOG_INF("Calculating factorial of numbers from 1 to %d", MAX_NUMBER_FACT); for(i=1;i<=MAX_NUMBER_FACT;i++){ factorial = factorial * i; LOG_INF("%d! = %ld", i, factorial); } } static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data) { switch (evt->type) { case UART_RX_RDY: if ((evt->data.rx.len) == 1) { if (evt->data.rx.buf[evt->data.rx.offset] == '1') { gpio_pin_toggle_dt(&led); } else if (evt->data.rx.buf[evt->data.rx.offset] == '2') { gpio_pin_toggle_dt(&led1); } } break; case UART_RX_DISABLED: uart_rx_enable(dev, rx_buf, sizeof rx_buf, RECEIVE_TIMEOUT); break; default: break; } }