XShell JavaWeb centos7安装 css excel listview gridview plugins module bluetooth onclick 系统后台模板 后台系统模板 河南普通话 php零基础入门视频 mac安装hadoop mysql数据库名称 汇编语言clr python中len函数 python中的map函数 python插件 java正则表达 java接口的使用 java中的数据结构 java自学编程入门教程 java定义字符串 javastring比较 java字符串相等 sql综合利用工具 ae脚本管理器 winterboard skycc组合营销软件 steam怎么卸载 软件龙头股 c程序 renderpartial 数据库编程软件 骰子表情包 华为手环怎么连接手机 top命令详解
当前位置: 首页 > 学习教程  > 

物联网之LoRa开发与应用四(LoRaPingPang系统设计)

2020/10/16 17:46:03 文章标签: lora开发

深入了解LoRa技术原理 内容概要: 1、LoRa扩频通信原理 2、LoRa关键技术参数 3、LoRa数据收发任务 模拟无线通信: 数字无线通信: 无线通信传播方式:地波传播(低于2MHz)、天波传播(2MHz~30MH…

深入了解LoRa技术原理

内容概要

1、LoRa扩频通信原理

2、LoRa关键技术参数

3、LoRa数据收发任务

模拟无线通信

数字无线通信

无线通信传播方式:地波传播(低于2MHz)、天波传播(2MHz~30MHz)、直线传播(30MHz以上)

无线通信传播路径:反射、散射、衍射

无线通信噪声

扩频通信技术:从各种类型的噪声和多径失真中获得免疫性

扩频通信算法:C表示信号质量

扩频通信原理:用户数据和扩频数据异或得到发送数据,增加了信号带宽,提高了信号质量

信号带宽(BW)

增加BW,可以提高有效数据速率以缩短传输时间,但是 以牺牲部分接受灵敏度为代价。对于LoRa芯片SX127x,LoRa带宽为双边带宽(全信道带宽),而FSK调制方式的BW是指单边带宽。

扩频因子(SF):原本使用1位来表示的信号变成多位来表示这个信号,提高信号的通讯质量

LoRa采用多个信息码片来代表有效负载信息的每个位,扩频信息的发送速度称为符号速率(Rs),而码片速率与标称的Rs比值即为扩频因子(SF,SpreadingFactor),表示了每个信息位发送的符号数量。

编码率(CR):提高信号质量的冗余,提高数据的可靠性

编码率(或信息率)是数据流中有用部分(非冗余)的比例。也就是说,如果编码率是k/n,则对每k位有用信息,编码器总共产生n位的数据,其中n-k是多余的。

LoRa采用循环纠错编码进行前向错误检测与纠错。。使用该方式会产生传输开销。

LoRa关键技术参数

LoRa符号速率Rs计算:Rs=BW/(2^SF)

LoRa数据速率DR计算:DR= SF*( BW/2^SF)*CR

LoRaWAN主要使用了125kHz信号带宽设置,但其他专用协议可以利用其他的信号带宽(BW)设置。改变BW、SF和CR也就改变了链路预算和传输时间,需要在电池寿命和距离上做个权衡。

LoRa参数设置

LoRa数据发送序列

数据发送流程:(1)LoRa模块标准模式—>(2)发送模式—>(3)将数据写入发送队列—>(4)发送数据—>(5)等待发送完成(判断数据是否发送完成,如果发送完成则再次进入标准模式,如果还有数据需要发送,则进入第三步)

LoRa数据接收序列

数据接收流程:

Radio事件任务:(官方固件提供的事件处理的任务)

LoRa固件相关代码:初始化时的参数设置 和 事件处理函数

​​sx1276-LoRa.c

// Default settings
tLoRaSettings LoRaSettings =       //设置LoRa参数
{
    870000000,        // RFFrequency
    20,               // Power
    9,                // SignalBw [0: 7.8kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,
                      // 5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz, other: Reserved]
    7,                // SpreadingFactor [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096  chips]
    2,                // ErrorCoding [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
    true,             // CrcOn [0: OFF, 1: ON]
    false,            // ImplicitHeaderOn [0: OFF, 1: ON]
    1,                // RxSingleOn [0: Continuous, 1 Single]
    0,                // FreqHopOn [0: OFF, 1: ON]
    4,                // HopPeriod Hops every frequency hopping period symbols
    100,              // TxPacketTimeout
    100,              // RxPacketTimeout
    128,              // PayloadLength (used for implicit header mode)
};





/*!
 * \brief Process the LoRa modem Rx and Tx state machines depending on the
 *        SX1276 operating mode.
 *
 * \retval rfState Current RF state [RF_IDLE, RF_BUSY, 
 *                                   RF_RX_DONE, RF_RX_TIMEOUT,
 *                                   RF_TX_DONE, RF_TX_TIMEOUT]
 */
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           CadDone
        SX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
                                    // CadDetected               ModeReady
        SX1276LR->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 Irq
            SX1276Write( 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 Irq
            SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL );
            // Debug
            RxGain = 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 Irq
            SX1276Write( 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 4
                RxPacketSnrEstimate = ( ( ~rxSnrEstimate + 1 ) & 0xFF ) >> 2;
                RxPacketSnrEstimate = -RxPacketSnrEstimate;
            }
            else
            {
                // Divide by 4
                RxPacketSnrEstimate = ( 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 size
        SX1276LR->RegPayloadLength = TxPacketSize;
        SX1276Write( REG_LR_PAYLOADLENGTH, SX1276LR->RegPayloadLength );
        
        SX1276LR->RegFifoTxBaseAddr = 0x00; // Full buffer used for Tx
        SX1276Write( REG_LR_FIFOTXBASEADDR, SX1276LR->RegFifoTxBaseAddr );

        SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoTxBaseAddr;
        SX1276Write( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
        
        // Write payload buffer to LORA modem
        SX1276WriteFifo( 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 Ready
        SX1276LR->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 Irq
            SX1276Write( 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 Irq
            SX1276Write( 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 sent
        SX1276LoRaSetOpMode( 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           CadDone
        SX1276LR->RegDioMapping1 = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
                                    // CAD Detected              ModeReady
        SX1276LR->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 Irq
            SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE  );
            if( DIO4 == 1 ) // CAD Detected interrupt
            {
                // Clear Irq
                SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED  );
                // CAD detected, we have a LoRa preamble
                RFLRState = 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;
}

 LoRaPingPong系统设计

内容概要

1、PingPong系统设计需求

2、PingPong系统通信机制

3、PingPong系统业务流程

PingPong系统设计需求

将LoRa终端定义成两种角色:Master(主机)和Slave(从机)

Master主动发送PING数据,接收PANG数据

Slave如果接收到PING数据,回应PANG数据

终端在LCD屏幕上显示终端类型及收发数据包个数

PingPong通信机制

//sx1276-LoRa.c

void SX1276LoRaGetRxPacket( void *buffer, uint16_t *size )//LoRa无线数据接收
{
    *size = RxPacketSize;
    RxPacketSize = 0;
    memcpy( ( void * )buffer, ( void * )RFBuffer, ( size_t )*size );
}

void SX1276LoRaSetTxPacket( const void *buffer, uint16_t size )//LoRa无线数据发送
{
    TxPacketSize = size;
    memcpy( ( void * )RFBuffer, buffer, ( size_t )TxPacketSize ); 

    RFLRState = RFLR_STATE_TX_INIT;//状态设置为发送初始化
}
sx1276-LoRa.h

typedef enum  //LoRa的所有状态。监听和设置这些状态来实现数据的收发
{
    RFLR_STATE_IDLE,           //空闲模式
    RFLR_STATE_RX_INIT,        //接收初始化
    RFLR_STATE_RX_RUNNING,     //接收进行
    RFLR_STATE_RX_DONE,        //接收完成
    RFLR_STATE_RX_TIMEOUT,     //接收超时
    RFLR_STATE_TX_INIT,        //发送初始化
    RFLR_STATE_TX_RUNNING,     //发送进行
    RFLR_STATE_TX_DONE,        //发送完成
    RFLR_STATE_TX_TIMEOUT,     //发送超时
    RFLR_STATE_CAD_INIT,       //
    RFLR_STATE_CAD_RUNNING,
}tRFLRStates;

 PingPong业务流程-初始化

PingPong业务流程-Master

PingPong业务流程-Slave

LoRa参数设置

// Default settings
tLoRaSettings LoRaSettings =       //设置LoRa参数
{
    870000000,        // RFFrequency
    20,               // Power
    9,                // SignalBw [0: 7.8kHz, 1: 10.4 kHz, 2: 15.6 kHz, 3: 20.8 kHz, 4: 31.2 kHz,
                      // 5: 41.6 kHz, 6: 62.5 kHz, 7: 125 kHz, 8: 250 kHz, 9: 500 kHz, other: Reserved]
    7,                // SpreadingFactor [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096  chips]
    2,                // ErrorCoding [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
    true,             // CrcOn [0: OFF, 1: ON]
    false,            // ImplicitHeaderOn [0: OFF, 1: ON]
    1,                // RxSingleOn [0: Continuous, 1 Single]
    0,                // FreqHopOn [0: OFF, 1: ON]
    4,                // HopPeriod Hops every frequency hopping period symbols
    100,              // TxPacketTimeout
    100,              // RxPacketTimeout
    128,              // PayloadLength (used for implicit header mode)
};

数据包结构:

LoRaPingPang系统功能开发

内容概要

1、IAR工程配置

2、搭建框架

3、编码

IAR工程配置:配置两个工程:Master 和 Slave(两个工程公用一个代码,修改一个工程下的代码,所有工程代码一起改变

建立功能函数:建立四个函数(LCD菜单显示信息、无线收发任务处理)

//**********************************//
//
//函数名称:  MLCD_Show 
//
//函数描述:   主机显示任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void MLCD_Show(void)
{
  uint8_t str[20] = {0};
  //LCDgpio重新初始化
  LCD_GPIO_Init();

  sprintf((char*)str,"%d",Master_RxNumber);
  show_rx(str);将RX数据显示到屏幕上
  memset((char*)str,0,strlen((const char*)str));


  sprintf((char*)str,"%d",Master_TxNumber);
  show_tx(str);将TX数据显示到屏幕上

  //SPI重新初始化
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
}


//**********************************//
//
//函数名称:  SLCD_Show 
//
//函数描述:   从机显示任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:    
//*******************************//

void SLCD_Show(void)
{
  uint8_t str[20] = {0};
  //LCDgpio重新初始化
  LCD_GPIO_Init();

  sprintf((char*)str,"%d",Slave_RxNumber);
  show_rx(str);将RX数据显示到屏幕上
  memset((char*)str,0,strlen((const char*)str));


  sprintf((char*)str,"%d",Slave_TxNumber);
  show_tx(str);将TX数据显示到屏幕上

  //SPI重新初始化
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
}

//**********************************//
//
//函数名称:   Master_Task
//
//函数描述:   主机无线任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void Master_Task(void)//无线任务处理函数会在下面补齐,这里只是搭建了一个框架
{
  
}


//**********************************//
//
//函数名称:   Slave_Task
//
//函数描述:   从机无线任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void Slave_Task(void)//无线任务处理函数会在下面补齐,这里只是搭建了一个框架
{

}

建立数据结构:声明全部变量、进行赋值初始化

#define BUFFERSIZE 4

uint8_t PingMsg[] = "PING";//PING数据
uint8_t PongMsg[] = "PONG";//PONG数据

uint16_t BufferSize = BUFFERSIZE;
uint8_t Buffer[BUFFERSIZE];//接收数据缓存

#ifdef MASTER
uint8_t EnbleMaster = true;
#else
uint8_t EnbleMaster = false;
#endif

uint32_t Master_TxNumber = 0;//发送数据计数
uint32_t Master_RxNumber = 0;//接收数据计数

uint32_t Slave_TxNumber = 0;//发送数据计数
uint32_t Slave_RxNumber = 0;//接收数据计数

tRadioDriver *Radio = NULL;/*如果需要收发任务,则要获取无线收发的数据结构:
                            在main函数中调用无线收发任务函数RadioDriverInit
                           进行初始化,返回一个初始化的结构体指针*/

无线收发任务初始化函数RadioDriverInit:

tRadioDriver RadioDriver;

tRadioDriver* RadioDriverInit( void )//如果需要使用无线收发任务,则需要在main函数中调用该函数进行初始化,返回一个初始化的指针
{
#if defined( USE_SX1232_RADIO )
    RadioDriver.Init = SX1232Init;
    RadioDriver.Reset = SX1232Reset;
    RadioDriver.StartRx = SX1232StartRx;
    RadioDriver.GetRxPacket = SX1232GetRxPacket;
    RadioDriver.SetTxPacket = SX1232SetTxPacket;
    RadioDriver.Process = SX1232Process;
#elif defined( USE_SX1272_RADIO )
    RadioDriver.Init = SX1272Init;
    RadioDriver.Reset = SX1272Reset;
    RadioDriver.StartRx = SX1272StartRx;
    RadioDriver.GetRxPacket = SX1272GetRxPacket;
    RadioDriver.SetTxPacket = SX1272SetTxPacket;
    RadioDriver.Process = SX1272Process;
#elif defined( USE_SX1276_RADIO )
    RadioDriver.Init = SX1276Init;
    RadioDriver.Reset = SX1276Reset;
    RadioDriver.StartRx = SX1276StartRx;
    RadioDriver.GetRxPacket = SX1276GetRxPacket;
    RadioDriver.SetTxPacket = SX1276SetTxPacket;
    RadioDriver.Process = SX1276Process;
#else
    #error "Missing define: USE_XXXXXX_RADIO (ie. USE_SX1272_RADIO)"
#endif    

    return &RadioDriver;
}

编码

功能函数编码

//上面已经对功能函数搭建好框架,现将实现代码填充进去

//**********************************//
//
//函数名称:  MLCD_Show 
//
//函数描述:   主机显示任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void MLCD_Show(void)
{
  uint8_t str[20] = {0};
  //LCDgpio重新初始化
  LCD_GPIO_Init();

  sprintf((char*)str,"%d",Master_RxNumber);
  show_rx(str);将RX数据显示到屏幕上
  memset((char*)str,0,strlen((const char*)str));


  sprintf((char*)str,"%d",Master_TxNumber);
  show_tx(str);将TX数据显示到屏幕上

  //SPI重新初始化
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
}


//**********************************//
//
//函数名称:  SLCD_Show 
//
//函数描述:   从机显示任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:    
//*******************************//

void SLCD_Show(void)
{
  uint8_t str[20] = {0};
  //LCDgpio重新初始化
  LCD_GPIO_Init();

  sprintf((char*)str,"%d",Slave_RxNumber);
  show_rx(str);将RX数据显示到屏幕上
  memset((char*)str,0,strlen((const char*)str));


  sprintf((char*)str,"%d",Slave_TxNumber);
  show_tx(str);将TX数据显示到屏幕上

  //SPI重新初始化
  HAL_SPI_DeInit(&hspi1);
  MX_SPI1_Init();
}

//**********************************//
//
//函数名称:   Master_Task
//
//函数描述:   主机无线任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void Master_Task(void)//无线任务处理函数
{
  switch(Radio->Process())//执行无线功能任务处理函数SX1276LoRaProcess,返回一个无线功能状态值,然后根据状态值做相应的处理
  {
    
    case RF_RX_DONE:
         Radio->GetRxPacket(Buffer,&BufferSize);//接收数据
         printf("Master_Task:RX_____%s\n",Buffer);//串口打印接收的数据
         if(strncmp((const char*)Buffer,(const char*)PongMsg,strlen((const char*)PongMsg)) == 0)//判断接收的是否为PONG数据
         {
          LedToggle(LED_RX);//发送指示灯翻转
          Master_RxNumber++;//发送计数
          Radio->SetTxPacket(PingMsg,strlen((const char*)PingMsg));//打开发送模式
          HAL_Delay(200);
         }
    break;
    case RF_TX_DONE:
          LedToggle(LED_TX);//接收指示灯翻转
          Master_TxNumber++;//接收计数
          Radio->StartRx();//打开接收模式
    break;
    default :
    break;
  }
}


//**********************************//
//
//函数名称:   Slave_Task
//
//函数描述:   从机无线任务
//
//函数参数:   无
//
//返回值:     无
//
//创建者:     
//*******************************//

void Slave_Task(void)//无线任务处理函数
{

  switch(Radio->Process())
  {
    
    case RF_RX_DONE:
         Radio->GetRxPacket(Buffer,&BufferSize);
         printf("Slave_Task:RX_____%s\n",Buffer);
         if(strncmp((const char*)Buffer,(const char*)PingMsg,strlen((const char*)PingMsg)) == 0)
         {
          LedToggle(LED_RX);
          Slave_RxNumber++;
          Radio->SetTxPacket(PongMsg,strlen((const char*)PongMsg));
          HAL_Delay(200);
         }
    break;
    case RF_TX_DONE:
          LedToggle(LED_TX);
          Slave_TxNumber++;
          Radio->StartRx();
    break;
    default :
    break;
  }
}

Main函数编码

  Lcd_Init();//LCD初始化函数
  
  
  Lcd_Clear_xy(0,0,GREEN);
  Lcd_Clear_xy(0,45,YELLOW);
 
  Gui_DrawFont_GBK16(12, 10, RED, GREEN, "LoRa Topology");
#ifdef MASTER
  Gui_DrawFont_GBK16(40, 26, RED, GREEN, "Master");
#else
  Gui_DrawFont_GBK16(40, 30, RED, GREEN, "SLAVE");
#endif
  Gui_DrawFont_GBK16(12, 50, BLACK, YELLOW, "SSID:");
  Gui_DrawFont_GBK16(12, 77, BLACK, YELLOW, "RX:");
  Gui_DrawFont_GBK16(12, 104, BLACK, YELLOW, "TX:");
  
  show_ssid("ERROR");
  show_rx("ERROR");
  show_tx("ERROR");
  
  Lcd_WriteIndex(0x29);//Display on  打开LCD屏幕显示
  
  Radio = RadioDriverInit();//如果需要使用无线收发任务,则需要在main函数中调用该函数进行初始化,返回一个初始化的指针
  Radio->Init();//调用Radio初始化函数之后才能正确调用Radio中的其他函数
  
  #ifdef MASTER
  Radio->SetTxPacket(PingMsg,strlen((const char*)PingMsg));//如果是主机,则发送PING数据
  printf("I am Master!\n");
#else
  Radio->StartRx();//如果是从机,则设置为接收状态
  printf("I am Slave!\n");
#endif

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
    
    if(EnbleMaster == true)
    {
      MLCD_Show();
      Master_Task();
    }
    else
    {
      SLCD_Show();
      Slave_Task();
    }

  }

LoRa驱动源码修改

    1、注释掉不用的代码:

    2、设置LoRa参数

    3、因为LoRa无线相关函数涉及到FSK的判断,所以需要添加FSK的相关函数,否则编译不通过:

 

LoRaPingPong系统功能调试

内容概要

1、硬件准备

2、程序烧写

3、调试信息

硬件准备

LoRa设备X2

STlinkX1

USBmini线X2

程序烧写

选择不同的工程进行分别烧录

调试信息

串口调试信息

屏幕调试信息

 


本文链接: http://www.dtmao.cc/news_show_300098.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?