LoRa无线通信技术介绍(六)SX127X芯片收发程序讲解
迪丽瓦拉
2025-05-28 21:32:40
0

LoRa接收程序

LoRa接收功能的目的是接收来自无线上的LORA信号,当芯片接收到无线数据后,会通过芯片的IRQ中断引脚触发MCU,进而MCU可通过SPI接口操作寄存器读取接收到的无线数据

所有LoRa数据的收发程序都需要调用SX1276LoRaProcess函数,

uint32_t SX1276LoRaProcess( void )
{uint32_t result = RF_BUSY;switch( RFLRState ){case RFLR_STATE_IDLE:break;case RFLR_STATE_RX_INIT:SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |//RFLR_IRQFLAGS_RXDONE |//RFLR_IRQFLAGS_PAYLOADCRCERROR |RFLR_IRQFLAGS_VALIDHEADER |RFLR_IRQFLAGS_TXDONE |RFLR_IRQFLAGS_CADDONE |//RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |RFLR_IRQFLAGS_CADDETECTED;SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );if( LoRaSettings.FreqHopOn == true ){SX1276LR->RegHopPeriod = LoRaSettings.HopPeriod;SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );}else{SX1276LR->RegHopPeriod = 255;}SX1276Write( REG_LR_HOPPERIOD, SX1276LR->RegHopPeriod );// RxDone                    RxTimeout                   FhssChangeChannel           CadDoneSX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;// CadDetected               ModeReadySX1276LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;SX1276WriteBuffer( REG_LR_DIOMAPPING1, &SX1276LR->RegDioMapping1, 2 );if( LoRaSettings.RxSingleOn == true ) // Rx single mode{SX1276LoRaSetOpMode( RFLR_OPMODE_RECEIVER_SINGLE );}else // Rx continuous mode{SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxBaseAddr;SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );SX1276LoRaSetOpMode( RFLR_OPMODE_RECEIVER );}memset( RFBuffer, 0, ( size_t )RF_BUFFER_SIZE );PacketTimeout = LoRaSettings.RxPacketTimeout;RxTimeoutTimer = GET_TICK_COUNT( );RFLRState = RFLR_STATE_RX_RUNNING;break;case RFLR_STATE_RX_RUNNING:if( DIO0 == 1 ) // RxDone{RxTimeoutTimer = GET_TICK_COUNT( );if( LoRaSettings.FreqHopOn == true ){SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );}// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE  );RFLRState = RFLR_STATE_RX_DONE;}if( DIO2 == 1 ) // FHSS Changed Channel{RxTimeoutTimer = GET_TICK_COUNT( );if( LoRaSettings.FreqHopOn == true ){SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );}// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );// DebugRxGain = SX1276LoRaReadRxGain( );}if( LoRaSettings.RxSingleOn == true ) // Rx single mode{if( ( GET_TICK_COUNT( ) - RxTimeoutTimer ) > PacketTimeout ){RFLRState = RFLR_STATE_RX_TIMEOUT;}}break;case RFLR_STATE_RX_DONE:SX1276Read( REG_LR_IRQFLAGS, &SX1276LR->RegIrqFlags );if( ( SX1276LR->RegIrqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR ) == RFLR_IRQFLAGS_PAYLOADCRCERROR ){// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR  );if( LoRaSettings.RxSingleOn == true ) // Rx single mode{RFLRState = RFLR_STATE_RX_INIT;}else{RFLRState = RFLR_STATE_RX_RUNNING;}break;}{uint8_t rxSnrEstimate;SX1276Read( REG_LR_PKTSNRVALUE, &rxSnrEstimate );if( rxSnrEstimate & 0x80 ) // The SNR sign bit is 1{// Invert and divide by 4RxPacketSnrEstimate = ( ( ~rxSnrEstimate + 1 ) & 0xFF ) >> 2;RxPacketSnrEstimate = -RxPacketSnrEstimate;}else{// Divide by 4RxPacketSnrEstimate = ( rxSnrEstimate & 0xFF ) >> 2;}}SX1276Read( REG_LR_PKTRSSIVALUE, &SX1276LR->RegPktRssiValue );if( LoRaSettings.RFFrequency < 860000000 )  // LF{    if( RxPacketSnrEstimate < 0 ){RxPacketRssiValue = RSSI_OFFSET_LF + ( ( double )SX1276LR->RegPktRssiValue ) + RxPacketSnrEstimate;}else{RxPacketRssiValue = RSSI_OFFSET_LF + ( 1.0666 * ( ( double )SX1276LR->RegPktRssiValue ) );}}else                                        // HF{    if( RxPacketSnrEstimate < 0 ){RxPacketRssiValue = RSSI_OFFSET_HF + ( ( double )SX1276LR->RegPktRssiValue ) + RxPacketSnrEstimate;}else{    RxPacketRssiValue = RSSI_OFFSET_HF + ( 1.0666 * ( ( double )SX1276LR->RegPktRssiValue ) );}}if( LoRaSettings.RxSingleOn == true ) // Rx single mode{SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxBaseAddr;SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );if( LoRaSettings.ImplicitHeaderOn == true ){RxPacketSize = SX1276LR->RegPayloadLength;SX1276ReadFifo( RFBuffer, SX1276LR->RegPayloadLength );}else{SX1276Read( REG_LR_NBRXBYTES, &SX1276LR->RegNbRxBytes );RxPacketSize = SX1276LR->RegNbRxBytes;SX1276ReadFifo( RFBuffer, SX1276LR->RegNbRxBytes );}}else // Rx continuous mode{SX1276Read( REG_LR_FIFORXCURRENTADDR, &SX1276LR->RegFifoRxCurrentAddr );if( LoRaSettings.ImplicitHeaderOn == true ){RxPacketSize = SX1276LR->RegPayloadLength;SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxCurrentAddr;SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );SX1276ReadFifo( RFBuffer, SX1276LR->RegPayloadLength );}else{SX1276Read( REG_LR_NBRXBYTES, &SX1276LR->RegNbRxBytes );RxPacketSize = SX1276LR->RegNbRxBytes;SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxCurrentAddr;SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );SX1276ReadFifo( RFBuffer, SX1276LR->RegNbRxBytes );}}if( LoRaSettings.RxSingleOn == true ) // Rx single mode{RFLRState = RFLR_STATE_RX_INIT;}else // Rx continuous mode{RFLRState = RFLR_STATE_RX_RUNNING;}result = RF_RX_DONE;break;case RFLR_STATE_RX_TIMEOUT:RFLRState = RFLR_STATE_RX_INIT;result = RF_RX_TIMEOUT;break;case RFLR_STATE_TX_INIT:SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );if( LoRaSettings.FreqHopOn == true ){SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |RFLR_IRQFLAGS_RXDONE |RFLR_IRQFLAGS_PAYLOADCRCERROR |RFLR_IRQFLAGS_VALIDHEADER |//RFLR_IRQFLAGS_TXDONE |RFLR_IRQFLAGS_CADDONE |//RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |RFLR_IRQFLAGS_CADDETECTED;SX1276LR->RegHopPeriod = LoRaSettings.HopPeriod;SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );}else{SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |RFLR_IRQFLAGS_RXDONE |RFLR_IRQFLAGS_PAYLOADCRCERROR |RFLR_IRQFLAGS_VALIDHEADER |//RFLR_IRQFLAGS_TXDONE |RFLR_IRQFLAGS_CADDONE |RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL |RFLR_IRQFLAGS_CADDETECTED;SX1276LR->RegHopPeriod = 0;}SX1276Write( REG_LR_HOPPERIOD, SX1276LR->RegHopPeriod );SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );// Initializes the payload sizeSX1276LR->RegPayloadLength = TxPacketSize;SX1276Write( REG_LR_PAYLOADLENGTH, SX1276LR->RegPayloadLength );SX1276LR->RegFifoTxBaseAddr = 0x00; // Full buffer used for TxSX1276Write( REG_LR_FIFOTXBASEADDR, SX1276LR->RegFifoTxBaseAddr );SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoTxBaseAddr;SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );// Write payload buffer to LORA modemSX1276WriteFifo( RFBuffer, SX1276LR->RegPayloadLength );// TxDone               RxTimeout                   FhssChangeChannel          ValidHeader         SX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_01;// PllLock              Mode ReadySX1276LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_01 | RFLR_DIOMAPPING2_DIO5_00;SX1276WriteBuffer( REG_LR_DIOMAPPING1, &SX1276LR->RegDioMapping1, 2 );SX1276LoRaSetOpMode( RFLR_OPMODE_TRANSMITTER );RFLRState = RFLR_STATE_TX_RUNNING;break;case RFLR_STATE_TX_RUNNING:if( DIO0 == 1 ) // TxDone{// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE  );RFLRState = RFLR_STATE_TX_DONE;   }if( DIO2 == 1 ) // FHSS Changed Channel{if( LoRaSettings.FreqHopOn == true ){SX1276Read( REG_LR_HOPCHANNEL, &SX1276LR->RegHopChannel );SX1276LoRaSetRFFrequency( HoppingFrequencies[SX1276LR->RegHopChannel & RFLR_HOPCHANNEL_CHANNEL_MASK] );}// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );}break;case RFLR_STATE_TX_DONE:// optimize the power consumption by switching off the transmitter as soon as the packet has been sentSX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );RFLRState = RFLR_STATE_IDLE;result = RF_TX_DONE;break;case RFLR_STATE_CAD_INIT:    SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );SX1276LR->RegIrqFlagsMask = RFLR_IRQFLAGS_RXTIMEOUT |RFLR_IRQFLAGS_RXDONE |RFLR_IRQFLAGS_PAYLOADCRCERROR |RFLR_IRQFLAGS_VALIDHEADER |RFLR_IRQFLAGS_TXDONE |//RFLR_IRQFLAGS_CADDONE |RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL; // |//RFLR_IRQFLAGS_CADDETECTED;SX1276Write( REG_LR_IRQFLAGSMASK, SX1276LR->RegIrqFlagsMask );// RxDone                   RxTimeout                   FhssChangeChannel           CadDoneSX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;// CAD Detected              ModeReadySX1276LR->RegDioMapping2 = RFLR_DIOMAPPING2_DIO4_00 | RFLR_DIOMAPPING2_DIO5_00;SX1276WriteBuffer( REG_LR_DIOMAPPING1, &SX1276LR->RegDioMapping1, 2 );SX1276LoRaSetOpMode( RFLR_OPMODE_CAD );RFLRState = RFLR_STATE_CAD_RUNNING;break;case RFLR_STATE_CAD_RUNNING:if( DIO3 == 1 ) //CAD Done interrupt{ // Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE  );if( DIO4 == 1 ) // CAD Detected interrupt{// Clear IrqSX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED  );// CAD detected, we have a LoRa preambleRFLRState = RFLR_STATE_RX_INIT;result = RF_CHANNEL_ACTIVITY_DETECTED;} else{    // The device goes in Standby Mode automatically    RFLRState = RFLR_STATE_IDLE;result = RF_CHANNEL_EMPTY;}}   break;default:break;} return result;
}

以上程序是LORA芯片的状态处理程序,数据能够正常收发对传数据的前提时,收发接到的相关LORA参数需要全部一致。

对于接收功能,需要调用以下程序进行接收,当程序返回的数据长度大于0时,代表收到无线数据,收到的无线数据将拷贝到pbuf的缓存内。

unsigned char LORA_Recvframe(unsigned char *pbuf)
{unsigned char rxlen ,RFState;RFState=(tRFProcessReturnCodes)SX1276LoRaProcess();if(RFState==RF_RX_DONE){SX1276LoRaGetRxPacket( pbuf, &rxlen );int rssi=SX1276LoRaGetPacketRssi();int channel=SX1276LoRaGetPacketRxChannel();return rxlen;}return 0;
}

LORA_Recvframe函数必须在需要接收的实际持续调用该函数,直到返回值大于0为止

LoRa发送程序

在发送模式下,仅在需要发送数据包数据的时候才会启动射频模块、PLL模块及PA模块,

这样可以优化功率消耗率。

  • 通过发送TX模式请求,开始数据发送。

  • 一旦完成数据发送,则发出TxDone中断请求,芯片回到待机模式。

  • 发送操作完成后,可以手动将无线设备设置为睡眠模式或重新向FIFO数据缓存写入数

据,以便稍后再次进行Tx操作。

对于发送端,需要实现以下功能的函数

unsigned char LORA_Sendframe(unsigned char *pdat, unsigned char len, int freq,int bw,int sf)
{SX1276LoRaSetOpMode( RFLR_OPMODE_STANDBY );//设置芯片位standby模式SX1276LoRaSetSpreadingFactor( Sf ); //设置扩频因子SX1276LoRaSetSignalBandwidth( Bw );//设置带宽SX1276LoRaSetErrorCoding( 1);SX1276LoRaSetRFFrequency(freq);//设置通信频率单位hzSX1276LoRaSetTxPacket( pdat, len );//调用该函数将带发送的数据拷贝到芯片的fifo中do{}while(SX1276LoRaProcess()!=RF_TX_DONE);//等待发送完成return 1;
}

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...