当前位置: 首页 > news >正文

STM32CubeIDE实现基于STM32的LoRa通信程序移植(SPI接口)

一、硬件

 LoRa模块链接:

立创商城:LSD4RF-2F717N30_(LSD(利尔达))LSD4RF-2F717N30中文资料_价格_PDF手册-立创电子商城

官网 :

标准LoRa模组,产品型号:LSD4RF-2F717N30

二、 配置工作

1、准备好printf工程,参考之前的教程

STM32CubeIDE实现printf重定向输出到串口_飞由于度的博客-CSDN博客STM32CubeIDE之printf重定向及串口https://blog.csdn.net/qq_35629563/article/details/1266658382、配置LoRa引脚

①SPI引脚(其他参数保持默认)

 ②控制引脚

将PA15、PB7配置为GPIO_output模式,然后右击引脚分别重命名为LORA_NSS、LORA_RESET

 ③呼吸灯

这里我是用的是PC1作为呼吸灯,其实不论使用哪个引脚控制的呼吸灯,只需将其命名为LED1即可

 

生成代码

三、代码移植

1、将SX1278直接拷贝到Core文件夹下,然后在STM32CubeIDE中刷新工程(快捷键F5)

2、将新添加的文件加入到路径中去

右击platform文件夹,选择Add/remove include path...

需要添加的文件夹一共有三个:platform、platform下的sx12xxEiger、radio

 四、代码修改

1、spi.c

在USER CODE BEGIN 1下添加以下代码

uint8_t SpiInOut( uint8_t TxData )
{
  uint8_t Rxdata;
  HAL_SPI_TransmitReceive(&hspi3,&TxData,&Rxdata,1, 1000);
  return Rxdata; 
}

2、spi.h

在USER CODE BEGIN Prototypes下添加以下代码

uint8_t SpiInOut( uint8_t TxData );

3、main.c

①在USER CODE BEGIN Includes下添加以下代码(为了简单,变量、函数都添加到了这里)

#include <stdio.h>
#include <string.h>

#include "radio.h"
#include "platform.h"
#include "sx1276.h"
#include "sx1276-Hal.h"
#include "sx1276-LoRa.h"
#include "sx1276-LoRaMisc.h"

#define BUFFERSIZE 200//收发数据的最大字节数

#define CIRCLE     16 //收发循环的次�??

uint8_t LoRa_TX_BUFF[BUFFERSIZE]={
		00,01,//the ID of the send package
		0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,//constant,easy to find error in the transition
		0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,
		0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99};
uint8_t LoRa_RX_BUFF[BUFFERSIZE];//接收缓冲区,200字节
uint16_t LoraTxLength=8;//记录发�?�数据的长度
uint16_t LoraRxLength=8;//记录接收数据的长�??

uint8_t START_RECEIVE_FLAG=0;
uint16_t nRx=0;//接收LoRa数据包的个数
uint16_t nTx=0;//发�?�LoRa数据包的个数


tRadioDriver *Radio=NULL;

bool LoraTxOn=false;


uint16_t last_ID=0;//record the first package's ID when the received MCU started

uint8_t ndelay=0;
uint8_t hh=0,mm=0,ss=0;

void Check_SPI_LoRa(void)
{
	uint8_t Reg_Version=0;//LoRa的版本,0x12=18才说明SPI通了
	uint8_t CIRCLE_MAX=5;//发�?�循环的次数
	uint8_t t=0;
	uint32_t lora_process=0;

	while(1)//测试SPI是否正常
	{
		SX1276Read( REG_LR_VERSION, &Reg_Version );
		if(Reg_Version!=0x12){
			printf("--------SPI read ERROR !!! --------\r\n");
			printf("LoRa Version = %d !\r\n",Reg_Version);
			HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
			HAL_Delay(100);
		}
		else{
			printf("SPI read SUCCESS !!!\r\n");
			printf("LoRa Version = %d !\r\n",Reg_Version);
			break;
		}
	}

	while(1)//测试LoRa是否正常
	{
		if(t++ > CIRCLE_MAX){
			SX1276LoRaSetTxPacket( LoRa_TX_BUFF, LoraTxLength);
			printf("-----------= TX START =-----------\r\n");
			printf("TX:%s \r\n",LoRa_TX_BUFF);
			t=0;
		}
		printf(" t = %d\r\n",t);
		lora_process=SX1276LoRaProcess();
		switch(lora_process)
		{
		case RF_IDLE:	//空闲状�??
			printf("lora process:RF_IDLE\r\n");
			t=CIRCLE_MAX+1;
			break;
		case RF_BUSY:	//模块执行任务�??
			printf("lora process:RF_BUSY\r\n");
			break;
		case RF_TX_DONE:
			//      printf("lora process:RF_TX_DONE\r\n");
			printf("-----------= LoRa TX END =-----------\r\n");
			return;
			break;
		default:
			printf("lora process=%d:unknown status\r\n",(int)lora_process);
			break;
		}
		HAL_Delay(200);
	}
}

void LoRaTxTask(void)
{
	uint8_t RSSI=0,i=0;
	nTx++;
	LoRa_TX_BUFF[0]=(nTx&0xff00)>>8;
	LoRa_TX_BUFF[1]=nTx&0xff;
	SX1276LoRaSetTxPacket( LoRa_TX_BUFF,LoraTxLength );//写入要发送的数据//LoraTxLength
	while(RF_TX_DONE!=SX1276LoRaProcess())HAL_Delay(10);//等待发�?�完�??

	for(i=0;i<LoraTxLength;i++)
	        printf("%02X->",LoRa_TX_BUFF[i]);
	printf("\r\n===========LoRa_TX_DONE: %d===========\r\n",nTx);
	//读取RSSI
	SX1276Read( REG_LR_PKTRSSIVALUE, &RSSI );
	printf("REG_LR_PKTRSSIVALUE=%d\r\n",RSSI-137);
	SX1276Read( REG_LR_RSSIVALUE, &RSSI );
	printf("REG_LR_RSSIVALUE=%d\r\n",RSSI-137);
	printf("===========LoRa_TX_DONE: %d===========\r\n",nTx);
}



void Rx_data_process(void)
{
  uint8_t RSSI=0;
  nRx++;//sometime send 5 pack,but only receive the fifth pack
  nTx=(((uint16_t)LoRa_RX_BUFF[0]<<8)&0xff00)+LoRa_RX_BUFF[1];//the numb of send package

  if(nTx==1){ //if this package is the first of send
    nRx=1;
    last_ID=nTx-1;
  }

  if(START_RECEIVE_FLAG==0)//if receive MCU is first start
  {
    START_RECEIVE_FLAG=1;
    nRx=1;
    last_ID=nTx-1;
  }

  //count the percentage of receive
    printf("ID=%d  last_ID=%d\r\n",nTx,last_ID);//ID is the new package;last_ID is the received package ID when the MCU firstly started
    printf("rx=%d,tx=%d\r\n",nRx,nTx-last_ID);//rx is the number of received package from the received MCU started;
    										//nTx-last_ID is the number of send package from the received MCU started
    printf("rx percentage=%f\r\n",(float)(nRx*100.0/(nTx-last_ID)));
  //read RSSI
  SX1276Read( REG_LR_PKTRSSIVALUE, &RSSI );
  printf("REG_LR_PKTRSSIVALUE=%d\r\n",RSSI-137); //the closer the lower;the lower the better,the lowest can be -45
  SX1276Read( REG_LR_RSSIVALUE, &RSSI );
  printf("REG_LR_RSSIVALUE=%d\r\n",RSSI-137);

}
void LoRaRxTask(void)
{
  uint32_t lora_process=RF_IDLE,i=0;

  lora_process=SX1276LoRaProcess();
  switch(lora_process)
  {
  case RF_IDLE:
//    printf("loraprocess:RF_IDLE\r\n");
    break;
  case RF_RX_DONE:
//    printf("loraprocess:RF_RX_DONE\r\n");
    memset(LoRa_RX_BUFF,0,BUFFERSIZE);//娓呯┖缂撳啿鍖�
    SX1276LoRaGetRxPacket(LoRa_RX_BUFF,&LoraRxLength);//璇诲彇鎺ユ敹鏁版�???
    printf("LoRa RX data=\r\n");
    for(i=0;i<LoraRxLength;i++)
        printf("%02X->",LoRa_RX_BUFF[i]);
    printf("\r\n---------- LoRa RX DONE ----------\r\n");

    Rx_data_process();
    break;
  case RF_BUSY:
    //      printf("loraprocess:RF_BUSY\r\n");
    break;
  default:
    printf("loraprocess=%d:unknown status\r\n",(int)lora_process);
    break;
  }
}


void TimeHandle(void)
{
	HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
	if(++ss>=60){
		ss=0;mm++;
		if(mm>=60){
			mm=0;hh++;
		}
	}
	printf(" time =%2dh - %02dm - %02ds \r\n",hh,mm,ss);
	//LoRa send a package every 2s
	if(ss%2==0)
		LoRaTxTask();
}

②在USER CODE BEGIN Includes下添加以下代码

  SX1276Init();// Initialize LoRa modem
  Check_SPI_LoRa();//to check whether SPI can work correctly
  SX1276StartRx();//

③在

相关文章:

  • JQuery系列之元素操作
  • BLEMotion-Kit 支蓝牙运动传感评估套件
  • 网课查题公众号平台及平台系统如何使用
  • 标准中文电码查询易语言代码
  • 影视新闻查询易语言代码
  • 开发环境搭建-windows系统使用nvm安装配置node本地环境
  • nacos配置中心的使用规则
  • 计算机毕业设计springboot+vue基本微信小程序的学生健康管理小程序
  • 董宇辉:读书让你更加深刻|程序员必读的一本书
  • Spring注解驱动之InitializingBean和DisposableBean
  • 微信输入法来了,如何下载?
  • Metacat实现原理解析
  • MTK Camera Senor Bring up 复盘总结
  • map有关的运算符重载
  • Java项目硅谷课堂学习笔记-P9-整合网关与实现订单和营销管理模块
  • 【RocksDB】TransactionDB源码分析
  • 【前端学习】-粗谈选择器
  • 07.Android之多媒体问题
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Android Studio:GIT提交项目到远程仓库
  • echarts的各种常用效果展示
  • ES学习笔记(12)--Symbol
  • extract-text-webpack-plugin用法
  • JavaScript设计模式之工厂模式
  • Java面向对象及其三大特征
  • js对象的深浅拷贝
  • k8s如何管理Pod
  • laravel with 查询列表限制条数
  • 程序员最讨厌的9句话,你可有补充?
  • 利用jquery编写加法运算验证码
  • 通过npm或yarn自动生成vue组件
  • 通信类
  • 为什么要用IPython/Jupyter?
  •  一套莫尔斯电报听写、翻译系统
  • 用Visual Studio开发以太坊智能合约
  • No resource identifier found for attribute,RxJava之zip操作符
  • MyCAT水平分库
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​iOS实时查看App运行日志
  • ###C语言程序设计-----C语言学习(3)#
  • #Java第九次作业--输入输出流和文件操作
  • #大学#套接字
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET:自动将请求参数绑定到ASPX、ASHX和MVC(菜鸟必看)
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .NET框架
  • .NET中使用Protobuffer 实现序列化和反序列化
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)
  • @EventListener注解使用说明