物联网实战--驱动篇之(四)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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2005-2023年各省国内生产总值指数分季度数据

2005-2023年各省国内生产总值指数分季度数据 1、时间:2005-2023年 2、来源:国家统计局、各省统计局 3、指标:地区生产总值指数(上年同期100)_累计值(%) 4、范围:31省 5、时间跨度:季度 6、缺失情况:无…

20240325-1-HMM

HMM 直观理解 马尔可夫链(英语:Markov chain),又称离散时间马尔可夫链(discrete-time Markov chain,缩写为DTMC),因俄国数学家安德烈马尔可夫(俄语:Андре…

Ubuntu 20.04.06 PCL C++学习记录(十六)

[TOC]PCL中点云分割模块的学习 学习背景 参考书籍&#xff1a;《点云库PCL从入门到精通》以及官方代码PCL官方代码链接,&#xff0c;PCL版本为1.10.0&#xff0c;CMake版本为3.16 学习内容 用一组点云数据做简单的平面的分割 源代码及所用函数 源代码 #include<iostr…

Linux 内核:线程的实现

在linux中的线程是轻量级线程&#xff08;Light-Weight-process&#xff0c;LWP&#xff09; 文章目录 线程概念线程实现 线程概念 线程分类 用户级线程内核级线程&#xff0c;没有用户空间&#xff0c;完全工作在内核中&#xff08;下图中没有[]的就是用户级线程&#xff09…

跨服务器迁移nextcloud数据

背景 阿里云最近做活动,99一年的2U2G的服务器,比我原来的1U1G的服务器不知道高到哪里去了,于是决定迁移服务器数据到另一台主机上。原先的计划是直接做一个自定义镜像,然后复制到另一台主机就行,结果发现旧主机是aliyunOS,新主机不想踩这个坑了,决定换成乌班图,因此决定重新搭…

大模型基础知识 - 语言模型及其演进

开场白 人工智能发展到现在&#xff0c;在2个重要领域取得了重大突破&#xff0c;有望达到人类水平&#xff1a; 计算机视觉 &#xff08;Computer Vision, CV&#xff09;-> 希望机器帮助人类处理图像数据自然语言处理&#xff08;Natural Language Processing, NLP&…

基于R语言lavaan结构方程模型(SEM)实践技术应用

原文链接&#xff1a;基于R语言lavaan结构方程模型&#xff08;SEM&#xff09;实践技术应用https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247596681&idx4&sn08753dd4d3e7bc492d750c0f06bba1b2&chksmfa823b6ecdf5b278ca0b94213391b5a222d1776743609cd…

文章自动生成器

1.前言 最近开始想写一些东西&#xff0c;脑子里也有不少想法&#xff0c;但是自己写又比较费时间&#xff0c;而且还要排版&#xff0c;精修&#xff0c;刚开始写的字数甚少&#xff0c;想法也是断断续续&#xff0c;不连贯&#xff0c;本想放弃&#xff0c;但是想到放弃就太…

HarmonyOS实战开发-如何实现跨应用数据共享实例。

介绍 本示例实现了一个跨应用数据共享实例&#xff0c;分为联系人&#xff08;数据提供方&#xff09;和联系人助手&#xff08;数据使用方&#xff09;两部分&#xff1a;联系人支持联系人数据的增、删、改、查等功能&#xff1b;联系人助手支持同步联系人数据&#xff0c;当…

15.队列集

1.简介 在使用队列进行任务之间的“沟通交流”时&#xff0c;一个队列只允许任务间传递的消息为同一种数据类型&#xff0c;如果需要在任务间传递不同数据类型的消息时&#xff0c;那么就可以使用队列集。FreeRTOS提供的队列集功能可以对多个队列进行“监听”&#xff0c;只要…

【数据结构与算法】—— 二叉树

目录 一、树 1、初识树 2、树的一些概念 3、树的表示形式 二、二叉树 1、初识二叉树 2、两种特殊的二叉树 3、二叉树的性质 4、二叉树的遍历 5、实现一棵二叉树 6、二叉树题目&#xff08;没代码的后面会给补上&#xff09; 一、树 1、初识树 &#xff08;1&…

从人机界面设计黄金三法则视角看 ChatGPT 的界面设计的“好”与“坏”

热门文章推荐&#xff1a; &#xff08;1&#xff09;《为什么很多人工作 3 年 却只有 1 年经验&#xff1f;》&#xff08;2&#xff09;《一文掌握大模型提示词技巧&#xff1a;从战略到战术巧》&#xff08;3&#xff09;《AI 时代&#xff0c;程序员的出路在何方&#xff1…

破晓数据新纪元:隐语隐私计算,携手共创安全智能的未来生态

1.业务背景&#xff1a;安全核对产生的土壤 隐语隐私计算在安全核对业务背景下的应用&#xff0c;主要聚焦于解决企业在数据交换和分析过程中面临的隐私保护问题。 在许多行业中&#xff0c;特别是在金融、医疗、政务等领域&#xff0c;数据的安全核对至关重要&#xff0c;例如…

三流大学毕业,物流专业转行自述:“从月薪4K到现在月入2W+,我做到了哪些?”

我是25岁转行学python的。说实在&#xff0c;转行就是奔着挣钱去的。希望我的经历可以给想转行的朋友带来一点启发和借鉴。 先简单介绍下个人背景&#xff0c;三流大学毕业&#xff0c;物流专业&#xff0c;学习能力一般&#xff0c;没啥特别技能&#xff0c;反正就很普通的一…

《springcloud alibaba》 四 seata安装以及使用

目录 准备调整db配置准备创建数据库 seata配置nacos配置confi.txt下载向nacos推送配置的脚本 启动seata新建项目order-seata项目 订单项目数据库脚本pom.xmlapplication.yml启动类实体类dao类service类controller类feign类mapper类 stock-seata 库存项目数据库脚本pom.xmlappli…

python代码使用过程中使用快捷键注释时报错

1.代码 2.代码报错 3.代码注释后的结果 4. 原因

动态输出n位小数——满满都是坑!

【题目描述】 输入正整数a&#xff0c;b&#xff0c;c&#xff0c;输出a/b的小数形式&#xff0c;精确到小数点后c位。a,b ≤10^6 &#xff0c;c≤100。输入包含多组数据&#xff0c;结束标记为a&#xff1d;b&#xff1d;c&#xff1d;0。 【样例输入】 1 6 4 0 0 0 【样…

HIDS是什么,如何保护主机系统

随着网络安全攻防对抗的日趋激烈&#xff0c;主机当前企业和组织的安全运营工作面临的挑战越来越突出&#xff0c;外网防护的同时&#xff0c;内网主机安全防护也越来越重要。 HIDS(Host-based Intrusion Detection System)&#xff0c;是基于主机型入侵检测系统的简称。作为计…

30万奖金谁能瓜分?OurBMC开源大赛决赛入围名单公示

首届开放原子开源大赛基础软件赛道自今年 1 月开启报名以来&#xff0c;吸引了全国各地 BMC 技术爱好者的广泛关注和踊跃报名。该赛事由开放原子开源基金会牵头&#xff0c; OurBMC 社区及理事长单位飞腾信息技术有限公司联合承办&#xff0c;以 “基于 BMC 技术的服务器故障诊…

抖音电商罗盘品牌人群运营策略指南

【干货资料持续更新&#xff0c;以防走丢】 抖音电商罗盘品牌人群运营策略指南 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 抖音运营资料合集&#xff08;完整资料包含以下内容&#xff09; 目录 品牌人群运营策略&#xff0c;旨在帮助品牌通过精细化运营提…