/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "spi.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include #include "stdio.h" #include "hw.h" #include "radio.h" #include "sx1281.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ int fputc(int ch,FILE *f) { //采用轮询方式发送1字节数据,超时时间设置为无限等待 HAL_UART_Transmit(&huart2,(uint8_t *)&ch,1,HAL_MAX_DELAY); return ch; } /*! * \brief Used to display firmware version UART flow */ #define FIRMWARE_VERSION ( ( char* )"Firmware Version: 170919A" ) /*! * Select mode of operation for the Ping Ping application */ #define MODE_BLE /* Bluetooth Low Energy */ // #define MODE_LORA /* Long Range */ // #define MODE_GFSK /* Gaussian Frequency Shift Keying */ // #define MODE_FLRC /* Fast Long Range Codec */ #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 output power in dBm * * \remark The range of the output power is [-18..+13] dBm */ #define TX_OUTPUT_POWER 13 /*! * \brief Defines the buffer size, i.e. the payload size */ #define BUFFER_SIZE 20 /*! * \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 /*! * \brief Defines the size of the token defining message type in the payload */ #define PINGPONGSIZE 4 /*! * \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 Define the possible message type for this application */ const uint8_t PingMsg[] = "PING"; const uint8_t PongMsg[] = "PONG"; /*! * \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]; /*! * \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 */ AppStates_t AppState = APP_LOWPOWER; #if defined( MODE_BLE ) /*! * \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; #endif // MODE_BLE PacketParams_t packetParams; PacketStatus_t packetStatus; /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_SPI1_Init(); MX_SPI2_Init(); MX_TIM1_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); /* USER CODE BEGIN 2 */ printf("CLK: SYS=%ld APB1=%ld APB2=%ld\r\n", HAL_RCC_GetSysClockFreq(), HAL_RCC_GetPCLK1Freq(), HAL_RCC_GetPCLK2Freq()); bool isMaster = true; ModulationParams_t modulationParams; HwInit( ); HAL_Delay( 500 ); // let DC/DC power ramp up Radio.Init( &Callbacks ); // Radio.SetRegulatorMode( USE_DCDC ); // Can also be set in LDO mode but consume more power memset( &Buffer, 0x00, BufferSize ); /* 1. 确保芯片已复位且 BUSY=0 */ SX1281HalReset(); // 已在 HwInit() 里调过,这里再调一次更保险 while (HAL_GPIO_ReadPin(RADIO_BUSY_PORT, RADIO_BUSY_PIN) != GPIO_PIN_RESET) ; // 等 BUSY 低 /* 2. 单包 SPI 双向测试 */ uint8_t tx[3] = {0x48, 0x00, 0x00}; // 读 Reg00 uint8_t rx[3] = {0}; HAL_GPIO_WritePin(RADIO_NSS_PORT, RADIO_NSS_PIN, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(&hspi1, tx, rx, 3, 100); HAL_GPIO_WritePin(RADIO_NSS_PORT, RADIO_NSS_PIN, GPIO_PIN_SET); /* 3. 打印结果 */ printf("tx: %02X %02X %02X\n", tx[0], tx[1], tx[2]); printf("rx: %02X %02X %02X\n", rx[0], rx[1], rx[2]); /* 4. 判断 */ if (rx[1] == 0xFF && rx[2] == 0xFF) printf("-> MISO 全高,SPI 没回话\n"); else if (rx[1] == 0x00 && rx[2] == 0x00) printf("-> MISO 全低,可能短地\n"); else if (rx[1] == 0x40 || rx[2] == 0x40) printf("-> SPI 双向 OK!\n"); 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( ) ); #if defined( MODE_BLE ) printf( "\nPing Pong running in BLE mode\n\r" ); 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; 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; #elif defined( MODE_GFSK ) printf( "\nPing Pong running in GFSK mode\n\r" ); modulationParams.PacketType = PACKET_TYPE_GFSK; modulationParams.Params.Gfsk.BitrateBandwidth = GFS_BLE_BR_0_125_BW_0_3; modulationParams.Params.Gfsk.ModulationIndex = GFS_BLE_MOD_IND_1_00; modulationParams.Params.Gfsk.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0; packetParams.PacketType = PACKET_TYPE_GFSK; packetParams.Params.Gfsk.PreambleLength = PREAMBLE_LENGTH_32_BITS; packetParams.Params.Gfsk.SyncWordLength = GFS_SYNCWORD_LENGTH_5_BYTE; packetParams.Params.Gfsk.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1; packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_VARIABLE_LENGTH; packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE; packetParams.Params.Gfsk.CrcLength = RADIO_CRC_3_BYTES; packetParams.Params.Gfsk.Whitening = RADIO_WHITENING_ON; #elif defined( MODE_LORA ) printf( "\nPing Pong running in LORA mode\n\r" ); modulationParams.PacketType = PACKET_TYPE_LORA; modulationParams.Params.LoRa.SpreadingFactor = LORA_SF12; modulationParams.Params.LoRa.Bandwidth = LORA_BW_1600; modulationParams.Params.LoRa.CodingRate = LORA_CR_LI_4_7; packetParams.PacketType = PACKET_TYPE_LORA; packetParams.Params.LoRa.PreambleLength = 12; packetParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH; packetParams.Params.LoRa.PayloadLength = BUFFER_SIZE; packetParams.Params.LoRa.CrcMode = LORA_CRC_ON; packetParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL; #elif defined( MODE_FLRC ) printf( "\nPing Pong running in FLRC mode\n\r" ); modulationParams.PacketType = PACKET_TYPE_FLRC; modulationParams.Params.Flrc.BitrateBandwidth = FLRC_BR_0_260_BW_0_3; modulationParams.Params.Flrc.CodingRate = FLRC_CR_1_2; modulationParams.Params.Flrc.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0; packetParams.PacketType = PACKET_TYPE_FLRC; packetParams.Params.Flrc.PreambleLength = PREAMBLE_LENGTH_32_BITS; packetParams.Params.Flrc.SyncWordLength = FLRC_SYNCWORD_LENGTH_4_BYTE; packetParams.Params.Flrc.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1; packetParams.Params.Flrc.HeaderType = RADIO_PACKET_VARIABLE_LENGTH; packetParams.Params.Flrc.PayloadLength = BUFFER_SIZE; packetParams.Params.Flrc.CrcLength = RADIO_CRC_3_BYTES; packetParams.Params.Flrc.Whitening = RADIO_WHITENING_OFF; #else #error "Please select the mode of operation for the Ping Ping demo" #endif Radio.SetStandby( STDBY_RC ); Radio.SetPacketType( modulationParams.PacketType ); Radio.SetModulationParams( &modulationParams ); Radio.SetPacketParams( &packetParams ); Radio.SetRfFrequency( RF_FREQUENCY ); Radio.SetBufferBaseAddresses( 0x00, 0x00 ); Radio.SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_02_US ); SX1281SetPollingMode( ); #if defined( 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 = PINGPONGSIZE + 2; ble_header_adv.Fields.pduType = 2; #endif // MODE_BLE //可以修改成ws2812做发射/接收指示灯 // GpioWrite( LED_TX_PORT, LED_TX_PIN, 0 ); // GpioWrite( LED_RX_PORT, LED_RX_PIN, 0 ); Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); AppState = APP_LOWPOWER; /* 人为触发一次发送,验证整条通路 */ static uint8_t once = 1; if (once) { once = 0; uint8_t ping[] = "PING"; Radio.SendPayload(ping, 4, (TickTime_t){RADIO_TICK_SIZE_1000_US, 100}); printf("Force TX\n"); } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ static uint8_t once = 1; if (once) { once = 0; uint8_t ping[] = "PING"; Radio.SetDioIrqParams(TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE); Radio.SendPayload(ping, 4, (TickTime_t){RADIO_TICK_SIZE_1000_US, 100}); printf("Force TX -> should RX myself\r\n"); } // uint16_t irq = Radio.GetIrqStatus(); //if (irq) printf("IRQ=0x%04X\r\n", irq); static uint8_t fifty = 0; if(fifty<50){ fifty++; uint8_t id; Radio.ReadRegisters(0x00, &id, 1); // 读 Chip Mode 寄存器 printf("Reg00=0x%02X (expect 0x40 or 0xFF)\r\n", id); } SX1281ProcessIrqs( ); switch( AppState ) { case APP_RX: AppState = APP_LOWPOWER; // GpioWrite( LED_RX_PORT, LED_RX_PIN, GpioRead( LED_RX_PORT, LED_RX_PIN ) ^ 1 ); Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); #if defined( MODE_BLE ) // Remove the 2st bytes that are BLE header from Buffer memcpy( Buffer, Buffer+2, PINGPONGSIZE ); #endif // MODE_BLE if( isMaster == true ) { if( BufferSize > 0 ) { if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, PINGPONGSIZE ) == 0 ) { printf( "...Pong\r\n" ); #if defined( MODE_BLE ) memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PingMsg, PINGPONGSIZE ); #else memcpy( Buffer, PingMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 ) { // A master already exists then become a slave printf( "...Ping - switch to Slave\r\n" ); isMaster = false; #if defined( MODE_BLE ) memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PongMsg, PINGPONGSIZE ); #else memcpy( Buffer, PongMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } else // valid reception but neither a PING or a PONG message { // Set device as master ans start again isMaster = true; #if defined( MODE_BLE ) memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PongMsg, PINGPONGSIZE ); Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); #else Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); #endif } } } else { if( BufferSize > 0 ) { if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, PINGPONGSIZE ) == 0 ) { printf( "...Ping\r\n" ); #if defined( MODE_BLE ) ble_header_adv.Fields.length = PINGPONGSIZE + 2; memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PongMsg, PINGPONGSIZE ); #else memcpy( Buffer, PongMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } else // valid reception but not a PING as expected { printf( "...Unexpected packet - switch to master\r\n" ); isMaster = true; Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); } } } break; case APP_TX: AppState = APP_LOWPOWER; // GpioWrite( LED_TX_PORT, LED_TX_PIN, GpioRead( LED_TX_PORT, LED_TX_PIN ) ^ 1 ); if( isMaster == true ) { printf( "Ping...\r\n" ); } else { printf( "Pong...\r\n" ); } Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); break; case APP_RX_TIMEOUT: AppState = APP_LOWPOWER; if( isMaster == true ) { // Send the next PING frame #if defined( MODE_BLE ) ble_header_adv.Fields.length = PINGPONGSIZE + 2; memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PingMsg, PINGPONGSIZE ); #else memcpy( Buffer, PingMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } else { Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); } break; case APP_RX_ERROR: AppState = APP_LOWPOWER; // We have received a Packet with a CRC error, send reply as if packet was correct if( isMaster == true ) { // Send the next PING frame #if defined( MODE_BLE ) ble_header_adv.Fields.length = PINGPONGSIZE + 2; memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PingMsg, PINGPONGSIZE ); #else memcpy( Buffer, PingMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } else { // Send the next PONG frame #if defined( MODE_BLE ) ble_header_adv.Fields.length = PINGPONGSIZE + 2; memcpy( Buffer, ble_header_adv.Serial, 2 ); memcpy( Buffer+2, PongMsg, PINGPONGSIZE ); #else memcpy( Buffer, PongMsg, PINGPONGSIZE ); #endif Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload( Buffer, BufferSize, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE } ); } break; case APP_TX_TIMEOUT: AppState = APP_LOWPOWER; Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); break; case APP_LOWPOWER: break; default: // Set low power break; } } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV2; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void OnTxDone( void ) { AppState = APP_TX; } void OnRxDone( void ) { AppState = APP_RX; } void OnTxTimeout( void ) { AppState = APP_TX_TIMEOUT; printf( "<>>>>>>>>TXE\n\r" ); } void OnRxTimeout( void ) { AppState = APP_RX_TIMEOUT; } void OnRxError( IrqErrorCode_t errorCode ) { AppState = APP_RX_ERROR; printf( "RXE<>>>>>>>>\n\r" ); } void OnCadDone( bool channelActivityDetected ) { } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */