LoRa终端设备ASR6505之PingPong通信

前言:前面几篇文章详细介绍了ASR6505外设的使用,从本篇开始介绍ASR6505关于LoRa的使用。

1、关于ASR6505的LoRa

ASR6505是SIP封装的STM8L和SX1262,因此对SX1262的操作实质就是对一个SPI外设的操作。

ASR6505内部连接:

SX1262 STM8L

RESET <--------------> PH_0

MOSI <--------------> PI_2

MISO <--------------> PI_3

SCLK <--------------> PI_1

BUSY <--------------> PH_1

DIO_1 <--------------> PH_2

BUSY:SX1262忙检测引脚,DIO1:通常配置为外部中断,来唤醒mcu起来处理射频事件。

另外SX1262的NSS以及射频开关电源控制引脚连接:

NSS <---------------> PD_7

SWITCH_POWER <--------------> PG_6

因此,后续的射频操作都是基于上面的连接进行的。LoRa的寄存器繁多,所幸的是,官方已经提供了完整的驱动,我们首先是要会用,然后再去深究原理。

2、PingPong通信

所谓“PingPong”:就是一发一收、一发一收,如此反复循环,即就是通常所说的点对点通讯,市面上的大部分私有协议(非LoRaWAN)也是在此基础上改进的。一些小型物联网搭建,就可以用点对点通讯。

3、无线射频参数

频率:无线最重要的参数,虽然SX1262支持150-960MHZ,但是为了更好的硬件射频性能,硬件已经匹配为470-510M。

发射功率:0-22dBm,功率越大,功耗越大。

扩频因子:也可以理解成速率,取值6-12,6速率最快,12最慢,速率越快,抗干扰越差,距离越近,反之。

编码率:取值1-4,分别对应4/5,4/6, 4/7, 4/8。

IQ极性:收发要保持相同。

4、实验设计

两个开发板相互发送数据,串口打印接收的数据,并打印RSSI和SNR。

5、核心代码

int main( void )
{
    bool isMaster = true;// 主从机,从机的时候改为false
    uint8_t i;
    // Target board initialization
    BoardInitMcu( );
    BoardInitPeriph( );

    printf("ASR6505 PingPong  test !\r\n");
    // Radio initialization
    RadioEvents.TxDone = OnTxDone; //注册回调函数,下同
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.TxTimeout = OnTxTimeout;
    RadioEvents.RxTimeout = OnRxTimeout;
    RadioEvents.RxError = OnRxError;

    Radio.Init( &RadioEvents );
    Radio.SetChannel( RF_FREQUENCY );
    //配置射频收发参数
    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                                   LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                                   LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                                   LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                                   LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
    Radio.Rx( RX_TIMEOUT_VALUE );
    while( 1 )
    {
        switch( State )
        {
            case RX:
              if( isMaster == true )
              {
                 if( BufferSize > 0 )
                  {
                     if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 )
                      {
                          printf("Received: PONG,rssi=%d,snr=%d\r\n",RssiValue,SnrValue);
                          // Send the next PING frame
                          Buffer[0] = 'P';
                          Buffer[1] = 'I';
                          Buffer[2] = 'N';
                          Buffer[3] = 'G';
                          // We fill the buffer with numbers for the payload
                          for( i = 4; i < BufferSize; i++ )
                          {
                             Buffer[i] = i - 4;
                          }
                          DelayMs( 1 );
                          printf("Send: PING\r\n");
                          Radio.Send( Buffer, BufferSize );
                        }
                        else 
                      if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                        { // A master already exists then become a slave
                            isMaster = false;
                            Radio.Rx( RX_TIMEOUT_VALUE );
                        }
                        else // valid reception but neither a PING or a PONG message
                        {    // Set device as master ans start again
                            isMaster = true;
                            Radio.Rx( RX_TIMEOUT_VALUE );
                        }
                    }
                }
                else
                {
                  if( BufferSize > 0 )
                  {
                     if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 )
                     {
                            printf("Received: PING,rssi=%d,snr=%d\r\n",RssiValue,SnrValue);

                            // Send the reply to the PONG string
                            Buffer[0] = 'P';
                            Buffer[1] = 'O';
                            Buffer[2] = 'N';
                            Buffer[3] = 'G';
                            // We fill the buffer with numbers for the payload
                            for( i = 4; i < BufferSize; i++ )
                            {
                                Buffer[i] = i - 4;
                            }
                            DelayMs( 1 );
                            Radio.Send( Buffer, BufferSize );
                            printf("Send: PONG\r\n");
                        }
                        else // valid reception but not a PING as expected
                        {    // Set device as master and start again
                            isMaster = true;
                            Radio.Rx( RX_TIMEOUT_VALUE );
                        }
                    }
                }
                State = LOWPOWER;
                break;
            case TX:
                Radio.Rx( RX_TIMEOUT_VALUE );
                State = LOWPOWER;
                break;
            case RX_TIMEOUT:
            case RX_ERROR:
                if( isMaster == true )
                {
                    // Send the next PING frame
                    Buffer[0] = 'P';
                    Buffer[1] = 'I';
                    Buffer[2] = 'N';
                    Buffer[3] = 'G';
                    for( i = 4; i < BufferSize; i++ )
                    {
                        Buffer[i] = i - 4;
                    }
                    DelayMs( 1 );
                    Radio.Send( Buffer, BufferSize );
                    printf("Sent: PING\r\n");
                }
                else
                {
                    Radio.Rx( RX_TIMEOUT_VALUE );
                }
                State = LOWPOWER;
                break;
            case TX_TIMEOUT:
                Radio.Rx( RX_TIMEOUT_VALUE );
                State = LOWPOWER;
                break;
            case LOWPOWER:
            default:
                // Set low power
                break;
        }
        TimerLowPowerHandler( );
        // Process Radio IRQ
        Radio.IrqProcess( );
    }
}

6、代码分析

主机上电后,处于接收状态,若在一定时间内(设定的RX_TIMEOT)没有收到从机的回复数据,则主机主动发送“Ping”数据。发送完成后处于接收状态,若在一定时间内若收到从机的回复,则从接收转变为发送,继续发送“Ping”数据。若收到从机的回复数据,先判断数据的正确性,然后再打印出来。

从机上电后,处于接收状态,若接收超时,则继续重新接收,直到收到主机的数据。收到数据后,先判断数据的正确性,然后打印RSSI和SNR,最后再发送“Pong”数据回复主机。

7、实现现象

下一篇
举报

扫码关注云+社区

领取腾讯云代金券

,,