最近有个项目,要做微型网关,对于尺寸、体积、功耗、成本以及开发周期有要求,方案基于以前的Lora网关为基础进行快速研发,里面唯一的难点就是用一个MCU驱动多个SX1278,通过对比SX1278的sx12xxDrivers-V2.1.0和sx12xxDrivers-V4.4.2,发现V4.4.2驱动更好修改,于是决定在V4.4.2驱动基础之上增加支持多片SX1278功能。

sx12xxDrivers-V4.4.2驱动移植请看:Lora1278驱动V4.4.2讲解一:驱动移植

一、思路

增加多片SX1278的总体思路就是运用面向对象思想实现,举例:

SX1278Drivers RF1,RF2RF3;

RF1.init();

RF2.init();

RF3.init();

等等,实现起来很轻松,在嵌入式C开发中怎么实现呢,思路如下:

抽象出功能相同的一套函数,抽象出功能不通的函数并定义函数指针,把全局变量和函数指针定义成结构体,定义RF1/RF2/RF3实体,并把实体指针当做那套抽象出的函数的入参。类似如下:

    net_work_rf_process(&s_tNetWorkRF1);                       //无线线程net_work_protocol_analysis_process(&s_tNetWorkRF1);        //协议解析father_station_routing_table_maintenance(&s_tNetWorkRF1);  //父节路由点维护net_work_logic_process(&s_tNetWorkRF1);                    //组网逻辑net_work_check_sx1278_process(&s_tNetWorkRF1);             //SX1278维护线程s_tNetWorkRF1.ptRadio->IrqProcess(&s_tNetWorkRF1.tSX1276); //DIO0处理函数

二、驱动修改

sx12xxDrivers-V4.4.2详细说明请看上篇博客(驱动讲解一),总体思路如下:

1、radio.h抽象出驱动接口;

/*!* \brief Radio driver definition*/
struct Radio_s
{/*!* \brief Initializes the radio** \param [IN] events Structure containing the driver callback functions*/void    ( *Init )( RadioEvents_t *events );/*!* Return current radio status** \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]*/RadioState_t ( *GetStatus )( void );/*!* \brief Configures the radio with the given modem** \param [IN] modem Modem to be used [0: FSK, 1: LoRa]*/void    ( *SetModem )( RadioModems_t modem );/*!* \brief Sets the channel frequency** \param [IN] freq         Channel RF frequency*/void    ( *SetChannel )( uint32_t freq );/*!* \brief Checks if the channel is free for the given time** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] freq       Channel RF frequency* \param [IN] rssiThresh RSSI threshold* \param [IN] maxCarrierSenseTime Max time while the RSSI is measured** \retval isFree         [true: Channel is free, false: Channel is not free]*/bool    ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime );/*!* \brief Generates a 32 bits random value based on the RSSI readings** \remark This function sets the radio in LoRa modem mode and disables*         all interrupts.*         After calling this function either Radio.SetRxConfig or*         Radio.SetTxConfig functions must be called.** \retval randomValue    32 bits random value*/uint32_t ( *Random )( void );/*!* \brief Sets the reception parameters** \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] bandwidth    Sets the bandwidth*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: [0: 125 kHz, 1: 250 kHz,*                                 2: 500 kHz, 3: Reserved]* \param [IN] datarate     Sets the Datarate*                          FSK : 600..300000 bits/s*                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,*                                10: 1024, 11: 2048, 12: 4096  chips]* \param [IN] coderate     Sets the coding rate (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: N/A ( set to 0 )* \param [IN] preambleLen  Sets the Preamble length*                          FSK : Number of bytes*                          LoRa: Length in symbols (the hardware adds 4 more symbols)* \param [IN] symbTimeout  Sets the RxSingle timeout value*                          FSK : timeout in number of bytes*                          LoRa: timeout in symbols* \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]* \param [IN] payloadLen   Sets payload length when fixed length is used* \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]* \param [IN] freqHopOn    Enables disables the intra-packet frequency hopping*                          FSK : N/A ( set to 0 )*                          LoRa: [0: OFF, 1: ON]* \param [IN] hopPeriod    Number of symbols between each hop*                          FSK : N/A ( set to 0 )*                          LoRa: Number of symbols* \param [IN] iqInverted   Inverts IQ signals (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [0: not inverted, 1: inverted]* \param [IN] rxContinuous Sets the reception in continuous mode*                          [false: single mode, true: continuous mode]*/void    ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth,uint32_t datarate, uint8_t coderate,uint32_t bandwidthAfc, uint16_t preambleLen,uint16_t symbTimeout, bool fixLen,uint8_t payloadLen,bool crcOn, bool freqHopOn, uint8_t hopPeriod,bool iqInverted, bool rxContinuous );/*!* \brief Sets the transmission parameters** \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] power        Sets the output power [dBm]* \param [IN] fdev         Sets the frequency deviation (FSK only)*                          FSK : [Hz]*                          LoRa: 0* \param [IN] bandwidth    Sets the bandwidth (LoRa only)*                          FSK : 0*                          LoRa: [0: 125 kHz, 1: 250 kHz,*                                 2: 500 kHz, 3: Reserved]* \param [IN] datarate     Sets the Datarate*                          FSK : 600..300000 bits/s*                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,*                                10: 1024, 11: 2048, 12: 4096  chips]* \param [IN] coderate     Sets the coding rate (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]* \param [IN] preambleLen  Sets the preamble length*                          FSK : Number of bytes*                          LoRa: Length in symbols (the hardware adds 4 more symbols)* \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]* \param [IN] crcOn        Enables disables the CRC [0: OFF, 1: ON]* \param [IN] freqHopOn    Enables disables the intra-packet frequency hopping*                          FSK : N/A ( set to 0 )*                          LoRa: [0: OFF, 1: ON]* \param [IN] hopPeriod    Number of symbols between each hop*                          FSK : N/A ( set to 0 )*                          LoRa: Number of symbols* \param [IN] iqInverted   Inverts IQ signals (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [0: not inverted, 1: inverted]* \param [IN] timeout      Transmission timeout [ms]*/void    ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev,uint32_t bandwidth, uint32_t datarate,uint8_t coderate, uint16_t preambleLen,bool fixLen, bool crcOn, bool freqHopOn,uint8_t hopPeriod, bool iqInverted, uint32_t timeout );/*!* \brief Checks if the given RF frequency is supported by the hardware** \param [IN] frequency RF frequency to be checked* \retval isSupported [true: supported, false: unsupported]*/bool    ( *CheckRfFrequency )( uint32_t frequency );/*!* \brief Computes the packet time on air in ms for the given payload** \Remark Can only be called once SetRxConfig or SetTxConfig have been called** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] pktLen     Packet payload length** \retval airTime        Computed airTime (ms) for the given packet payload length*/uint32_t  ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen );/*!* \brief Sends the buffer of size. Prepares the packet to be sent and sets*        the radio in transmission** \param [IN]: buffer     Buffer pointer* \param [IN]: size       Buffer size*/void    ( *Send )( uint8_t *buffer, uint8_t size );/*!* \brief Sets the radio in sleep mode*/void    ( *Sleep )( void );/*!* \brief Sets the radio in standby mode*/void    ( *Standby )( void );/*!* \brief Sets the radio in reception mode for the given time* \param [IN] timeout Reception timeout [ms]*                     [0: continuous, others timeout]*/void    ( *Rx )( uint32_t timeout );/*!* \brief Start a Channel Activity Detection*/void    ( *StartCad )( void );/*!* \brief Sets the radio in continuous wave transmission mode** \param [IN]: freq       Channel RF frequency* \param [IN]: power      Sets the output power [dBm]* \param [IN]: time       Transmission mode timeout [s]*/void    ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time );/*!* \brief Reads the current RSSI value** \retval rssiValue Current RSSI value in [dBm]*/int16_t ( *Rssi )( RadioModems_t modem );/*!* \brief Writes the radio register at the specified address** \param [IN]: addr Register address* \param [IN]: data New register value*/void    ( *Write )( uint16_t addr, uint8_t data );/*!* \brief Reads the radio register at the specified address** \param [IN]: addr Register address* \retval data Register value*/uint8_t ( *Read )( uint16_t addr );/*!* \brief Writes multiple radio registers starting at address** \param [IN] addr   First Radio register address* \param [IN] buffer Buffer containing the new register's values* \param [IN] size   Number of registers to be written*/void    ( *WriteBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );/*!* \brief Reads multiple radio registers starting at address** \param [IN] addr First Radio register address* \param [OUT] buffer Buffer where to copy the registers data* \param [IN] size Number of registers to be read*/void    ( *ReadBuffer )( uint16_t addr, uint8_t *buffer, uint8_t size );/*!* \brief Sets the maximum payload length.** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] max        Maximum payload length in bytes*/void    ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max );/*!* \brief Sets the network to public or private. Updates the sync byte.** \remark Applies to LoRa modem only** \param [IN] enable if true, it enables a public network*/void    ( *SetPublicNetwork )( bool enable );/*!* \brief Gets the time required for the board plus radio to get out of sleep.[ms]** \retval time Radio plus board wakeup time in ms.*/uint32_t  ( *GetWakeupTime )( void );/*!* \brief Process radio irq*/void ( *IrqProcess )( void );/** The next functions are available only on SX126x radios.*//*!* \brief Sets the radio in reception mode with Max LNA gain for the given time** \remark Available on SX126x radios only.** \param [IN] timeout Reception timeout [ms]*                     [0: continuous, others timeout]*/void    ( *RxBoosted )( uint32_t timeout );/*!* \brief Sets the Rx duty cycle management parameters** \remark Available on SX126x radios only.** \param [in]  rxTime        Structure describing reception timeout value* \param [in]  sleepTime     Structure describing sleep timeout value*/void ( *SetRxDutyCycle ) ( uint32_t rxTime, uint32_t sleepTime );
};

2、sx1276.c实现接口;

3、用户和底层打交道是通过5个事件,用户实现,底层驱动调用;

/*!* \brief Radio driver callback functions*/
typedef struct
{/*!* \brief  Tx Done callback prototype.*/void    ( *TxDone )( void );/*!* \brief  Tx Timeout callback prototype.*/void    ( *TxTimeout )( void );/*!* \brief Rx Done callback prototype.** \param [IN] payload Received buffer pointer* \param [IN] size    Received buffer size* \param [IN] rssi    RSSI value computed while receiving the frame [dBm]* \param [IN] snr     SNR value computed while receiving the frame [dB]*                     FSK : N/A ( set to 0 )*                     LoRa: SNR value in dB*/void    ( *RxDone )(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );/*!* \brief  Rx Timeout callback prototype.*/void    ( *RxTimeout )( void );/*!* \brief Rx Error callback prototype.*/void    ( *RxError )( void );/*!* \brief  FHSS Change Channel callback prototype.** \param [IN] currentChannel   Index number of the current channel*/void ( *FhssChangeChannel )( uint8_t currentChannel );/*!* \brief CAD Done callback prototype.** \param [IN] channelDetected    Channel Activity detected during the CAD*/void ( *CadDone ) ( bool channelActivityDetected );
}RadioEvents_t;

4、DIO中断处理

Lora有DIO0-DIO5,通过它们来指示目前芯片状态(比用SPI查询,快),底层驱动有对应的处理函数:

SX1276OnDio0Irq,

SX1276OnDio1Irq,

SX1276OnDio2Irq,

SX1276OnDio3Irq,

SX1276OnDio4Irq

DIO5没有,

这5个DIO处理函数在驱动里面是放到一个数组中,

/*!* Hardware DIO IRQ callback initialization*/
static DioIrqHandler *DioIrq[] = { SX1276OnDio0Irq, SX1276OnDio1Irq,SX1276OnDio2Irq, SX1276OnDio3Irq,SX1276OnDio4Irq, NULL };

然后需要外部实现:void SX1276IoIrqInit(DioIrqHandler **irqHandlers )

查看例子:

void SX1276IoIrqInit( DioIrqHandler **irqHandlers )
{GpioSetInterrupt( &SX1276.DIO0, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[0] );GpioSetInterrupt( &SX1276.DIO1, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[1] );GpioSetInterrupt( &SX1276.DIO2, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[2] );GpioSetInterrupt( &SX1276.DIO3, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[3] );GpioSetInterrupt( &SX1276.DIO4, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[4] );GpioSetInterrupt( &SX1276.DIO5, LL_EXTI_MODE_IT, LL_EXTI_TRIGGER_RISING, IRQ_HIGH_PRIORITY, irqHandlers[5] );
}

功能就是把中断处理函数放到对应的IO口中断处理函数里面,官方例程实现有点复杂,因为他写的是通用架构(我个人感觉没必要,总之记住一句话:把IO口中断放到对应的IO口中断处理函数里面)。以上是历程思路,也可以用驱动V2.1.0的查询思路,很简单:就是查询IO口状态,如果有效,则调用对应的函数,实现如下:

实现函数IrqProcess(入参void* ptRFStruct是为了支持多芯片,你可以直接在函数里面用实体实现):

#if (0 == LORA_IRQ_IS_ENABLE)
void IrqProcess( void* ptRFStruct )
{SX1276_t* ptSX1276 = (SX1276_t*)ptRFStruct;DioIrqHandler*  ptIrqHandler = NULL;if(NULL == ptSX1276){return;}if(GpioRead(&ptSX1276->DIO0)){ptIrqHandler=ptSX1276->DioIrq[0];if(NULL != ptIrqHandler){ptIrqHandler(ptSX1276,NULL);}}
//    if(GpioRead(&ptSX1276->DIO1)){
//        ptIrqHandler=ptSX1276->DioIrq[1];
//        if(NULL != ptIrqHandler){
//            ptIrqHandler(ptSX1276,NULL);
//        }
//    }
//    if(GpioRead(&ptSX1276->DIO2)){
//        ptIrqHandler=ptSX1276->DioIrq[2];
//        if(NULL != ptIrqHandler){
//            ptIrqHandler(ptSX1276,NULL);
//        }
//    }
//    if(GpioRead(&ptSX1276->DIO3)){
//        ptIrqHandler=ptSX1276->DioIrq[3];
//        if(NULL != ptIrqHandler){
//            ptIrqHandler(ptSX1276,NULL);
//        }
//    }
//    if(GpioRead(&ptSX1276->DIO4)){
//        ptIrqHandler=ptSX1276->DioIrq[4];
//        if(NULL != ptIrqHandler){
//            ptIrqHandler(ptSX1276,NULL);
//        }
//    }
//    if(GpioRead(&ptSX1276->DIO5)){
//        ptIrqHandler=ptSX1276->DioIrq[5];
//        if(NULL != ptIrqHandler){
//            ptIrqHandler(ptSX1276,NULL);
//        }
//    }
}
#endif

由于我测试驱动,只用到了DIO0,因此其他处理函数屏蔽掉。

5、超时处理函数

驱动提供了超时处理函数SX1276OnTimeoutIrq,驱动里面定义的三个超时事件:

/*!* Tx and Rx timers*/
TimerEvent_t TxTimeoutTimer;
TimerEvent_t RxTimeoutTimer;
TimerEvent_t RxTimeoutSyncWord;

驱动初始化:

    // Initialize driver timeout timersTimerInit( &TxTimeoutTimer, SX1276OnTimeoutIrq );TimerInit( &RxTimeoutTimer, SX1276OnTimeoutIrq );TimerInit( &RxTimeoutSyncWord, SX1276OnTimeoutIrq );

主要在收、发、接收同步字超时时候处理,这里如果不用低功耗模式(MCU休眠),则可以直接忽略,同时在应用层自己做对应逻辑,或者在应用层超时时候直接调用这个超时处理函数即可。

三、实现驱动支持多芯片

1、查看sx1276.c的全局变量:

/** Private global variables*//*!* Radio callbacks variable*/
static RadioEvents_t *RadioEvents;/*!* Reception buffer*/
static uint8_t RxTxBuffer[RX_BUFFER_SIZE];/** Public global variables*//*!* Radio hardware and global parameters*/
SX1276_t SX1276;/*!* Hardware DIO IRQ callback initialization*/
DioIrqHandler *DioIrq[] = { SX1276OnDio0Irq, SX1276OnDio1Irq,SX1276OnDio2Irq, SX1276OnDio3Irq,SX1276OnDio4Irq, NULL };/*!* Tx and Rx timers*/
TimerEvent_t TxTimeoutTimer;
TimerEvent_t RxTimeoutTimer;
TimerEvent_t RxTimeoutSyncWord;

分析如下:

1、RadioEvents变量指针为事件处理,需要用户实现,然后传入进来,由底层驱动调用,每个芯片的事件处理肯定不同,因此RadioEvents放到struct SX1276_s结构体中;

2、static uint8_t RxTxBuffer[RX_BUFFER_SIZE];接收发送缓存,放到struct SX1276_s结构体中;

3、SX1276_t SX1276;去掉,由用户层定义,当做驱动层API的入参;

4、DioIrq不变,修改DIO中断处理的,增加SX1276_t*指针入参;

5、三个超时处理事件变量,放到struct SX1276_s结构体中;

6、struct SX1276_s结构体中增加电源控制脚、射频开关控制脚,修改后如下:

/*!* Radio hardware and global parameters*/
typedef struct SX1276_s
{//GPIOGpio_t        Reset;Gpio_t        Power;Gpio_t        RFswitch;Gpio_t        DIO0;Gpio_t        DIO1;Gpio_t        DIO2;Gpio_t        DIO3;Gpio_t        DIO4;Gpio_t        DIO5;Spi_t         Spi;RadioSettings_t Settings;//事件RadioEvents_t *RadioEvents;//缓存uint8_t RxTxBuffer[RX_BUFFER_SIZE];//超时事件TimerEvent_t TxTimeoutTimer;TimerEvent_t RxTimeoutTimer;TimerEvent_t RxTimeoutSyncWord;//IO中断
#if (0 == LORA_IRQ_IS_ENABLE)DioIrqHandler **DioIrq;
#endif
}SX1276_t;

7、Spi_t里面增加SpiId变量,修改如下;

/*!* SPI object type definition*/
typedef struct Spi_s
{SPI_TypeDef* SpiId;Gpio_t Mosi;Gpio_t Miso;Gpio_t Sclk;Gpio_t Nss;
}Spi_t;

8、接口修改

对应的接口增加void*入参,因为radio.h为对外接口文件,sx1276.h包含radio.h,因此struct SX1276_s类型对radio.h是不可见的,

修改后的radio.h抽象接口:

/*!* \brief Radio driver definition*/
struct Radio_s
{/*!* \brief Initializes the radio** \param [IN] events Structure containing the driver callback functions*/void    ( *Init )(void* ptSX1276, RadioEvents_t *events );/*!* Return current radio status** \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING]*/RadioState_t ( *GetStatus )( void* ptSX1276 );/*!* \brief Configures the radio with the given modem** \param [IN] modem Modem to be used [0: FSK, 1: LoRa]*/void    ( *SetModem )(void* ptSX1276, RadioModems_t modem );/*!* \brief Sets the channel frequency** \param [IN] freq         Channel RF frequency*/void    ( *SetChannel )(void* ptSX1276, uint32_t freq );/*!* \brief Checks if the channel is free for the given time** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] freq       Channel RF frequency* \param [IN] rssiThresh RSSI threshold* \param [IN] maxCarrierSenseTime Max time while the RSSI is measured** \retval isFree         [true: Channel is free, false: Channel is not free]*/bool    ( *IsChannelFree )(void* ptSX1276, RadioModems_t modem, uint32_t freq, int16_t rssiThresh, uint32_t maxCarrierSenseTime );/*!* \brief Generates a 32 bits random value based on the RSSI readings** \remark This function sets the radio in LoRa modem mode and disables*         all interrupts.*         After calling this function either Radio.SetRxConfig or*         Radio.SetTxConfig functions must be called.** \retval randomValue    32 bits random value*/uint32_t ( *Random )( void* ptSX1276 );/*!* \brief Sets the reception parameters** \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] bandwidth    Sets the bandwidth*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: [0: 125 kHz, 1: 250 kHz,*                                 2: 500 kHz, 3: Reserved]* \param [IN] datarate     Sets the Datarate*                          FSK : 600..300000 bits/s*                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,*                                10: 1024, 11: 2048, 12: 4096  chips]* \param [IN] coderate     Sets the coding rate (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: N/A ( set to 0 )* \param [IN] preambleLen  Sets the Preamble length*                          FSK : Number of bytes*                          LoRa: Length in symbols (the hardware adds 4 more symbols)* \param [IN] symbTimeout  Sets the RxSingle timeout value*                          FSK : timeout in number of bytes*                          LoRa: timeout in symbols* \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]* \param [IN] payloadLen   Sets payload length when fixed length is used* \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]* \param [IN] freqHopOn    Enables disables the intra-packet frequency hopping*                          FSK : N/A ( set to 0 )*                          LoRa: [0: OFF, 1: ON]* \param [IN] hopPeriod    Number of symbols between each hop*                          FSK : N/A ( set to 0 )*                          LoRa: Number of symbols* \param [IN] iqInverted   Inverts IQ signals (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [0: not inverted, 1: inverted]* \param [IN] rxContinuous Sets the reception in continuous mode*                          [false: single mode, true: continuous mode]*/void    ( *SetRxConfig )(void* ptSX1276, RadioModems_t modem, uint32_t bandwidth,uint32_t datarate, uint8_t coderate,uint32_t bandwidthAfc, uint16_t preambleLen,uint16_t symbTimeout, bool fixLen,uint8_t payloadLen,bool crcOn, bool freqHopOn, uint8_t hopPeriod,bool iqInverted, bool rxContinuous );/*!* \brief Sets the transmission parameters** \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] power        Sets the output power [dBm]* \param [IN] fdev         Sets the frequency deviation (FSK only)*                          FSK : [Hz]*                          LoRa: 0* \param [IN] bandwidth    Sets the bandwidth (LoRa only)*                          FSK : 0*                          LoRa: [0: 125 kHz, 1: 250 kHz,*                                 2: 500 kHz, 3: Reserved]* \param [IN] datarate     Sets the Datarate*                          FSK : 600..300000 bits/s*                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,*                                10: 1024, 11: 2048, 12: 4096  chips]* \param [IN] coderate     Sets the coding rate (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]* \param [IN] preambleLen  Sets the preamble length*                          FSK : Number of bytes*                          LoRa: Length in symbols (the hardware adds 4 more symbols)* \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]* \param [IN] crcOn        Enables disables the CRC [0: OFF, 1: ON]* \param [IN] freqHopOn    Enables disables the intra-packet frequency hopping*                          FSK : N/A ( set to 0 )*                          LoRa: [0: OFF, 1: ON]* \param [IN] hopPeriod    Number of symbols between each hop*                          FSK : N/A ( set to 0 )*                          LoRa: Number of symbols* \param [IN] iqInverted   Inverts IQ signals (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [0: not inverted, 1: inverted]* \param [IN] timeout      Transmission timeout [ms]*/void    ( *SetTxConfig )(void* ptSX1276, RadioModems_t modem, int8_t power, uint32_t fdev,uint32_t bandwidth, uint32_t datarate,uint8_t coderate, uint16_t preambleLen,bool fixLen, bool crcOn, bool freqHopOn,uint8_t hopPeriod, bool iqInverted, uint32_t timeout );/*!* \brief Checks if the given RF frequency is supported by the hardware** \param [IN] frequency RF frequency to be checked* \retval isSupported [true: supported, false: unsupported]*/bool    ( *CheckRfFrequency )(void* ptSX1276, uint32_t frequency );/*!* \brief Computes the packet time on air in ms for the given payload** \Remark Can only be called once SetRxConfig or SetTxConfig have been called** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] pktLen     Packet payload length** \retval airTime        Computed airTime (ms) for the given packet payload length*/uint32_t  ( *TimeOnAir )(void* ptSX1276, RadioModems_t modem, uint8_t pktLen );/*!* \brief Sends the buffer of size. Prepares the packet to be sent and sets*        the radio in transmission** \param [IN]: buffer     Buffer pointer* \param [IN]: size       Buffer size*/void    ( *Send )(void* ptSX1276, uint8_t *buffer, uint8_t size );/*!* \brief Sets the radio in sleep mode*/void    ( *Sleep )( void* ptSX1276 );/*!* \brief Sets the radio in standby mode*/void    ( *Standby )( void* ptSX1276 );/*!* \brief Sets the radio in reception mode for the given time* \param [IN] timeout Reception timeout [ms]*                     [0: continuous, others timeout]*/void    ( *Rx )(void* ptSX1276, uint32_t timeout );/*!* \brief Start a Channel Activity Detection*/void    ( *StartCad )( void* ptSX1276 );/*!* \brief Sets the radio in continuous wave transmission mode** \param [IN]: freq       Channel RF frequency* \param [IN]: power      Sets the output power [dBm]* \param [IN]: time       Transmission mode timeout [s]*/void    ( *SetTxContinuousWave )(void* ptSX1276, uint32_t freq, int8_t power, uint16_t time );/*!* \brief Reads the current RSSI value** \retval rssiValue Current RSSI value in [dBm]*/int16_t ( *Rssi )(void* ptSX1276, RadioModems_t modem );/*!* \brief Writes the radio register at the specified address** \param [IN]: addr Register address* \param [IN]: data New register value*/void    ( *Write )(void* ptSX1276, uint16_t addr, uint8_t data );/*!* \brief Reads the radio register at the specified address** \param [IN]: addr Register address* \retval data Register value*/uint8_t ( *Read )(void* ptSX1276, uint16_t addr );/*!* \brief Writes multiple radio registers starting at address** \param [IN] addr   First Radio register address* \param [IN] buffer Buffer containing the new register's values* \param [IN] size   Number of registers to be written*/void    ( *WriteBuffer )(void* ptSX1276, uint16_t addr, uint8_t *buffer, uint8_t size );/*!* \brief Reads multiple radio registers starting at address** \param [IN] addr First Radio register address* \param [OUT] buffer Buffer where to copy the registers data* \param [IN] size Number of registers to be read*/void    ( *ReadBuffer )(void* ptSX1276, uint16_t addr, uint8_t *buffer, uint8_t size );/*!* \brief Sets the maximum payload length.** \param [IN] modem      Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] max        Maximum payload length in bytes*/void    ( *SetMaxPayloadLength )(void* ptSX1276, RadioModems_t modem, uint8_t max );/*!* \brief Sets the network to public or private. Updates the sync byte.** \remark Applies to LoRa modem only** \param [IN] enable if true, it enables a public network*/void    ( *SetPublicNetwork )(void* ptSX1276, bool enable );/*!* \brief Gets the time required for the board plus radio to get out of sleep.[ms]** \retval time Radio plus board wakeup time in ms.*/uint32_t  ( *GetWakeupTime )(void* ptSX1276 );/*!* \brief Process radio irq*/void ( *IrqProcess )( void* ptSX1276 );/** The next functions are available only on SX126x radios.*//*!* \brief Sets the radio in reception mode with Max LNA gain for the given time** \remark Available on SX126x radios only.** \param [IN] timeout Reception timeout [ms]*                     [0: continuous, others timeout]*/void    ( *RxBoosted )(void* ptSX1276, uint32_t timeout );/*!* \brief Sets the Rx duty cycle management parameters** \remark Available on SX126x radios only.** \param [in]  rxTime        Structure describing reception timeout value* \param [in]  sleepTime     Structure describing sleep timeout value*/void ( *SetRxDutyCycle ) (void* ptSX1276, uint32_t rxTime, uint32_t sleepTime );
};

定义在sx1276-board.c:

/*!* Radio driver structure initialization*/
const struct Radio_s Radio =
{SX1276Init,SX1276GetStatus,SX1276SetModem,SX1276SetChannel,SX1276IsChannelFree,SX1276Random,SX1276SetRxConfig,SX1276SetTxConfig,SX1276CheckRfFrequency,SX1276GetTimeOnAir,SX1276Send,SX1276SetSleep,SX1276SetStby,SX1276SetRx,SX1276StartCad,SX1276SetTxContinuousWave,SX1276ReadRssi,SX1276Write,SX1276Read,SX1276WriteBuffer,SX1276ReadBuffer,SX1276SetMaxPayloadLength,SX1276SetPublicNetwork,SX1276GetWakeupTime,
#if (0 == LORA_IRQ_IS_ENABLE)IrqProcess,
#elseNULL, // void ( *IrqProcess )( void )
#endifNULL, // void ( *RxBoosted )( uint32_t timeout ) - SX126x OnlyNULL, // void ( *SetRxDutyCycle )( uint32_t rxTime, uint32_t sleepTime ) - SX126x Only
};

sx1276.c接口实现修改,以SX1276Init为例,其它函数修改类似:

void SX1276Init(void* ptRFStruct, RadioEvents_t *events )
{uint8_t i;SX1276_t* ptSX1276 = (SX1276_t*)ptRFStruct;if(NULL == ptSX1276){return;}ptSX1276->RadioEvents = events;// Initialize driver timeout timersTimerInit( &ptSX1276->TxTimeoutTimer, SX1276OnTimeoutIrq );TimerInit( &ptSX1276->RxTimeoutTimer, SX1276OnTimeoutIrq );TimerInit( &ptSX1276->RxTimeoutSyncWord, SX1276OnTimeoutIrq );//TRACE_DEBUG("SX1276Init=%d\r\n",1);SX1276Reset( ptSX1276 );//TRACE_DEBUG("SX1276Init=%d\r\n",2);while(0x6C != SX1276Read(ptSX1276,0x06)){TRACE_ERROR("Hard SPI Err!\r\n");my_delay_ms(500);}//TRACE_DEBUG("SX1276Init=%d\r\n",3);RxChainCalibration(ptSX1276 );SX1276SetOpMode(ptSX1276, RF_OPMODE_SLEEP );#if (LORA_IRQ_IS_ENABLE)SX1276IoIrqInit(ptSX1276, DioIrq );
#elseptSX1276->DioIrq = DioIrq;
#endiffor( i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ ){SX1276SetModem(ptSX1276, RadioRegsInit[i].Modem );SX1276Write(ptSX1276, RadioRegsInit[i].Addr, RadioRegsInit[i].Value );}SX1276SetModem(ptSX1276, MODEM_FSK );ptSX1276->Settings.State = RF_IDLE;//TRACE_DEBUG("SX1276Init irq= %x\r\n",SX1276Read(REG_LR_IRQFLAGS));
}

四、应用层修改

1、首先定义不同实体:

static net_work_t   s_tNetWorkRF1;
static net_work_t   s_tNetWorkRF2;
static net_work_t   s_tNetWorkRF3;

2、实现不同的事件处理函数:

static void OnTxDoneRF1( void )
{SET_EVENT(&s_tNetWorkRF1.tRfTxDone);
}static void OnRxDoneRF1(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{if(WAIT_EVENT(&s_tNetWorkRF1.tRfRxDone) || size > NET_WOEK_RF_BUFFER_SIZE || NULL == payload){return;}memcpy(s_tNetWorkRF1.chRadioRxBuffer,payload,size);s_tNetWorkRF1.hwRadioRxSize = size;s_tNetWorkRF1.chPacketRssiValue = rssi;s_tNetWorkRF1.chSnrValue = snr;SET_EVENT(&s_tNetWorkRF1.tRfRxDone);
}static void OnTxTimeoutRF1( void )
{//Radio.Sleep( );
}static void OnRxTimeoutRF1( void )
{//Radio.Sleep( );
}static void OnRxErrorRF1( void )
{//Radio.Sleep( );
}static void OnTxDoneRF2( void )
{SET_EVENT(&s_tNetWorkRF2.tRfTxDone);
}static void OnRxDoneRF2(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{if(WAIT_EVENT(&s_tNetWorkRF2.tRfRxDone) || size > NET_WOEK_RF_BUFFER_SIZE || NULL == payload){return;}memcpy(s_tNetWorkRF2.chRadioRxBuffer,payload,size);s_tNetWorkRF2.hwRadioRxSize = size;s_tNetWorkRF2.chPacketRssiValue = rssi;s_tNetWorkRF2.chSnrValue = snr;SET_EVENT(&s_tNetWorkRF2.tRfRxDone);
}static void OnTxTimeoutRF2( void )
{//Radio.Sleep( );
}static void OnRxTimeoutRF2( void )
{//Radio.Sleep( );
}static void OnRxErrorRF2( void )
{//Radio.Sleep( );
}static void OnTxDoneRF3( void )
{SET_EVENT(&s_tNetWorkRF3.tRfTxDone);
}static void OnRxDoneRF3(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{if(WAIT_EVENT(&s_tNetWorkRF3.tRfRxDone) || size > NET_WOEK_RF_BUFFER_SIZE || NULL == payload){return;}memcpy(s_tNetWorkRF3.chRadioRxBuffer,payload,size);s_tNetWorkRF3.hwRadioRxSize = size;s_tNetWorkRF3.chPacketRssiValue = rssi;s_tNetWorkRF3.chSnrValue = snr;SET_EVENT(&s_tNetWorkRF3.tRfRxDone);
}static void OnTxTimeoutRF3( void )
{//Radio.Sleep( );
}static void OnRxTimeoutRF3( void )
{//Radio.Sleep( );
}static void OnRxErrorRF3( void )
{//Radio.Sleep( );
}
/*!* Radio events function pointer*/
static const RadioEvents_t s_RadioEventsRF1 = {.TxDone             = OnTxDoneRF1,.TxTimeout          = OnTxTimeoutRF1,.RxDone             = OnRxDoneRF1,.RxTimeout          = OnRxTimeoutRF1,.RxError            = OnRxErrorRF1,.FhssChangeChannel  = NULL,.CadDone            = NULL,
};
static const RadioEvents_t s_RadioEventsRF2 = {.TxDone             = OnTxDoneRF2,.TxTimeout          = OnTxTimeoutRF2,.RxDone             = OnRxDoneRF2,.RxTimeout          = OnRxTimeoutRF2,.RxError            = OnRxErrorRF2,.FhssChangeChannel  = NULL,.CadDone            = NULL,
};
static const RadioEvents_t s_RadioEventsRF3 = {.TxDone             = OnTxDoneRF3,.TxTimeout          = OnTxTimeoutRF3,.RxDone             = OnRxDoneRF3,.RxTimeout          = OnRxTimeoutRF3,.RxError            = OnRxErrorRF3,.FhssChangeChannel  = NULL,.CadDone            = NULL,
};

3、初始化如下:

void user_net_work_init(net_work_app_api_t *ptAppApiRF1,net_work_app_api_t *ptAppApiRF2,net_work_app_api_t *ptAppApiRF3)
{srand(s_chRandomNumber[0]%s_chRandomNumber[1]+s_chRandomNumber[2]%s_chRandomNumber[3]);     //随机数种子TRACE_DEBUG("srand=%d\r\n",(s_chRandomNumber[0]%s_chRandomNumber[1]+s_chRandomNumber[2]%s_chRandomNumber[3]));memset((uint8_t*)&s_tNetWorkRF1,0x00,sizeof(net_work_t));memset((uint8_t*)&s_tNetWorkRF2,0x00,sizeof(net_work_t));memset((uint8_t*)&s_tNetWorkRF3,0x00,sizeof(net_work_t));s_tNetWorkRF1.tChannel = RF_DATA_CHANNEL_BASE_STATION;s_tNetWorkRF2.tChannel = RF_DATA_CHANNEL_HANDHELD_DEVICE;s_tNetWorkRF3.tChannel = RF_DATA_CHANNEL_SENSOR_1;SX1276IoInit(&s_tNetWorkRF1.tSX1276,s_tNetWorkRF1.tChannel);SX1276IoInit(&s_tNetWorkRF2.tSX1276,s_tNetWorkRF2.tChannel);SX1276IoInit(&s_tNetWorkRF3.tSX1276,s_tNetWorkRF3.tChannel);SpiInit(&s_tNetWorkRF1.tSX1276.Spi,RF1_SPI);SpiInit(&s_tNetWorkRF2.tSX1276.Spi,RF2_SPI);SpiInit(&s_tNetWorkRF3.tSX1276.Spi,RF3_SPI);net_work_init(&s_tNetWorkRF1,s_chRfBufferRF1,sizeof(s_chRfBufferRF1),(RadioEvents_t*)&s_RadioEventsRF1,ptAppApiRF1);TRACE_DEBUG("RF1 init success\r\n");net_work_init(&s_tNetWorkRF2,s_chRfBufferRF2,sizeof(s_chRfBufferRF2),(RadioEvents_t*)&s_RadioEventsRF2,ptAppApiRF2);TRACE_DEBUG("RF2 init success\r\n");net_work_init(&s_tNetWorkRF3,s_chRfBufferRF3,sizeof(s_chRfBufferRF3),(RadioEvents_t*)&s_RadioEventsRF3,ptAppApiRF3);TRACE_DEBUG("RF3 init success\r\n");}

4、应用接口思路同驱动一样

示例:

/*************************************  APP  **********************************/
bool net_work_service_process(void)
{net_work_rf_process(&s_tNetWorkRF1);                       //无线线程net_work_protocol_analysis_process(&s_tNetWorkRF1);        //协议解析father_station_routing_table_maintenance(&s_tNetWorkRF1);  //父节路由点维护net_work_logic_process(&s_tNetWorkRF1);                    //组网逻辑net_work_check_sx1278_process(&s_tNetWorkRF1);             //SX1278维护线程s_tNetWorkRF1.ptRadio->IrqProcess(&s_tNetWorkRF1.tSX1276); //DIO0处理函数net_work_rf_process(&s_tNetWorkRF2);                       //无线线程net_work_protocol_analysis_process(&s_tNetWorkRF2);        //协议解析father_station_routing_table_maintenance(&s_tNetWorkRF2);  //父节路由点维护net_work_logic_process(&s_tNetWorkRF2);                    //组网逻辑net_work_check_sx1278_process(&s_tNetWorkRF2);             //SX1278维护线程s_tNetWorkRF2.ptRadio->IrqProcess(&s_tNetWorkRF2.tSX1276); //DIO0处理函数net_work_rf_process(&s_tNetWorkRF3);                       //无线线程net_work_protocol_analysis_process(&s_tNetWorkRF3);        //协议解析father_station_routing_table_maintenance(&s_tNetWorkRF3);  //父节路由点维护net_work_logic_process(&s_tNetWorkRF3);                    //组网逻辑net_work_check_sx1278_process(&s_tNetWorkRF3);             //SX1278维护线程s_tNetWorkRF3.ptRadio->IrqProcess(&s_tNetWorkRF3.tSX1276); //DIO0处理函数return true;
}

读取RSSI应用层API:

/********************************  SX1278维护线程  ****************************/
static bool  net_work_check_rf_chip_state(net_work_t *ptNetWork)
{int16_t             iTemp   = 0;static  uint8_t     chNum   = 0;if(RF_IDLE == ptNetWork->ptRadio->GetStatus(&ptNetWork->tSX1276)){chNum = 0;return true;}iTemp = ptNetWork->ptRadio->Rssi(&ptNetWork->tSX1276,MODEM_LORA);TRACE_DEBUG("RF rx rssi = %d\r\n",iTemp);if(iTemp <= (-160)){chNum++;TRACE_ERROR("RF rx rssi error = %d\r\n",iTemp);if(chNum >= 5){chNum = 0;return false;}}else{chNum=0;}return true;
}

读取RSSI驱动层API:

int16_t SX1276ReadRssi(void* ptRFStruct, RadioModems_t modem )
{int16_t rssi = 0;SX1276_t* ptSX1276 = (SX1276_t*)ptRFStruct;if(NULL == ptSX1276){return 0;}switch( modem ){case MODEM_FSK:rssi = -( SX1276Read(ptSX1276, REG_RSSIVALUE ) >> 1 );break;case MODEM_LORA:if( ptSX1276->Settings.Channel > RF_MID_BAND_THRESH ){rssi = RSSI_OFFSET_HF + SX1276Read(ptSX1276, REG_LR_RSSIVALUE );}else{rssi = RSSI_OFFSET_LF + SX1276Read(ptSX1276, REG_LR_RSSIVALUE );}break;default:rssi = -1;break;}return rssi;
}

运行效果如下:

2022.06.08

今天测试sx12xxDrivers-V4.4.2驱动,发现Lora最大接收64字节,而以前sx12xxDrivers-V2.1.0驱动则没有这个限制,什么问题呢?

查看旧驱动在void SX1276LoRaInit( void )有如下设置:

    SX1276LoRaSetPayloadLength( LoRaSettings.PayloadLength );tLoRaSettings LoRaSettings =
{LoRa_FREQENCY ,   // RFFrequency20,               // Power8,                // 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]11,                // SpreadingFactor [6: 64, 7: 128, 8: 256, 9: 512, 10: 1024, 11: 2048, 12: 4096  chips]1,                // 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]0,                // RxSingleOn [0: Continuous, 1 Single]0,                // FreqHopOn [0: OFF, 1: ON]              //跳频技术4,                // HopPeriod Hops every frequency hopping period symbols100,              // TxPacketTimeout100,              // RxPacketTimeout128,              // PayloadLength (used for implicit header mode)
};

查看sx12xxDrivers-V4.4.2,有如下设置:

/*!* \brief Sets the reception parameters** \remark When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported** \param [IN] modem        Radio modem to be used [0: FSK, 1: LoRa]* \param [IN] bandwidth    Sets the bandwidth*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: [0: 125 kHz, 1: 250 kHz,*                                 2: 500 kHz, 3: Reserved]* \param [IN] datarate     Sets the Datarate*                          FSK : 600..300000 bits/s*                          LoRa: [6: 64, 7: 128, 8: 256, 9: 512,*                                10: 1024, 11: 2048, 12: 4096  chips]* \param [IN] coderate     Sets the coding rate (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]* \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only)*                          FSK : >= 2600 and <= 250000 Hz*                          LoRa: N/A ( set to 0 )* \param [IN] preambleLen  Sets the Preamble length*                          FSK : Number of bytes*                          LoRa: Length in symbols (the hardware adds 4 more symbols)* \param [IN] symbTimeout  Sets the RxSingle timeout value*                          FSK : timeout number of bytes*                          LoRa: timeout in symbols* \param [IN] fixLen       Fixed length packets [0: variable, 1: fixed]* \param [IN] payloadLen   Sets payload length when fixed length is used* \param [IN] crcOn        Enables/Disables the CRC [0: OFF, 1: ON]* \param [IN] freqHopOn    Enables disables the intra-packet frequency hopping*                          FSK : N/A ( set to 0 )*                          LoRa: [0: OFF, 1: ON]* \param [IN] hopPeriod    Number of symbols between each hop*                          FSK : N/A ( set to 0 )*                          LoRa: Number of symbols* \param [IN] iqInverted   Inverts IQ signals (LoRa only)*                          FSK : N/A ( set to 0 )*                          LoRa: [0: not inverted, 1: inverted]* \param [IN] rxContinuous Sets the reception in continuous mode*                          [false: single mode, true: continuous mode]*/
void SX1276SetRxConfig(void* ptRFStruct, RadioModems_t modem, uint32_t bandwidth,uint32_t datarate, uint8_t coderate,uint32_t bandwidthAfc, uint16_t preambleLen,uint16_t symbTimeout, bool fixLen,uint8_t payloadLen,bool crcOn, bool freqHopOn, uint8_t hopPeriod,bool iqInverted, bool rxContinuous );

但是查看说明:payloadLen   Sets payload length when fixed length is used,意思是只有使用固定长度模式,才设置磁参数,显然不对。

于是查看void SX1276Init(void* ptRFStruct, RadioEvents_t *events )函数,看到:

    for( i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ ){SX1276SetModem(ptSX1276, RadioRegsInit[i].Modem );SX1276Write(ptSX1276, RadioRegsInit[i].Addr, RadioRegsInit[i].Value );}

再看:

/*!* Radio hardware registers initialization** \remark RADIO_INIT_REGISTERS_VALUE is defined in sx1276-board.h file*/
const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE;

再看:

/*!* \brief Radio hardware registers initialization definition** \remark Can be automatically generated by the SX1276 GUI (not yet implemented)*/
#define RADIO_INIT_REGISTERS_VALUE                \
{                                                 \{ MODEM_FSK , REG_LNA                , 0x23 },\{ MODEM_FSK , REG_RXCONFIG           , 0x1E },\{ MODEM_FSK , REG_RSSICONFIG         , 0xD2 },\{ MODEM_FSK , REG_AFCFEI             , 0x01 },\{ MODEM_FSK , REG_PREAMBLEDETECT     , 0xAA },\{ MODEM_FSK , REG_OSC                , 0x07 },\{ MODEM_FSK , REG_SYNCCONFIG         , 0x12 },\{ MODEM_FSK , REG_SYNCVALUE1         , 0xC1 },\{ MODEM_FSK , REG_SYNCVALUE2         , 0x94 },\{ MODEM_FSK , REG_SYNCVALUE3         , 0xC1 },\{ MODEM_FSK , REG_PACKETCONFIG1      , 0xD8 },\{ MODEM_FSK , REG_FIFOTHRESH         , 0x8F },\{ MODEM_FSK , REG_IMAGECAL           , 0x02 },\{ MODEM_FSK , REG_DIOMAPPING1        , 0x00 },\{ MODEM_FSK , REG_DIOMAPPING2        , 0x30 },\{ MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\
} 

看到么有:MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40

修改为255,测试OK。看手册这个值默认是0xFF,因此sx12xxDrivers-V2.1.0不设置,是没有问题的。而sx12xxDrivers-V4.4.2默认设置为64。

Lora1278驱动V4.4.2讲解二:驱动多个SX1278芯片相关推荐

  1. Lora1278驱动V4.4.2讲解一:驱动移植

    注意,Lora1278驱动sx12xxDrivers-V2.1.0,原厂已经不更新和维护了,反馈的任何软件问题, 原厂就是一句话升级新的驱动,新驱动下载地址:https://github.com/Lo ...

  2. S3C2440上LCD驱动(FrameBuffer)实例开发讲解

    一.开发环境 主  机:VMWare--Fedora 9  开发板:Mini2440--64MB Nand, Kernel:2.6.30.4  编译器:arm-linux-gcc-4.3.2 二.背景 ...

  3. Linux设备驱动开发详解【二】_设备驱动相关硬件基础知识

    本文简介 本文讲解底层驱动工程师必备的硬件基础,给出了嵌入式系统硬件原理及分析方法的全景视图.         2.1 节讲解微控制器.微处理器.数字信号处理器以及应用于特定领域的处理器各自的特点. ...

  4. S3C2440上LCD驱动 (FrameBuffer)实例开发讲解

    1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其中的代码也可直接参考:drivers/video/s3c2410fb.c 以下为转载文章,文章原地址:http://blog. ...

  5. Windows驱动开发学习笔记(二)—— 驱动调试内核编程基础

    Windows驱动开发学习笔记(二)-- 驱动调试&内核编程基础 基础知识 驱动调试 PDB(Program Debug Database) WinDbg 加载 PDB 实验:调试 .sys ...

  6. 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框

    linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  7. [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店...

    原文:[.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店 一.前言 在前面专题一中,我已经介绍了我写这系列文章的初衷了.由于dax.net中的DDD框架和Bytear ...

  8. windows10驱动 x64--- 3环代码加载驱动(二)

    windows10驱动 x64--- 3环代码加载驱动 一:了解驱动加载工具 二:应用层--3环代码示例 一:了解驱动加载工具 平时调试.sys 我们都是用的驱动加载工具:open(打开驱动文件) - ...

  9. FS_S5PC100平台上Linux Camera驱动开发详解(二)

    http://blog.csdn.net/wh_19910525/article/details/18091915 这个问题弄清楚了以后下面就来看获得Camera信息以后如何做后续的处理: 在fimc ...

最新文章

  1. 侧链,驱动链,和根链的双向锚定设计
  2. python爬百度翻译-Python爬取百度翻译(利用json提取数据)
  3. Linux下修改mysql root密码
  4. xcat 安装(liunx高性能刀片集群管理软件)
  5. Python对数列进行全排列
  6. live555源代码简介
  7. spark job运行参数优化
  8. Python编程 | 新手必会的 9 个 Python 技巧
  9. C++ 数据抽象 封装 接口
  10. java setter与getter方法
  11. 为什么可积不一定可导_本命年为什么要穿红?你一定不知道!
  12. vbs程序批量禁用域用户然后移动到指定OU
  13. 视频内容付费系统整站源码
  14. 基于jsp+mysql+java+ssm实验室设备管理系统——计算机毕业设计
  15. 13. 如何打破白天开会、晚上加班的节奏
  16. 元素出栈入栈顺序是否合法
  17. java去掉字符串的空格_如何去掉字符串中的空格?
  18. lammps教程:实例讲解npt、nvt系综的选择
  19. 银河麒麟系统部署.net core环境
  20. 示波器读取SCI串口数据

热门文章

  1. 计算机视觉注意力机制-Attention
  2. 必修三计算机选修三知识点总结,高一数学必修三知识点总结(超实用)
  3. 【DIY】手把手教你爆改一台手机制作掌上游戏机
  4. python声纹识别_【kaldi学习.4】Aishell V1(说话人识别、声纹识别)中的run.sh详解...
  5. Web前端之JavaScript基础
  6. 记一次feign调用报错:feign.codec.DecodeException: Error while extracting response for type [java...
  7. 怎么获得华为手机的产品sn号码imei号
  8. hazelcast java_Hazelcast入门教程
  9. IT项目经理应该做什么
  10. 南方cass简码识别大全_cass-简码识别详细分解.doc