物联网实战--驱动篇之(四)LoRa应用(modbus)

目录

一、前言

二、板级收发

三、主机请求

四、从机接收及回复

五、主机接收


一、前言

        之前两篇分别介绍了modbus和sx1278的驱动,但是都并未具体讲解如何应用,那么这一篇就把两者结合起来,做个小demo,便于理解这两个驱动的使用方法。

        简单讲就是物理层的通讯链路用LoRa,协议层用modbus,由于有主机、从机,所以需要两套硬件设备,STM32F103C8T6系统板+SX1278模块,两套硬件是一样的,代码有差异,就是在软件层面定义身份是主机还是从机,分别对应下载进去就能实现主机请求从机数据的功能了。

        STM32F103C8T6就跟净化器项目那个一样就行了,SX1278模块需要有插针,这样才能用杜邦线链接,有能力的自己画PCB板也是可以的,可以参考这个链接的https://item.taobao.com/item.htm?abbucket=8&id=621186198228&ns=1&skuId=4892611431467&spm=a21n57.1.item.5.42d6523catPFYv

具体的接线如下:

二、板级收发

        为了方便应用层调用,我们再把收发函数封装一层,具体如下:


/*		
================================================================================
描述 : 设置无线参数
输入 : 
输出 : 
================================================================================
*/
void bsp_sx1278_set_param(u32 freq, u8 sf, u8 bw)
{drv_sx1278_set_rf_freq(&g_sDrvSx1278, freq);drv_sx1278_set_sf(&g_sDrvSx1278, sf);drv_sx1278_set_bw(&g_sDrvSx1278, bw);  
}/*		
================================================================================
描述 : LORA底层发送函数
输入 : 
输出 : 
================================================================================
*/
u8 bsp_sx1278_send_level(u32 freq, u8 sf, u8 bw, u8 *buff, u16 len)
{static const u16 dly_time=15;u16 tx_timeout=drv_sx1278_calcu_air_time(sf, bw, len)*1.2+500;//计算发送时长u32 dly_cnts=tx_timeout/dly_time;u8 tx_len=0;bsp_sx1278_set_param(freq, sf, bw);drv_sx1278_send(&g_sDrvSx1278, buff, len);printf("drv_port_sx1278_send_level: time_out=%dms, P(%u, %u, %u)\n", tx_timeout,  freq, sf, bw);
//	printf_hex("send buff= ", buff, len);while(dly_cnts--){delay_os(dly_time);if(drv_sx1278_send_check(&g_sDrvSx1278)==true){drv_sx1278_recv_init(&g_sDrvSx1278);	//设置成接收模式tx_len=len;printf("app_sx1278_send: send ok, tx_len=%d\n", tx_len);break;}		}if(tx_len==0){printf("app_sx1278_send: send failed!\n");drv_sx1278_recv_init(&g_sDrvSx1278);	//设置成接收模式}return tx_len;		
}/*		
================================================================================
描述 : LORA接收检测
输入 : 
输出 : 
================================================================================
*/
void bsp_sx1278_recv_check(void)
{static u8 recv_buff[256]={0};u8 recv_len=0;	recv_len=drv_sx1278_recv_check(&g_sDrvSx1278, recv_buff);//LORA接收if(recv_len>0){
//		printf_hex("recv_buff= ", recv_buff, recv_len); if(SX1278_ROLE==SX1278_MASTER) //主机模式{app_sx1278_master_recv_parse(recv_buff, recv_len);//主机数据解析}else{app_sx1278_slaver_recv_parse(recv_buff, recv_len);//从机数据解析}}	}

        这样,发送的时候就可以根据自己需要的无线参数灵活配置,发送函数内部自动完成了发送时间计算、无线参数配置、数据写入和延时等待等任务;对于接收,这里写得比较不严谨,收到数据后的解析处理正常要用回调函数的,但是为了方便测试也就没搞得那么麻烦了,不管主机还是从机,收到数据后会进入各自的解析函数。

        主机和从机的角色要在这里自己定义,更改后重新编译下载。

三、主机请求

        这种主从结构的网络,都是主机主动请求,从机被动回复的,理论上从机不能随意发送数据的,不然会让整个网络乱套的。下面是主机请求的代码:


/*		
================================================================================
描述 : 主机请求数据
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_master_req_data(void)
{static u32 last_sec_time=0;u32 now_sec_time=drv_get_sec_counter();if(now_sec_time-last_sec_time>=5)//5秒请求一次{u8 make_buff[50]={0};u16 make_len=0;make_len=drv_modbus_send_fun03(1, 0x0000, 2, make_buff, sizeof(make_buff));//组合请求数据bsp_sx1278_send_level(434000000, 12, 9, make_buff, make_len);//根据无线参数发送modbus数据  last_sec_time=now_sec_time;}}

        也是比较简单的,间隔5秒请求一次,请求的数据通过之前的modbus驱动函数来组合的,参数是从机地址1,起始寄存器0x0000,寄存器数量2个;无线参数是频率434MHz,SF=12,BW=9;最后就是等它发送完成了。

四、从机接收及回复

        从机的LoRa平时都是处于接收模式的,所以当主机发送数据后,只要信号没什么问题,正常都能接收到一个数据包的,记得两个模块不要放太近,天线要插上。接收解析和回复代码如下:

/*		
================================================================================
描述 : 从机回复数据
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_slaver_ack_data(void)
{u8 make_buff[50]={0};u16 make_len=0;//在这里只是模拟测试,我们发送一个固定数据包就行了make_buff[make_len++]=0x01; //地址码make_buff[make_len++]=0x03; //功能码make_buff[make_len++]=0x04; //数据长度make_buff[make_len++]=0x02; make_buff[make_len++]=0x92; make_buff[make_len++]=0xFF;make_buff[make_len++]=0x9B; //4字节数据make_buff[make_len++]=0x5A;make_buff[make_len++]=0x3D; //CRC校验bsp_sx1278_send_level(434000000, 12, 9, make_buff, make_len);//根据无线参数发送回复数据    
}/*		
================================================================================
描述 : 从机接收解析
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_slaver_recv_parse(u8 *recv_buff, u16 recv_len)
{printf_hex("slaver recv= ", recv_buff, recv_len);//打印应用层数据app_sx1278_slaver_ack_data();//回复到主机
}

        从机这里没做过多的解析,直接就是回复一个固定的数据包就是了,自己可以添加一些地址码和校验码检测的内容,数据也可以添加一些随机数。从机回复的发送过程跟主机是一样的,无线参数是要一致的。

五、主机接收

        主机发送完成后会马上进入接收模式,等待从机的回复,收到回复后会进行modbus的解析,代码如下:

/*		
================================================================================
描述 : 主机接收解析
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_master_recv_parse(u8 *recv_buff, u16 recv_len)
{u8 data_buff[20]={0};u16 data_len=drv_modbus_parse_fun03(1, recv_buff, recv_len, data_buff, sizeof(data_buff));//modbus解析if(data_len>0){printf_hex("master recv= ", data_buff, data_len);//打印应用层数据}
}

        最后把数据区打印出来,这样一个完整的请求回复流程就完成了,剩下的就是不断重复这个过程。这里,我们单独开了一个线程用户LoRa的数据请求,代码如下:

/*		
================================================================================
描述 : 
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_init(void)
{app_sx1278_hal_init();bsp_sx1278_set_param(434000000, 12, 9);//无线参数初始化
}/*		
================================================================================
描述 : sx1278线程
输入 : 
输出 : 
================================================================================
*/
void app_sx1278_thread_entry(void *parameter) 
{app_sx1278_init();while(1){if(SX1278_ROLE==SX1278_MASTER) //主机模式{app_sx1278_master_req_data(); //轮询从机数据}bsp_sx1278_recv_check();//数据接收delay_os(20);}
}

        在初始化的时候开启这个线程就能运行了。

下图是结构目录:

代码链接:https://download.csdn.net/download/ypp240124016/89101284

本项目的交流QQ群:701889554

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

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

相关文章

测试开发面经(Flask,轻量级Web框架)

1. Flask的核心特点 a. 轻量级:核心简洁,只提供了基本的功能,其他高级功能可以通过插件或扩展来添加。 b. 灵活性:允许开发者选择适合自己项目的组件和工具,没有强制的项目结构和设计模式。 c. 易于扩展:提…

蓝桥杯刷题-09-三国游戏-贪心⭐⭐⭐

蓝桥杯2023年第十四届省赛真题-三国游戏 小蓝正在玩一款游戏。游戏中魏蜀吴三个国家各自拥有一定数量的士兵X, Y, Z (一开始可以认为都为 0 )。游戏有 n 个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第 i 个事件发生时会分别让 X, Y,…

并发 ---- 多线程原理及底层实现

并发现象遍布日常生活,我们时常接触:我们可以边走路边说话;或者,左右手同时做出不一样的动作。在计算机应用程序中也有很好的例子: 浏览器 - 浏览器可以同时下载任意数量的文件和打开多个网页,下载时仍允许…

【Linux】进程控制之进程程序替换

目录 前言 替换的原理 替换函数 记忆技巧 函数使用 execl execlp execv execvp execle execvpe 调用其它语言的程序 模拟实现一个shell 前言 关于本文可以先去看看上一篇【Linux】进程控制详解-CSDN博客可以更好的理解这里的内容 学完本篇文章,你就…

AI智能分析盒子在工地的应用,提高工地管理效率和安全性

工地ai智能分析盒子是一种基于人工智能视觉分析技术的人工智能盒子,旨在提升工地作业区域的管理效率和保障作业人员的安全。通过最前沿的AI视觉算法、大数据,能够实时监控工地现场视频流画面,对施工工地人员的工作着装及日常作业行为进行规范…

OpenCV 4.9基本绘图

返回:OpenCV系列文章目录(持续更新中......) 上一篇:OpenCV使用通用内部函数对代码进行矢量化 下一篇:使用OpenCV4.9的随机生成器和文本 ​目标 在本教程中,您将学习如何: 使用 OpenCV 函数 line() 画一…

产品经理和项目经理的区别

1. 前言 本文深入探讨了产品经理与项目经理在职责、关注点以及所需技能方面的显著区别。产品经理主要负责产品的规划、设计和市场定位,强调对用户需求的深刻理解和产品创新的推动;而项目经理则侧重于项目的执行、进度控制和资源管理,确保项目按时、按质、按预算完成。两者在…

一文搞懂从爬楼梯到最小花费(力扣70,746)

文章目录 题目前知动态规划简介动态规划模版 爬楼梯一、思路二、解题方法三、Code 使用最小花费爬楼梯一、思路二、解题方法三、Code 总结 在计算机科学中,动态规划是一种强大的算法范例,用于解决多种优化问题。本文将介绍动态规划的核心思想&#xff0c…

CTK插件框架学习-服务工厂(06)

CTK插件框架学习-信号槽(05)https://mp.csdn.net/mp_blog/creation/editor/137240105 一、服务工厂定义 注册插件时使用服务工厂注册,使用getService根据调用者插件资源文件内容获取在服务工厂内的对应实现在服务工厂中可以知道是哪个插件正在调用服务工厂懒汉模式…

rabbitmq死信交换机,死信队列使用

背景 对于核心业务需要保证消息必须正常消费,就必须考虑消费失败的场景,rabbitmq提供了以下三种消费失败处理机制 直接reject,丢弃消息(默认)返回nack,消息重新入队列将失败消息投递到指定的交换机 对于核…

代码随想录第34天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分发糖果

1005.K次取反后最大化的数组和 1005. K 次取反后最大化的数组和 - 力扣(LeetCode) 代码随想录 (programmercarl.com) 贪心算法,这不就是常识?还能叫贪心?LeetCode:1005.K次取反后最大化的数组和_哔哩哔…

10.枚举

1.背景及定义 枚举是在JDK1.5以后引入的。 主要用途是: 将一组常量组织起来, 在这之前表示一组常量通常使用定义常量的方式: public static final int RED 1; public static final int GREEN 2; public static final int BLACK 3; 但是…

Web Component 组件库有什么优势

前言 前端目前比较主流的框架有 react,vuejs,angular 等。 我们通常去搭建组件库的时候都是基于某一种框架去搭建,比如 ant-design 是基于 react 搭建的UI组件库,而 element-plus 则是基于 vuejs 搭建的组件库。 可能你有这种体…

C语言进阶课程学习记录-第22课 - 条件编译使用分析

C语言进阶课程学习记录-第22课 - 条件编译使用分析 条件编译基本概念条件编译实验cmd命令窗口输入演示条件编译本质实验-ifdefcmd定义宏结果比较 include本质实验-间接包含同一个头文件解决重复包含的方法-ifndef实验-条件编译的应用小结 本文学习自狄泰软件学院 唐佐林老师的 …

线上研讨会 | 新一代数字化技术赋能机器人及智能产线行业高质量发展

随着智能制造的快速推进,制造业转型升级到了关键阶段。越来越多的企业以数字化技术搭配智能机器人及智慧产线,主动实现数字化转型。达索系统3D体验平台是实现企业数字化转型的新一代数智化平台,基于型、数字驱动、数字化连续技术,…

基于Socket简单的UDP网络程序

⭐小白苦学IT的博客主页 ⭐初学者必看:Linux操作系统入门 ⭐代码仓库:Linux代码仓库 ❤关注我一起讨论和学习Linux系统 1.前言 网络编程前言 网络编程是连接数字世界的桥梁,它让计算机之间能够交流信息,为我们的生活和工作带来便利…

ICLR24_OUT-OF-DISTRIBUTION DETECTION WITH NEGATIVE PROMPTS

摘要 分布外检测(OOD Detection)的研究对于开放世界(open-world)学习非常重要。受大模型(CLIP)启发,部分工作匹配图像特征和提示来实现文本-图像特征之间的相似性。 现有工作难以处理具有与已…

牛顿:Archetype AI 的开创性模型,实时解读真实世界的新宠儿

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

免费云服务器汇总,最长永久免费使用

随着云计算技术的快速发展,越来越多的企业和个人开始将业务迁移到云端。云服务器作为云计算的重要组成部分,以其灵活、高效、可扩展等特点受到广泛关注。然而,许多人在初次接触云服务器时,可能会对高昂的价格望而却步。为了帮助大…

VBA数据库解决方案第九讲:把数据库的内容在工作表中显示

《VBA数据库解决方案》教程(版权10090845)是我推出的第二套教程,目前已经是第二版修订了。这套教程定位于中级,是学完字典后的另一个专题讲解。数据库是数据处理的利器,教程中详细介绍了利用ADO连接ACCDB和EXCEL的方法…