#include "sx1281_driver.h" #include #include "stdio.h" #include "radio.h" #include "usart.h" #include "bsp/uart.h" #include "sx1281_header.h" #include "sx1281.h" #include "device/device.h" /* --------------SX1281 Work mode------------- */ #define SX1281_INTERRUP_MODE /* 中断模式 */ // #define SX1281_POLLING_MODE /* 轮询模式 */ /* ------------SX1281 Work mode end----------- */ /* ----------------SX1281 debug--------------- */ #define SX1281_VIEW #ifdef SX1281_VIEW int fputc(int ch,FILE *f) { //采用轮询方式发送1字节数据,超时时间设置为无限等待 HAL_UART_Transmit(BSP_UART_GetHandle(BSP_UART_SX1281),(uint8_t *)&ch,1,HAL_MAX_DELAY); return ch; } #endif /* --------------SX1281 debug end------------- */ #if defined(SX1281_INTERRUP_MODE) && defined(SX1281_POLLING_MODE) #error "Both SX1281_INTERRUP_MODE and SX1281_POLLING_MODE are defined. Only one can be defined." #elif !defined(SX1281_INTERRUP_MODE) && !defined(SX1281_POLLING_MODE) #error "Neither SX1281_INTERRUP_MODE nor SX1281_POLLING_MODE is defined. One of them must be defined." #endif /*! * \brief Used to display firmware version UART flow */ #define FIRMWARE_VERSION ( ( char* )"Firmware Version: 170919A" ) #define RF_BL_ADV_CHANNEL_38 2426000000 // Hz /*! * \brief Defines the nominal frequency */ #define RF_FREQUENCY RF_BL_ADV_CHANNEL_38 // Hz /*! * \brief Defines the buffer size, i.e. the payload size */ #define BUFFER_SIZE 5 /*! * \brief Number of tick size steps for tx timeout */ #define TX_TIMEOUT_VALUE 10000 // ms /*! * \brief Number of tick size steps for rx timeout */ #define RX_TIMEOUT_VALUE 1000 // ms /*! * \brief Size of ticks (used for Tx and Rx timeout) */ #define RX_TIMEOUT_TICK_SIZE RADIO_TICK_SIZE_1000_US /**-------------------------radio params----------------------------------**/ const SX1281_LORAConfig_t loraConfigList[RF_BAUDRATE_LORA_NUM] = { {//216.264204545455bps,SF=12,BW=203kHz,CR=7 .SpreadingFactor = LORA_SF12, .SignalBw = LORA_BW_0200, .ErrorCoding = LORA_CR_LI_4_7, }, {//991.2109375bps,SF=10,BW=203kHz,CR=4 .SpreadingFactor = LORA_SF10, .SignalBw = LORA_BW_0200, .ErrorCoding = LORA_CR_4_8, }, {//4987.44419642857bps,SF=11,BW=1625kHz,CR=3 .SpreadingFactor = LORA_SF11, .SignalBw = LORA_BW_1600, .ErrorCoding = LORA_CR_4_7, }, {//10150bps,SF=8,BW=812kHz,CR=6 .SpreadingFactor = LORA_SF8, .SignalBw = LORA_BW_0800, .ErrorCoding = LORA_CR_LI_4_6, }, {//20300bps,SF=8,BW=812kHz,CR=1 .SpreadingFactor = LORA_SF8, .SignalBw = LORA_BW_0800, .ErrorCoding = LORA_CR_4_5, }, {//60900bps,SF=6,BW=812kHz,CR=1 .SpreadingFactor = LORA_SF6, .SignalBw = LORA_BW_0800, .ErrorCoding = LORA_CR_4_5, }, {//126953.125bps,SF=5,BW=1625kHz,CR=4 .SpreadingFactor = LORA_SF5, .SignalBw = LORA_BW_1600, .ErrorCoding = LORA_CR_4_8, }, {//203125bps,SF=5,BW=1625kHz,CR=1 .SpreadingFactor = LORA_SF5, .SignalBw = LORA_BW_1600, .ErrorCoding = LORA_CR_4_5, }, }; const SX1281_FLRCConfig_t flrcConfigList[RF_BAUDRATE_FLRC_NUM-RF_BAUDRATE_LORA_NUM-1] = { {//0.13Mbps .BitrateBandwidth =FLRC_BR_0_260_BW_0_3, .CodingRate =FLRC_CR_1_2, .ModulationShaping =RADIO_MOD_SHAPING_BT_1_0, }, {//0.26Mbps .BitrateBandwidth =FLRC_BR_0_520_BW_0_6, .CodingRate =FLRC_CR_1_2, .ModulationShaping =RADIO_MOD_SHAPING_BT_1_0, }, {//0.52Mbps .BitrateBandwidth =FLRC_BR_1_040_BW_1_2, .CodingRate =FLRC_CR_1_2, .ModulationShaping =RADIO_MOD_SHAPING_BT_1_0, }, {//1.04Mbps .BitrateBandwidth =FLRC_BR_1_040_BW_1_2, .CodingRate =FLRC_CR_1_0, .ModulationShaping =RADIO_MOD_SHAPING_BT_1_0, }, }; /*! * \brief Defines the states of the application */ typedef enum { APP_LOWPOWER, APP_RX, APP_RX_TIMEOUT, APP_RX_ERROR, APP_TX, APP_TX_TIMEOUT, }AppStates_t; /*! * \brief Function to be executed on Radio Tx Done event */ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ void OnRxDone( void ); /*! * \brief Function executed on Radio Tx Timeout event */ void OnTxTimeout( void ); /*! * \brief Function executed on Radio Rx Timeout event */ void OnRxTimeout( void ); /*! * \brief Function executed on Radio Rx Error event */ void OnRxError( IrqErrorCode_t ); /*! * \brief All the callbacks are stored in a structure */ RadioCallbacks_t Callbacks = { &OnTxDone, // txDone &OnRxDone, // rxDone NULL, // syncWordDone NULL, // headerDone &OnTxTimeout, // txTimeout &OnRxTimeout, // rxTimeout &OnRxError, // rxError NULL, // cadDone }; /*! * \brief The size of the buffer */ uint8_t BufferSize = BUFFER_SIZE; /*! * \brief The buffer */ uint8_t Buffer[BUFFER_SIZE]={0}; /*! * \brief Mask of IRQs to listen to in rx mode */ uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT; /*! * \brief Mask of IRQs to listen to in tx mode */ uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; /*! * \brief The State of the application */ SX1281_States_t sx1281_state = LOWPOWER; /*! * \brief In case of BLE, the payload must contain the header */ typedef union { struct BleAdvHeaderField_s { uint8_t pduType: 4; uint8_t rfu1:2; uint8_t txAddr:1; uint8_t rxAddr:1; uint8_t length:6; uint8_t rfu2:2; } Fields; uint8_t Serial[ 2 ]; }BleAdvHeaders_t; BleAdvHeaders_t ble_header_adv; PacketParams_t packetParams; ModulationParams_t modulationParams; int8_t SX1281_SetMode(SX1281_t *radio, SX1281_Mode_t mode) { if (radio==NULL) { return DEVICE_ERR; } radio->mode = mode; return DEVICE_OK; } int8_t SX1281_Init(SX1281_t *radio, SX1281_Mode_t mode) { if (radio==NULL) { return DEVICE_ERR; } radio->mode = mode; SX1281_BSPInit() ; HAL_Delay( 500 );/* let DC/DC power ramp up */ Radio.Init( &Callbacks ); // memset( &radio->rxBuffer, 0x00, BufferSize ); #ifdef SX1281_VIEW /* 打印版本号,检查SPI是否跑通 */ printf( "\n\n\r SX1281 Ping Pong Demo Application. %s\n\n\r", FIRMWARE_VERSION ); printf( "\n\n\r Radio firmware version 0x%x\n\n\r", Radio.GetFirmwareVersion( ) ); #endif //SX1281_VIEW /* 根据模式选择属性 */ switch (mode) { case MODE_BLE: #ifdef SX1281_VIEW printf( "\nrunning in BLE mode\n\r" ); #endif //SX1281_VIEW radio->modulationParams.PacketType = PACKET_TYPE_BLE; radio->modulationParams.Params.Ble.BitrateBandwidth = GFS_BLE_BR_1_000_BW_1_2; radio->modulationParams.Params.Ble.ModulationIndex = GFS_BLE_MOD_IND_0_50; radio->modulationParams.Params.Ble.ModulationShaping = RADIO_MOD_SHAPING_BT_0_5; radio->packetParams.PacketType = PACKET_TYPE_BLE; radio->packetParams.Params.Ble.BlePacketType = BLE_EYELONG_1_0; radio->packetParams.Params.Ble.ConnectionState = BLE_ADVERTISER; radio->packetParams.Params.Ble.CrcField = BLE_CRC_3B; radio->packetParams.Params.Ble.Whitening = RADIO_WHITENING_ON; radio->baudrate=RF_BAUDRATE_NONE; break; case MODE_LORA: #ifdef SX1281_VIEW printf( "\nrunning in LORA mode\n\r" ); #endif //SX1281_VIEW radio->modulationParams.PacketType = PACKET_TYPE_LORA; radio->modulationParams.Params.LoRa.SpreadingFactor = LORA_SF11; radio->modulationParams.Params.LoRa.Bandwidth = LORA_BW_1600; radio->modulationParams.Params.LoRa.CodingRate = LORA_CR_LI_4_7; radio->packetParams.PacketType = PACKET_TYPE_LORA; radio->packetParams.Params.LoRa.PreambleLength = 12; radio->packetParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH; radio->packetParams.Params.LoRa.PayloadLength = BUFFER_SIZE; radio->packetParams.Params.LoRa.CrcMode = LORA_CRC_ON; radio->packetParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL; radio->baudrate=RF_BAUDRATE_LORA_005K; break; case MODE_GFSK: #ifdef SX1281_VIEW printf( "\nrunning in GFSK mode\n\r" ); #endif //SX1281_VIEW radio->modulationParams.PacketType = PACKET_TYPE_GFSK; radio->modulationParams.Params.Gfsk.BitrateBandwidth = GFS_BLE_BR_0_125_BW_0_3; radio->modulationParams.Params.Gfsk.ModulationIndex = GFS_BLE_MOD_IND_1_00; radio->modulationParams.Params.Gfsk.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0; radio->packetParams.PacketType = PACKET_TYPE_GFSK; radio->packetParams.Params.Gfsk.PreambleLength = PREAMBLE_LENGTH_32_BITS; radio->packetParams.Params.Gfsk.SyncWordLength = GFS_SYNCWORD_LENGTH_5_BYTE; radio->packetParams.Params.Gfsk.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1; radio->packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_VARIABLE_LENGTH; radio->packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE; radio->packetParams.Params.Gfsk.CrcLength = RADIO_CRC_3_BYTES; radio->packetParams.Params.Gfsk.Whitening = RADIO_WHITENING_ON; radio->baudrate=RF_BAUDRATE_NONE; break; case MODE_FLRC: #ifdef SX1281_VIEW printf( "\nrunning in FLRC mode\n\r" ); #endif //SX1281_VIEW radio->modulationParams.PacketType = PACKET_TYPE_FLRC; radio->modulationParams.Params.Flrc.BitrateBandwidth = FLRC_BR_0_260_BW_0_3; radio->modulationParams.Params.Flrc.CodingRate = FLRC_CR_1_2; radio->modulationParams.Params.Flrc.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0; radio->packetParams.PacketType = PACKET_TYPE_FLRC; radio->packetParams.Params.Flrc.PreambleLength = PREAMBLE_LENGTH_32_BITS; radio->packetParams.Params.Flrc.SyncWordLength = FLRC_SYNCWORD_LENGTH_4_BYTE; radio->packetParams.Params.Flrc.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1; radio->packetParams.Params.Flrc.HeaderType = RADIO_PACKET_VARIABLE_LENGTH; radio->packetParams.Params.Flrc.PayloadLength = BUFFER_SIZE; radio->packetParams.Params.Flrc.CrcLength = RADIO_CRC_3_BYTES; radio->packetParams.Params.Flrc.Whitening = RADIO_WHITENING_OFF; radio->baudrate=RF_BAUDRATE_FLRC_130K; break; default: return DEVICE_ERR; } /* 默认功率13dBm */ radio->txOutputPower=13; /* 设置属性 */ Radio.SetStandby( STDBY_RC ); Radio.SetPacketType( modulationParams.PacketType ); Radio.SetModulationParams( &modulationParams ); Radio.SetPacketParams( &packetParams ); Radio.SetRfFrequency( RF_FREQUENCY );//设置射频工作中心频率 Radio.SetBufferBaseAddresses( 0x00, 0x00 ); Radio.SetTxParams( radio->txOutputPower, RADIO_RAMP_02_US ); #ifdef SX1281_INTERRUP_MODE /* 中断模式 */ Radio.SetInterruptMode(); #endif #ifdef SX1281_POLLING_MODE /* 轮询模式 */ Radio.SetPollingMode(); #endif /* 还没搞懂这里是干啥的 */ if (radio->mode==MODE_BLE) { // only used in GENERIC and BLE mode Radio.SetSyncWord( 1, ( uint8_t[] ){ 0xDD, 0xA0, 0x96, 0x69, 0xDD } ); Radio.WriteRegister(0x9c7, 0x55 ); Radio.WriteRegister(0x9c8, 0x55 ); Radio.WriteRegister(0x9c9, 0x55 ); //Radio.WriteRegister( 0x9c5, 0x33 ); Radio.SetBleAdvertizerAccessAddress( ); Radio.SetWhiteningSeed( 0x33 ); ble_header_adv.Fields.length = 2; ble_header_adv.Fields.pduType = 2; } return DEVICE_OK; } /////蓝牙还没研究明白 void SetBLEAdvertisingPacket(SX1281_t *radio, uint8_t *data, uint8_t length) { if (radio->mode != MODE_BLE) { printf("Error: Not in BLE mode\n"); return; } // 检查数据长度是否符合BLE规范 if (length > 37) { // BLE广告PDU最大有效载荷为37字节 printf("Error: BLE advertising data too long: %d bytes (max 37)\n", length); return; } // 根据BLE规范构建PDU报头 uint8_t pduHeader[2] = {0}; // 第一字节: PDU类型(4位) + RFU(2位) + TxAdd(1位) + RxAdd(1位) // ADV_IND类型 = 0x0, TxAdd=1(随机地址), RxAdd=0 pduHeader[0] = (0x0 << 4) | (0x0 << 2) | (0x1 << 1) | (0x0 << 0); // 第二字节: 长度(6位) + RFU(2位) // 长度不包括报头本身,只包括有效载荷 pduHeader[1] = (length & 0x3F) | (0x0 << 6); printf("PDU Header: 0x%02X 0x%02X\n", pduHeader[0], pduHeader[1]); printf("Payload length: %d\n", length); // 组合完整的PDU: 报头(2字节) + 有效载荷 uint8_t completePdu[2 + length]; completePdu[0] = pduHeader[0]; completePdu[1] = pduHeader[1]; memcpy(&completePdu[2], data, length); // 设置BLE模式 Radio.SetStandby(STDBY_RC); Radio.SetPacketType(PACKET_TYPE_BLE); // 设置调制参数 ModulationParams_t modulationParams; modulationParams.PacketType = PACKET_TYPE_BLE; modulationParams.Params.Ble.BitrateBandwidth = GFS_BLE_BR_1_000_BW_1_2; modulationParams.Params.Ble.ModulationIndex = GFS_BLE_MOD_IND_0_50; modulationParams.Params.Ble.ModulationShaping = RADIO_MOD_SHAPING_BT_0_5; Radio.SetModulationParams(&modulationParams); // 设置包参数 - BLE模式下没有PayloadLength字段 PacketParams_t packetParams; packetParams.PacketType = PACKET_TYPE_BLE; packetParams.Params.Ble.BlePacketType = BLE_EYELONG_1_0; packetParams.Params.Ble.ConnectionState = BLE_ADVERTISER; packetParams.Params.Ble.CrcField = BLE_CRC_3B; packetParams.Params.Ble.Whitening = RADIO_WHITENING_ON; Radio.SetPacketParams(&packetParams); // 设置频率 - BLE广告信道38: 2426000000 Hz Radio.SetRfFrequency(RF_FREQUENCY); // 设置BLE特定参数 Radio.SetSyncWord(1, (uint8_t[]){0xDD, 0xA0, 0x96, 0x69, 0xDD}); Radio.SetBleAdvertizerAccessAddress(); Radio.SetWhiteningSeed(0x33); // 写入寄存器配置 Radio.WriteRegister(0x9C7, 0x55); Radio.WriteRegister(0x9C8, 0x55); Radio.WriteRegister(0x9C9, 0x55); // 设置中断参数并发送完整的PDU uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; Radio.SetDioIrqParams(TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE); // 发送完整的PDU(报头+有效载荷) Radio.SendPayload(completePdu, length + 2, (TickTime_t){RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE}); printf("BLE Advertising packet sent, total PDU length: %d\n", length + 2); } int8_t SX1281_SetRXSingle(void) { Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); return DEVICE_OK; } int8_t SX1281_SetRXSuccessive(void) { Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } ); return DEVICE_OK; } int8_t SX1281_SetTX (void) { Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload((uint8_t*)"12345",5, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE }); return DEVICE_OK; } int8_t SX1281_SetBaudrate(SX1281_t *radio, SX1281_Baudrate_t baudrate) { if (radio==NULL) { return DEVICE_ERR; } radio->baudrate=baudrate; Radio.SetStandby( STDBY_RC ); switch (radio->mode) { case MODE_BLE: case MODE_GFSK: return DEVICE_OK; case MODE_LORA: if (radio->modulationParams.PacketType != PACKET_TYPE_LORA) { #ifdef SX1281_VIEW printf("error: Incorrect parameter"); #endif return DEVICE_ERR; } // radio->modulationParams.Params.LoRa.SpreadingFactor = loraConfigList[baudrate].SpreadingFactor; // radio->modulationParams.Params.LoRa.Bandwidth = loraConfigList[baudrate].SignalBw; // radio->modulationParams.Params.LoRa.CodingRate = loraConfigList[baudrate].ErrorCoding; break; case MODE_FLRC: if (radio->modulationParams.PacketType != PACKET_TYPE_FLRC) { #ifdef SX1281_VIEW printf("error: Incorrect parameter"); #endif return DEVICE_ERR; } // radio->modulationParams.Params.Flrc.BitrateBandwidth = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].BitrateBandwidth; // radio->modulationParams.Params.Flrc.CodingRate = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].CodingRate; // radio->modulationParams.Params.Flrc.ModulationShaping = flrcConfigList[baudrate-(RF_BAUDRATE_LORA_NUM+1)].ModulationShaping; break; default: return DEVICE_ERR; break; } Radio.SetModulationParams( &radio->modulationParams ); return DEVICE_OK; } int8_t SX1281_SetPacketConfig(SX1281_t *radio) { if (radio==NULL) { return DEVICE_ERR; } Radio.SetStandby( STDBY_RC ); return DEVICE_OK; } /** * @brief 退出射频进入休眠 * */ int8_t SX1281_SetSleep(SX1281_t *radio) { if (radio == 0) { return DEVICE_ERR; } // SleepParams_t SleepParams; // SleepParams.DataBufferRetention = 1; // SleepParams.DataRamRetention = 1; // SleepParams.InstructionRamRetention = 1; // SleepParams.WakeUpRTC = 0; // // Radio.SetSleep( SleepParams ); // Radio.SetStandby( STDBY_RC ); return DEVICE_OK; } /** * 获取射频波特率 * @param : br-> */ //SX1281_Baudrate_t SX1281_GetBaudrate(SX1281_t *radio) //{ // if (radio==NULL) // { // return DEVICE_ERR; // } // // return radio->baudrate; //} int8_t SX1281_Running() { SX1281ProcessIrqs(); HAL_Delay(10); return DEVICE_OK; } /* Callback function -------------------------------------------------------- */ __attribute__((weak)) int8_t SX1281_Callback(SX1281_States_t source) { switch (source) { case RX_DONE: /* 打印状态 */ printf( "<>>>>>>>>OnRxDone\n\r" ); /* 从缓冲区拿数据 */ BufferSize = 0; Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); Buffer[BufferSize+1] = 0; /* 重启接收 */ //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); break; case RX_TIMEOUT: /* 打印状态 */ printf( "<>>>>>>>>OnRXTimeout\n\r" ); //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } ); break; case RX_ERROR: /* 打印状态 */ printf( "<>>>>>>>>OnRxErr\n\r" ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); break; case TX_DONE: /* 打印状态 */ printf( "<>>>>>>>>OnTxDone\n\r" ); Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload((uint8_t*)"hello",5, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE }); break; case TX_TIMEOUT: /* 打印状态 */ printf( "<>>>>>>>>OnTxTimeout\n\r" ); break; case LORA_CAD_DONE: /* 打印状态 */ printf( "<>>>>>>>>OnCadDone\n\r" ); break; default: break; } return 0; } void OnTxDone( void ) { sx1281_state = TX_DONE; SX1281_Callback(sx1281_state); } void OnRxDone( void ) { sx1281_state = RX_DONE; SX1281_Callback(sx1281_state); } void OnTxTimeout( void ) { sx1281_state = TX_TIMEOUT; SX1281_Callback(sx1281_state); } void OnRxTimeout( void ) { sx1281_state = RX_TIMEOUT; SX1281_Callback(sx1281_state); } void OnRxError( IrqErrorCode_t errorCode ) { sx1281_state = RX_ERROR; SX1281_Callback(sx1281_state); } void OnCadDone( bool channelActivityDetected ) { sx1281_state = LORA_CAD_DONE; SX1281_Callback(sx1281_state); }