版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
单片机型号:STM32L053R8T6
本文详述将SX1268官方驱动程序,移植到C++程序设计框架的方法。
1、文件结构
在系统中加入以下文件。
2、屏蔽和硬件相关的数据类型
sx126x.h文件,屏蔽以下语句。暂时屏蔽,后续需要解决。
typedef struct SX126x_s
{
// Gpio_t Reset;
// Gpio_t BUSY;
// Gpio_t DIO1;
// Gpio_t DIO2;
// Gpio_t DIO3;
// Spi_t Spi;
PacketParams_t PacketParams;
PacketStatus_t PacketStatus;
ModulationParams_t ModulationParams;
}SX126x_t;
3、解决TxTimeoutTimer定时器
系统中搜索TxTimeoutTimer定时器,在以下程序中出现。
其在初始化时,指定TxTimeoutTimer定时器的回调函数。
void RadioInit( RadioEvents_t *events )
{
RadioEvents = events;
SX126xInit( RadioOnDioIrq );
SX126xSetStandby( STDBY_RC );
SX126xSetRegulatorMode( USE_DCDC );
SX126xSetBufferBaseAddress( 0x00, 0x00 );
SX126xSetTxParams( 0, RADIO_RAMP_200_US );
SX126xSetDioIrqParams( IRQ_RADIO_ALL, IRQ_RADIO_ALL, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
// Initialize driver timeout timers
TimerInit( &TxTimeoutTimer, RadioOnTxTimeoutIrq );
TimerInit( &RxTimeoutTimer, RadioOnRxTimeoutIrq );
IrqFired = false;
}
在数据发送函数中,指定定时器延时时间,并启动定时器。
void RadioSend( uint8_t *buffer, uint8_t size )
{
SX126xSetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RADIO_NONE,
IRQ_RADIO_NONE );
if( SX126xGetPacketType( ) == PACKET_TYPE_LORA )
{
SX126x.PacketParams.Params.LoRa.PayloadLength = size;
}
else
{
SX126x.PacketParams.Params.Gfsk.PayloadLength = size;
}
SX126xSetPacketParams( &SX126x.PacketParams );
SX126xSendPayload( buffer, size, 0 );
TimerSetValue( &TxTimeoutTimer, TxTimeout );
TimerStart( &TxTimeoutTimer );
}
在中断处理的IRQ_TX_DONE和IRQ_RX_TX_TIMEOUT事件中,停止定时器。IRQ_TX_DONE是指数据发送完毕,IRQ_RX_TX_TIMEOUT是指发送或接收延时时间到。
可见其正常处理流程是,我发送数据时,让TxTimeoutTimer启动,数据发送完毕或者芯片提示发送超时,都将定时器停止。只有芯片给出不正常反应时,才调用TxTimeoutTimer回调函数,以完成错误处理。
void RadioIrqProcess( void )
{
if( IrqFired == true )
{
BoardDisableIrq( );
IrqFired = false;
BoardEnableIrq( );
uint16_t irqRegs = SX126xGetIrqStatus( );
SX126xClearIrqStatus( IRQ_RADIO_ALL );
if( ( irqRegs & IRQ_TX_DONE ) == IRQ_TX_DONE )
{
TimerStop( &TxTimeoutTimer );
if( ( RadioEvents != NULL ) && ( RadioEvents->TxDone != NULL ) )
{
RadioEvents->TxDone( );
}
}
if( ( irqRegs & IRQ_RX_DONE ) == IRQ_RX_DONE )
{
uint8_t size;
TimerStop( &RxTimeoutTimer );
SX126xGetPayload( RadioRxPayload, &size , 255 );
SX126xGetPacketStatus( &RadioPktStatus );
if( ( RadioEvents != NULL ) && ( RadioEvents->RxDone != NULL ) )
{
RadioEvents->RxDone( RadioRxPayload, size, RadioPktStatus.Params.LoRa.RssiPkt, RadioPktStatus.Params.LoRa.SnrPkt );
}
}
if( ( irqRegs & IRQ_CRC_ERROR ) == IRQ_CRC_ERROR )
{
if( ( RadioEvents != NULL ) && ( RadioEvents->RxError ) )
{
RadioEvents->RxError( );
}
}
if( ( irqRegs & IRQ_CAD_DONE ) == IRQ_CAD_DONE )
{
if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) )
{
RadioEvents->CadDone( ( ( irqRegs & IRQ_CAD_ACTIVITY_DETECTED ) == IRQ_CAD_ACTIVITY_DETECTED ) );
}
}
if( ( irqRegs & IRQ_RX_TX_TIMEOUT ) == IRQ_RX_TX_TIMEOUT )
{
if( SX126xGetOperatingMode( ) == MODE_TX )
{
TimerStop( &TxTimeoutTimer );
if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) )
{
RadioEvents->TxTimeout( );
}
}
else if( SX126xGetOperatingMode( ) == MODE_RX )
{
TimerStop( &RxTimeoutTimer );
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
}
}
}
if( ( irqRegs & IRQ_PREAMBLE_DETECTED ) == IRQ_PREAMBLE_DETECTED )
{
//__NOP( );
}
if( ( irqRegs & IRQ_SYNCWORD_VALID ) == IRQ_SYNCWORD_VALID )
{
//__NOP( );
}
if( ( irqRegs & IRQ_HEADER_VALID ) == IRQ_HEADER_VALID )
{
//__NOP( );
}
if( ( irqRegs & IRQ_HEADER_ERROR ) == IRQ_HEADER_ERROR )
{
TimerStop( &RxTimeoutTimer );
if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) )
{
RadioEvents->RxTimeout( );
}
}
}
}
4、解决RxTimeoutTimer定时器
其在RadioRx函数中,设置定时器延时并启动了定时器。
void RadioRx( uint32_t timeout )
{
SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RADIO_NONE,
IRQ_RADIO_NONE );
if( timeout != 0 )
{
TimerSetValue( &RxTimeoutTimer, timeout );
TimerStart( &RxTimeoutTimer );
}
if( RxContinuous == true )
{
SX126xSetRx( 0xFFFFFF ); // Rx Continuous
}
else
{
SX126xSetRx( RxTimeout << 6 );
}
}
其在RadioRxBoosted函数中,设置定时器延时并启动了定时器。
void RadioRxBoosted( uint32_t timeout )
{
SX126xSetDioIrqParams( IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RADIO_ALL, //IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RADIO_NONE,
IRQ_RADIO_NONE );
if( timeout != 0 )
{
TimerSetValue( &RxTimeoutTimer, timeout );
TimerStart( &RxTimeoutTimer );
}
if( RxContinuous == true )
{
SX126xSetRxBoosted( 0xFFFFFF ); // Rx Continuous
}
else
{
SX126xSetRxBoosted( RxTimeout << 6 );
}
}
其在RadioSetTxContinuousWave函数中,设置定时器延时并启动了定时器。
void RadioSetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time )
{
SX126xSetRfFrequency( freq );
SX126xSetRfTxPower( power );
SX126xSetTxContinuousWave( );
TimerSetValue( &RxTimeoutTimer, time * 1e3 );
TimerStart( &RxTimeoutTimer );
}
RadioRx作用:设置在给定的时间内接收无线信号
RadioRxBoosted作用:设置在给定的时间内,低噪放最大增益接收无线信号
RadioSetTxContinuousWave作用:连续发送模式(此函数无实际用途,仅做测试使用)
所以,只需关心RadioRx和RadioRxBoosted函数即可。
其在3个事件中停止:IRQ_RX_DONE、IRQ_RX_TX_TIMEOUT和IRQ_HEADER_ERROR,分别为RX完成、RX或TX时间到,错误。