1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > (29条消息)物联网之LoRa开发与应用四(LoRaPingPang系统设计)

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

时间:2021-12-23 00:56:55

相关推荐

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

深入了解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

程序烧写:

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

调试信息:

串口调试信息

屏幕调试信息

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。