【RTT-Studio】详细使用教程十三:UART的DMA 接收及轮询发送

文章目录

    • 一、简介
    • 二、RTT配置
    • 三、使用信号量接收
    • 四、使用消息队列接收
    • 五、测试验证

一、简介

  串口是指数据一位一位地顺序传送,其特点是通讯线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。一条信息的各位数据被逐位按顺序传送的通讯方式称为串行通讯。串行通讯的特点是:数据位的传送,按位顺序进行,最少只需一根传输线即可完成;成本低但传送速度慢。串行通讯的距离可以从几米到几千米;根据信息的传送方向,串行通讯可以进一步分为单工、半双工和全双工三种。

  运行序列图如下图所示:
在这里插入图片描述
  当串口接收到一批数据后会调用接收回调函数,接收回调函数会把此时缓冲区的数据大小通过消息队列发送给等待的数据处理线程。线程获取到消息后被激活,并读取数据。一般情况下 DMA 接收模式会结合 DMA 接收完成中断和串口空闲中断完成数据接收。


二、RTT配置

(1)在board.h文件中进行配置,具体操作在board.h文件中有介绍:

/** After configuring corresponding UART or UART DMA, you can use it.** STEP 1, define macro define related to the serial port opening based on the serial port number*                 such as     #define BSP_USING_UART1** STEP 2, according to the corresponding pin of serial port, define the related serial port information macro*                 such as     #define BSP_UART1_TX_PIN       "PA9"*                             #define BSP_UART1_RX_PIN       "PA10"** STEP 3, if you want using SERIAL DMA, you must open it in the RT-Thread Settings.*                 RT-Thread Setting -> Components -> Device Drivers -> Serial Device Drivers -> Enable Serial DMA Mode** STEP 4, according to serial port number to define serial port tx/rx DMA function in the board.h file*                 such as     #define BSP_UART1_RX_USING_DMA**/#define BSP_USING_UART1
#define BSP_UART1_TX_PIN       "PA9"
#define BSP_UART1_RX_PIN       "PA10"#define BSP_USING_UART3
#define BSP_UART3_TX_PIN       "PD8"
#define BSP_UART3_RX_PIN       "PD9"
#define BSP_UART3_RX_USING_DMA

(2)打开可视化界面上驱动使能,使能串口DMA模式,并且可以根据自己需要设置缓冲区的大小:
在这里插入图片描述

(3)打开DMA所需要的HAL库文件,只需要将相应的宏定义打开即可。
在这里插入图片描述


三、使用信号量接收

1.uart3.h文件

#ifndef APPLICATIONS_UART3_H_
#define APPLICATIONS_UART3_H_#include <rtthread.h>
#include <drv_common.h>#define SAMPLE_UART_NAME        "uart3"rt_size_t rx_len;/* 串口设备句柄 */
static rt_device_t serial;/* 信号量控制变量 */
rt_sem_t  rx_sem;#endif /* APPLICATIONS_UART3_H_ */

2.uart3.c文件

#include "uart3.h"/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{rx_len = size;rt_sem_release(rx_sem);return RT_EOK;
}static void serial_thread_entry(void *parameter)
{rt_size_t len = 0;char buffer[256] = {0};while (1){rt_memset(&buffer, 0, sizeof(buffer));/* 从信号量中读取消息 */rt_sem_take(rx_sem, RT_WAITING_FOREVER);len = rt_device_read(serial, 0, buffer, 256);buffer[len] = '\0';rt_device_write(serial, 0, buffer, len);rt_kprintf("%s\n", buffer);}
}void Create_Uart3_Test_Entry(void)
{char str[] = "hello, rt-thread!";/* 查找串口设备 */serial = rt_device_find(SAMPLE_UART_NAME);if (!serial){rt_kprintf("find %s failed!\n", SAMPLE_UART_NAME);}/* 以 DMA 接收及轮询发送方式打开串口设备 */rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);/* 初始化配置参数 */struct serial_configure uart3_config = RT_SERIAL_CONFIG_DEFAULT;uart3_config.baud_rate = BAUD_RATE_19200;rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, (void *) &uart3_config);/* 创建信号量 */rx_sem = rt_sem_create("rx_sem", 0, RT_IPC_FLAG_PRIO);/* 设置接收回调函数 */rt_device_set_rx_indicate(serial, uart_input);/* 发送字符串 */rt_device_write(serial, 0, str, (sizeof(str) - 1));/* 创建 serial 线程 */rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);/* 创建成功则启动线程 */if (thread != RT_NULL){rt_thread_startup(thread);}
}
MSH_CMD_EXPORT_ALIAS(Create_Uart3_Test_Entry, test, Create Uart3 Test Entry);

四、使用消息队列接收

1.uart3.h文件

#ifndef APPLICATIONS_UART3_H_
#define APPLICATIONS_UART3_H_#include <rtthread.h>
#include <drv_common.h>#define SAMPLE_UART_NAME        "uart3"/* 串口接收消息结构 */
struct rx_msg
{rt_device_t dev;rt_size_t   size;
};/* 串口设备句柄 */
static rt_device_t serial;/* 消息队列控制块 */
static struct rt_messagequeue rx_mq;#endif /* APPLICATIONS_UART3_H_ */

2.uart3.c文件

#include "uart3.h"/* 接收数据回调函数 */
static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
{struct rx_msg msg;rt_err_t result;msg.dev = dev;msg.size = size;result = rt_mq_send(&rx_mq, &msg, sizeof(msg));if ( result == -RT_EFULL){/* 消息队列满 */rt_kprintf("message queue full!\n");}return result;
}static void serial_thread_entry(void *parameter)
{struct rx_msg msg;rt_err_t result;rt_uint32_t rx_length;static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];while (1){rt_memset(&msg, 0, sizeof(msg));/* 从消息队列中读取消息 */result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);if (result == RT_EOK){/* 从串口读取数据 */rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);rx_buffer[rx_length] = '\0';/* 通过串口设备 serial 输出读取到的消息  */rt_device_write(serial, 0, rx_buffer, rx_length);/* 打印数据 */rt_kprintf("%s\n", rx_buffer);}}
}void Create_Uart3_Test_Entry(void)
{static char msg_pool[256];char str[] = "hello RT-Thread!\r\n";/* 查找串口设备 */serial = rt_device_find(SAMPLE_UART_NAME);if (!serial){rt_kprintf("find %s failed!\n", SAMPLE_UART_NAME);}/* 初始化消息队列 */rt_mq_init(&rx_mq, "rx_mq",msg_pool,                /* 存放消息的缓冲区  */sizeof(struct rx_msg),   /* 一条消息的最大长度  */sizeof(msg_pool),        /* 存放消息的缓冲区大小  */RT_IPC_FLAG_FIFO);       /* 如果有多个线程等待,按照先来先得到的方法分配消息  *//* 以 DMA 接收及轮询发送方式打开串口设备 */rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);/* 初始化配置参数 */struct serial_configure uart3_config = RT_SERIAL_CONFIG_DEFAULT;uart3_config.baud_rate = BAUD_RATE_19200;rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, (void *) &uart3_config);/* 设置接收回调函数 */rt_device_set_rx_indicate(serial, uart_input);/* 发送字符串 */rt_device_write(serial, 0, str, (sizeof(str) - 1));/* 创建 serial 线程 */rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);/* 创建成功则启动线程 */if (thread != RT_NULL){rt_thread_startup(thread);}
}
MSH_CMD_EXPORT_ALIAS(Create_Uart3_Test_Entry, test, Create Uart3 Test Entry);

五、测试验证

  通过将上面的两个程序烧录到控制板中,通过RTT特有的控制台进行指令操作,通过大宋质量test来执行串口函数,从而实现对串口3的参数配置以及DMA配置,通过信号量或者消息队列的方式来接收数据,从而将接收到的数据重新发送到串口3,实际的实验效果如下所示:
在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/405693.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我的创作纪念日【2048】

机缘 2048&#xff0c;是计算机二进制世界里很奇妙的数字&#xff0c;在CSDN上创作的第六年&#xff0c;记录从事本行业的知识学习与总结&#xff0c;好记性不如烂笔头&#xff0c;或许写的东西不如大佬的文章&#xff0c;那么有深度&#xff0c;但自己也是在坚持&#xff0c;…

自动微分autograd实践要点

目录 定义Value手动定义每个 operator 的 _backward() 函数构建反向传播计算链 本文主要参考 反向传播和神经网络训练 大神Andrej Karpathy 的“神经网络从Zero到Hero 系列”之一&#xff0c;提炼一些精要&#xff0c;将反向传播的细节和要点展现出来 定义Value 第一步首先要…

传知代码-自动化细胞核分割与特征分析(论文复现)

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 引言 细胞核分割和分类在医学研究和临床诊断中具有重要意义。精准的细胞核分割能够帮助医生更好地识别和分析细胞核的形态学特征&#xff0c;从而辅助疾病诊断、癌症检测以及药物研发。HoverNet是一种基于深度学…

【GitLab】使用 Docker engine安装 GitLab 2: gitlab-ce:17.3.0-ce.0 拉取

ce版本必须配置代理。 极狐版本可以直接pull 社区版GitLab不支持Alibaba Cloud Linux 3,本操作以Ubuntu/Debian系统为例进行说明,其他操作系统安装说明,请参见安装社区版GitLab。 docker 环境重启 sudo systemctl daemon-reload sudo systemctl restart docker脚本安装 安裝…

苹果手机微信聊天记录删除了怎么恢复?

在日常使用手机的过程中&#xff0c;我们经常会遇到误删微信聊天记录的情况&#xff0c;尤其是对于那些重要的对话记录&#xff0c;一旦丢失可能会带来不小的困扰。今天&#xff0c;我们就来探讨一下如何在苹果手机上恢复被删除的微信聊天记录。 一、利用第三方数据恢复工具 对…

拓客工具,助你多维度筛选客源!

随着大数据与人工智能技术的飞速发展&#xff0c;企业拓客的方式也迎来了前所未有的变革。在这里将分享如何利用拓客工具&#xff0c;在任意行业中精实现高效拓客。 一、高级搜索&#xff1a;最新企业&#xff01; 传统的客户开发方式往往依赖于广撒网式的营销手段&#xff0c;…

Qt实现tcp协议

void Widget::readyRead_slot() {//读取服务器发来的数据QByteArray msg socket->readAll();QString str QString::fromLocal8Bit(msg);QStringList list str.split(:);if(list.at(0) userName){QString str2;for (int i 1; i < list.count(); i) {str2 list.at(i);…

作业8/21

client cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), socket(new QTcpSocket(this)) {ui->setupUi(this); // 设置 UI 界面// 控件初始状态设置为禁用&#xff0c;防止未连接…

Linux timedatectl 命令

timedatectl 是 Linux 系统中用于查询和更改系统日期、时间和时区的工具&#xff0c;它特别适用于那些使用 systemd 作为系统和服务管理器的系统。语法格式为“timedatectl [参数]”。 发现电脑时间跟实际时间不符&#xff1f;如果只差几分钟的话&#xff0c;我们可以直接调整。…

tekton通过ceph挂载node_modules的时候报错failed to execute command: copying dir: symlink

分析&#xff1a; 如果ceph的mountPath和workingDir路径一致的话&#xff0c;就会报错。 解决&#xff1a;node_modules挂载到/workspace下&#xff0c;workingDir的代码mv到/workspace下进行构建。

MyBatis-Plus与PageHelper依赖的jsqlparser库冲突

问题 最近遇到的一个项目升级了SpringBoot到3.x版本了&#xff0c;同时也准备升级MyBatis-Plus&#xff0c;即使用如下依赖&#xff1a; <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><…

初级python代码编程学习----简单的图形化闹钟小程序

我们来创建一个简单的图形化闹钟程序通常需要使用图形用户界面&#xff08;GUI&#xff09;库。以下是使用Python的Tkinter库创建一个基本闹钟程序的步骤&#xff1a; 环境准备 确保已安装Python。安装Tkinter库&#xff08;Python 3.8及以上版本自带Tkinter&#xff0c;无需…

【代码】Swan-Transformer 代码详解(待完成)

1. 局部注意力 Window Attention (W-MSA Module) class WindowAttention(nn.Module):r""" Window based multi-head self attention (W-MSA) module with relative position bias.It supports both of shifted and non-shifted window.Args:dim (int): Number…

用户画像实时标签数据处理流程图

背景 在用户画像中&#xff0c;有一类实时标签&#xff0c;我们既要它能够实时的对外提供数据统计&#xff0c;也要保存到大数据组件中用于后续的对数&#xff0c;圈选的逻辑&#xff0c;本文就看一下用户画像的实时标签的数据流转图 实时标签数据流转图 首先我们肯定是要使…

独立站PrestaShop安装

独立站PrestaShop安装 独立站PrestaShop安装系统需求下载PrestaShop浏览器下载命令行下载 解压PrestaShop创建数据库移动PrestaShop源码到web目录composer安装依赖包nginx配置访问域名进入安装页面选择语言许可协议系统兼容性店铺信息Content of your store系统配置数据库店铺安…

书生大模型学习笔记9 - LMDeploy 量化部署

LMDeploy 量化部署 InternLM 2.5 20b量化前部署W4A16 模型量化量化模型部署streamlit web InternLM 2.5 20b量化前部署 lmdeploy serve api_server \/root/learning/InternLM/XTuner/merged_20b \--model-format hf \--quant-policy 0 \--cache-max-entry-count 0.01\--server…

数据结构与算法——图

1、为什么要有图 1&#xff09;前面我们学习了线性表和树 2&#xff09;线性表局限于一个直接前驱和一个直接后继的关系 3&#xff09;树也只能有一个直接前驱就是父节点 4&#xff09;当我们需要表示多对多的关系时&#xff0c;这里我们就用到了图 图是一种数据结构&#xf…

支持2.4G频秒变符合GB42590的标准的飞行器【无人机GB42590发射端】

使用方法: 放在飞机 上&#xff0c;按键那一面需要朝上对着天空(因为GPS陶瓷天线在按键面)&#xff0c;支持基本ID&#xff0c;向量和系统包&#xff0c;电池容量240mAH充电1小时&#xff0c;使用时间大概2小时。 1.长按3秒开关机 2.开机红灯慢闪&#xff0c;只发射基本ID数据…

JavaScript_7_练习:随机抽奖案例

效果图 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>练习&#xff1a;随机抽奖案例</tit…

【后续更新】python搜集上海二手房数据

源码如下: import asyncio import aiohttp from lxml import etree import logging import datetime import openpyxlwb = openpyxl.Workbook() sheet = wb.active sheet.append([房源, 房子信息, 所在区域, 单价, 关注人数和发布时间, 标签]) logging.basicConfig(level=log…