RT-Thread基于AT32单片机的485应用开发(二)

在上篇RT-Thread基于AT32单片机的485应用开发(一)中实现了RS485收发,但总觉得效率不高,函数封装也不完善。考虑到RS485总线应用都是主从式结构,比如工业领域常用的Modbus协议,都是以帧为单位进行收发,本次测试对收发函数进行了封装,并对RS485的收发控制引脚根据波特率进行了自动延时控制,降低了CPU负载。

本例中收发全部采用DMA的NON_BLOCKING方式,把接收一帧数据和发送一帧数据进行了函数封装。

测试代码如下:

#include <rtthread.h>
#include <rtdevice.h>/* 串口设备句柄 */
static rt_device_t serial;/* 485控制引脚 */
static rt_base_t rs485_ctrl_pin = -1;/* timeout receive */
static int serial_read_frame(rt_device_t dev, uint8_t *buf, int max_len, uint32_t idle_ms, int timeout_ms)
{int rx_len = 0, rc;uint32_t idle_time, timeout_time, cur_tick, last_tick;timeout_time = rt_tick_from_millisecond(timeout_ms);idle_time = rt_tick_from_millisecond(idle_ms);cur_tick = rt_tick_get();while((rt_tick_get()-last_tick<idle_time && rx_len<max_len) || rx_len<=0){rc = rt_device_read(dev, rx_len, buf, max_len-rx_len);if(rc>0){rx_len += rc;last_tick = rt_tick_get();}else{rt_thread_mdelay(1);}if(rt_tick_get()-cur_tick>timeout_time && rx_len<=0)break;}return rx_len;
}
/* transmit with auto 485 pin ctrl */
static void serial_write_frame_rs485(rt_device_t dev, uint8_t *buf, int len, int bitrate, int ctrl_pin)
{int ms = len * 10 *1000 / bitrate + 2;rt_pin_write(rs485_ctrl_pin,1);rt_hw_us_delay(10);rt_device_write(dev, 0, buf, len);rt_thread_mdelay(ms);rt_pin_write(rs485_ctrl_pin,0);
}
static void serial_thread_entry(void *parameter)
{rt_uint32_t rx_len;static unsigned char rx_buf[256];while(1){rx_len = serial_read_frame(serial, rx_buf, 255, 10, 1000);if(rx_len<=0)continue;serial_write_frame_rs485(serial, rx_buf, rx_len, 115200, rs485_ctrl_pin);/* 打印数据 */rx_buf[rx_len] = '\0';rt_kprintf("rx_len = %d\n",rx_len);}
}static int uart_485_sample(int argc, char *argv[])
{rt_err_t ret = RT_EOK;char uart_name[RT_NAME_MAX] = "uart4";if (argc == 2){rt_strncpy(uart_name, argv[1], RT_NAME_MAX);}rt_kprintf("uart_name = %s\n",uart_name);if(rt_strcmp(uart_name,"uart3")==0){rs485_ctrl_pin = rt_pin_get("PE.15");rt_pin_mode(rs485_ctrl_pin, PIN_MODE_OUTPUT);rt_pin_write(rs485_ctrl_pin,0 );}else if(rt_strcmp(uart_name,"uart4")==0){rs485_ctrl_pin = rt_pin_get("PA.15");rt_pin_mode(rs485_ctrl_pin, PIN_MODE_OUTPUT);rt_pin_write(rs485_ctrl_pin,0);}else{return RT_ERROR;}/* 查找串口设备 */serial = rt_device_find(uart_name);if (!serial){rt_kprintf("find %s failed!\n", uart_name);return RT_ERROR;}/* 以 DMA 接收及轮询发送方式打开串口设备 */rt_device_open(serial, RT_DEVICE_FLAG_RX_NON_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING);/* 创建 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);}else{ret = RT_ERROR;}return ret;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(uart_485_sample, uart device rs485 sample);

接收函数,返回收到的字节数:

int serial_read_frame(rt_device_t dev, uint8_t *buf, int max_len, uint32_t idle_ms, int timeout_ms)

idle_ms : 收到最后一个字节数据后空闲的毫秒数

timeout_ms : 如果在这个时间内没有收到数据,则返回0;-1代表一直等待直到收到数据。

发送函数

void serial_write_frame_rs485(rt_device_t dev, uint8_t *buf, int len, int bitrate, int ctrl_pin)

bitrate : 波特率,用于计算实际需要发送的时间

ctrl_pin :485收发控制引脚号

实际测试结果:

在编辑文字的约6分钟内,总共收发了31270个字节,没有发生错误。

在此基础上,后续又实现了一个极简ModbusRTU从机,核心代码不到300行,支持01、02、03、04、05、06、15、16功能码。

RT-Thread基于AT32单片机的485应用开发(三)Modbus从机

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

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

相关文章

【python】内存管理和数据类型问题

一、内存管理 Python有一个自动内存管理机制&#xff0c;但它并不总是按照期望的方式工作。例如&#xff0c;如果创建了一个大的列表或字典&#xff0c;并且没有删除它&#xff0c;那么这个对象就会一直占用内存&#xff0c;直到Python的垃圾回收器决定清理它。为了避免这种情…

【Verilog】运算符

系列文章 数值&#xff08;整数&#xff0c;实数&#xff0c;字符串&#xff09;与数据类型&#xff08;wire、reg、mem、parameter&#xff09; 系列文章算术运算符关系运算符相等关系运算符逻辑运算符按位运算符归约运算符移位运算符条件运算符连接和复制运算符 算术运算符 …

全志T113开发板Qt远程调试

1引言 通常情况下工程师在调试Qt程序时&#xff0c;需要频繁制作镜像烧录到核心板来测试Qt程序是否完善&#xff0c;这样的操作既费时又费力。这时我们可以通过QtCreator设备功能&#xff0c;定义设备后&#xff0c;在x86_64虚拟机上交叉编译qt程序&#xff0c;将程序远程部署到…

【机器学习前置知识】狄利克雷分布

在阅读本文前&#xff0c;建议先食用以下几篇文章以能更好地理解狄利克雷分布&#xff1a; 二项分布 Beta分布 多项分布 共轭分布 狄利克雷分布 狄利克雷分布(Dirichlet distribution)是Beta分布的扩展&#xff0c;把Beta分布从二元扩展到多元形式就是狄利克雷分布&#…

你Go代码写的像“鸭子”吗???

概 述 Go 语言也提供了接口类型&#xff0c;使得我们可以面向接口编程&#xff0c;将实现和接口分离。在我看来&#xff0c;软件的抽象之美也应该以此来表达&#xff0c;和 Java 语言不同的是 Go 并不是那么 “强制”&#xff0c;它使用了一种 鸭子类型 的方式让动态类型成为可…

three.js : tweenjs创建threejs动画

效果&#xff1a; 代码 <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div> <div class"box-right"><…

超凡脱俗的 sudo

文章目录 超凡脱俗的 sudo语法 没有sudo权限的用户指定用户执行命令列出目前sudo的权限使用sudo快速统计家目录的使用情况更多信息 超凡脱俗的 sudo Linux sudo命令以系统管理者的身份执行指令&#xff0c;也就是说&#xff0c;经由 sudo 所执行的指令就好像是 root 亲自执行。…

认识SpringBoot中的条件注解

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 循序渐进学SpringBoot ✨特色专栏&…

虚幻引擎:开创视觉与创意的新纪元

先看看据说虚幻5做出来的东西吧&#xff1a; 虚幻引擎5&#xff01;&#xff01;&#xff01;4K画质PS5实机演示&#xff01; 好了&#xff0c;用文字认识一下吧&#xff1a; 虚幻引擎5.3对UE5的核心工具集作了进一步优化&#xff0c;涉及渲染、世界构建、程序化内容生成&…

【解刊】Elsevier旗下,1区CCF-B,超快审稿:2个月22天录用!

计算机类 • 升区期刊 本次带来Elsevier旗下高分快刊&#xff0c;入选CCF-B类推荐&#xff0c;如有相关领域作者意向投稿&#xff0c;可重点关注&#xff01;更多领域期刊&#xff0c;可移步公众号【Unionpub学术】了解详情~ 01 期刊简介 Computer Networks ✅出版社&#x…

14:00面试,14:07就出来了,问的问题有点变态。。。

前言 刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资还…

回顾基础--HTML篇

HTML语法规范 <html></html> 开始标签与结束标签 <br /> 单标签 包含关系 <head><title></title> </head>并列关系 <head></head> <body></body> 1、 标题标签 标题标签 【双标签】【不同标题字体大小…

计算机网络-各层协议

大家在搞嵌入式开发的时候基本都了解过七层网络协议、五层网络协议、四层网络协议&#xff0c;那么今天让我们更加的深入了解一下&#xff1a; 历史发展介绍 OSI七层模型由ISO国际标准化组织提出的通信标准。TCP/IP四层模型是OSI七层模型的简化版&#xff0c;OSI在它被官方完…

论文阅读1---OpenCalib论文阅读之factory calibration模块

前言 该论文的标定间比较高端&#xff0c;一旦四轮定位后&#xff0c;可确定标定板与车辆姿态。以下为本人理解&#xff0c;仅供参考。 工厂标定&#xff0c;可理解为车辆相关的标定&#xff0c;不涉及传感器间标定 该标定工具不依赖opencv&#xff1b;产线长度一般2.5米 Fa…

浅谈WAF——守护网络安全的无形之盾

随着信息化时代的到来&#xff0c;网络已逐渐融入我们日常生活的方方面面。然而&#xff0c;与此同时&#xff0c;网络安全问题却也如影随形。为此&#xff0c;一种名为“Web应用防火墙”的工具应运而生&#xff0c;简称”WAF”。 WAF是什么&#xff1f; WAF&#xff08;Web …

实现LCM在docker之间的通信

目录 1.docker容器互联 新建网络 连接容器 2.设置环境变量 3.在两个docker之间实现通信 1.docker容器互联 新建网络 $ docker network create -d bridge test-net 连接容器 运行一个容器并连接到新建的 test-net 网络: $ docker run -itd --name lcm_1 --network tes…

通过iFrame嵌入Grafana页面或pannel

前言 在当前数据驱动的时代&#xff0c;有效地可视化和监控关键性能指标变得至关重要。Grafana&#xff0c;作为一个开源的监控解决方案&#xff0c;提供了强大的功能来呈现和分析数据&#xff0c;从而帮助用户及时洞察和响应各种情况。随着技术的不断发展&#xff0c;将这些信…

docker 容器添加指定网络地址

docker 容器添加指定网络地址 在搭建halo博客时&#xff0c;准备让 halo、mysql8.1、nginx 三个容器在同一个网段中&#xff0c;并指定IP。 实现docker内部容器之间网络互通。 查看容器网络信息命令 docker inspect 容器名各容器部署成功后网络效果如下&#xff1a; nginx …

直播美颜SDK开发指南:从零开始搭建主播美颜工具

本篇文章&#xff0c;笔者将带你从零开始&#xff0c;一步步搭建主播美颜工具的开发环境&#xff0c;介绍关键技术和步骤&#xff0c;助你打造出令人惊艳的直播美颜SDK。 第一步&#xff1a;环境搭建 在开始SDK的开发之前&#xff0c;确保你的开发环境准备就绪。选择一个适合的…

挑战Transformer的新架构Mamba解析以及Pytorch复现

今天我们来详细研究这篇论文“Mamba:具有选择性状态空间的线性时间序列建模” Mamba一直在人工智能界掀起波澜&#xff0c;被吹捧为Transformer的潜在竞争对手。到底是什么让Mamba在拥挤的序列建中脱颖而出? 在介绍之前先简要回顾一下现有的模型 Transformer:以其注意力机制而…