E77-400M22S 是基于ST 新推出的STM32WLE5CCU6(ARM Cortex-M4 + LoRa)SoC 无线通信模块,具备通信远,待机功耗低,抗干扰能力强,接口资源丰富,处理能力强,外形尺寸小等特性。并适用于433/470MHz 频段贴片式LoRa 无线模块, 使用工业级高精度32.768KHz 和32MHz 晶振。
1.工程创建前的准备
硬件:带有E77模块的开发板,2块,我这里使用的是亿佰特的E77-400MBL-01模块,其电路图可到亿佰特官网下载。
开发环境:STM32CubeIDE,建议使用较新的版本。
资源包:BSP包,位于库文件中,官方例程Drivers/BSP/STM32WLxx_Nucleo/文件夹下,也可到github下载,点击下载。
2.创建工程
2.1 STM32CubeIDE图形化工具设置
2.1.1选择对应的MCU,创建工程
2.1.2配置RTC
为了方便配置时钟树,这里先进行RTC配置。
点击add按钮,在弹出的窗口添加常数,依次添加下列常数名和常数值。
Constant Name | Constant Value |
---|---|
RTC_PREDIV_A | ((1<<(15-RTC_N_PREDIV_S))-1) |
RTC_PREDIV_S | ((1<<RTC_N_PREDIV_S)-1) |
RTC_N_PREDIV_S | 10 |
然后,返回到Parameter Settings页面,配置RTC参数。
最后,开启RTC中断
2.1.3时钟树配置
这里不使用外部时钟
下面配置时钟树,RTC时钟源选择32KHz内部时钟,系统时钟源选择48000KHz内部时钟。
2.1.4 系统滴嗒不开启,若要开启需注意设置优先级
2.1.5串口设置,这里使用LPUART1,对应引脚为PA2->TX和PA3->RX。
开启串口DMA,DMA设置如下
开启串口中断
串口中断优先级设置,为了防止串口DMA中断与任务管理器调度冲突,将串口和DMA中断设置为2,0
2.1.6开启SUBGHZ
2.1.7 设置SBUGHZ_PHY(物理层)
打开SUBGHZ功能后,点击中间件(Middleware)选项,找到“ _SUBGHZ_PHY _ ”,使能后,在应用栏,选择高级模板选项 *Advanced template* , 下面介绍下几个主要的参数。 Trace verbose level:日志打印级别 有H,M,L三个级别,日志信息由高到低,默认为VLEVEL_M; Enable Application Logging : 使能应用日志打印,关闭串口不打印日志,默认开启; Disable Low Power Mode : 关闭低功耗模式,默认开启低功耗;
Modem :调制解调模式,有Lora和FSK两种,本次测试时基于Lora。 Region :区域选择,根据所在区域选择,国内选择 470MHz 中国频段 。 LoRa bandwidth:带宽,带宽于灵敏度呈负相关,带宽约高,灵敏度越低,这里使用最低的125KHz。 LoRa spreading factor :扩频因子;与信噪比(SNR)呈正相关,扩频因子越大,传输误码率(信噪比)越低, 但传输的数据速率(比特率)就越小。这里使用SF7。 LoRa coding rate :编码率;数据流中有用的部分,用于检验传输有无出错。默认使用CR 4/5。 LoRa preamble length :前导码长度,最常用的有8Bit和16Bit,这里使用8bit。 LoRa symbol timeout :帧超时,帧数为5。 LoRa fix length payload on : 数据负载混合长度,默认不开启。 LoRa IQ inversion : 默认不开启。 Payload length :数据负载长度,使用64bit数据长度。
Probes Lines in Platform Settings :在硬件平台设置中开启监测线,即使用IO状态对程序运行出现的错误进行警告,这里选择不开启。
2.1.8 DEBUG模式设置
2.1.9 代码生成器设置 ,生成代码
3. 添加BSP驱动文件
将BSP文件夹添加到工程Drivers目录下,并设置文件路径。
4. 代码修改
首先,确认下面的宏是开启的,SUBGHZ_HPY设置正确的话,一般这地方是开启的,如果未开启,则检查相应的设置。
//31行
#define USE_BSP_DRIVER
3.1 main.c
添加初始化代码
/* USER CODE BEGIN 2 */
BSP_RADIO_Init();
BSP_LED_Init(LED1);
BSP_LED_Init(LED2);
/* USER CODE END 2 */
3.2 stm32wlxx_nucleo_radio.h
//99行
#define RF_SW_CTRL3_PIN GPIO_PIN_6
#define RF_SW_CTRL3_GPIO_PORT GPIOA
#define RF_SW_CTRL3_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define RF_SW_CTRL3_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE()
#define RF_SW_CTRL1_PIN GPIO_PIN_7
#define RF_SW_CTRL1_GPIO_PORT GPIOA
#define RF_SW_CTRL1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
#define RF_SW_RX_GPIO_CLK_DISABLE() __HAL_RCC_GPIOC_CLK_DISABLE()
文件中的其它端口(按键和LED)可根据自己的开发板,做相应的更改。
3.3 stm32wlxx_nucleo_radio.c
//105行
int32_t BSP_RADIO_ConfigRFSwitch(BSP_RADIO_Switch_TypeDef Config)
{
switch (Config)
{
case RADIO_SWITCH_OFF:
{
/* Turn off switch */
HAL_GPIO_WritePin(RF_SW_CTRL3_GPIO_PORT, RF_SW_CTRL3_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RADIO_SWITCH_RX:
{
/*Turns On in Rx Mode the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL3_GPIO_PORT, RF_SW_CTRL3_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_RESET);
break;
}
case RADIO_SWITCH_RFO_LP:
{
/*Turns On in Tx Low Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL3_GPIO_PORT, RF_SW_CTRL3_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
case RADIO_SWITCH_RFO_HP:
{
/*Turns On in Tx High Power the RF Switch */
HAL_GPIO_WritePin(RF_SW_CTRL3_GPIO_PORT, RF_SW_CTRL3_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(RF_SW_CTRL1_GPIO_PORT, RF_SW_CTRL1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(RF_SW_CTRL2_GPIO_PORT, RF_SW_CTRL2_PIN, GPIO_PIN_SET);
break;
}
default:
break;
}
return BSP_ERROR_NONE;
}
//155行
int32_t BSP_RADIO_GetTxConfig(void)
{
// return RADIO_CONF_RFO_LP_HP;
return RADIO_CONF_RFO_HP;
}
//168行
int32_t BSP_RADIO_IsTCXO(void)
{
// return RADIO_CONF_TCXO_SUPPORTED;
return RADIO_CONF_TCXO_NOT_SUPPORTED;
}
3.4 subghz_phy_app.c 完整代码
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file subghz_phy_app.c
* @author MCD Application Team
* @brief Application of the SubGHz_Phy Middleware
******************************************************************************
* @attention
*
* Copyright (c) 2023 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 "platform.h"
#include "sys_app.h"
#include "subghz_phy_app.h"
#include "radio.h"
/* USER CODE BEGIN Includes */
#include "stm32_timer.h"
#include "stm32_seq.h"
#include "utilities_def.h"
#include "app_version.h"
#include "subghz_phy_version.h"
/* USER CODE END Includes */
/* External variables ---------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum
{
RX,
RX_TIMEOUT,
RX_ERROR,
TX,
TX_TIMEOUT,
} States_t;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* Configurations */
/*Timeout*/
#define RX_TIMEOUT_VALUE 3000
#define TX_TIMEOUT_VALUE 3000
/* PING string*/
#define PING "PING"
/* PONG string*/
#define PONG "PONG"
/*Size of the payload to be sent*/
/* Size must be greater of equal the PING and PONG*/
#define MAX_APP_BUFFER_SIZE 255
#if (PAYLOAD_LEN > MAX_APP_BUFFER_SIZE)
#error PAYLOAD_LEN must be less or equal than MAX_APP_BUFFER_SIZE
#endif /* (PAYLOAD_LEN > MAX_APP_BUFFER_SIZE) */
/* wait for remote to be in Rx, before sending a Tx frame*/
#define RX_TIME_MARGIN 200
/* Afc bandwidth in Hz */
#define FSK_AFC_BANDWIDTH 83333
/* LED blink Period*/
#define LED_PERIOD_MS 200
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* Radio events function pointer */
static RadioEvents_t RadioEvents;
/* USER CODE BEGIN PV */
/*Ping Pong FSM states */
static States_t State = RX;
/* App Rx Buffer*/
static uint8_t BufferRx[MAX_APP_BUFFER_SIZE];
/* App Tx Buffer*/
static uint8_t BufferTx[MAX_APP_BUFFER_SIZE];
/* Last Received Buffer Size*/
uint16_t RxBufferSize = 0;
/* Last Received packer Rssi*/
int8_t RssiValue = 0;
/* Last Received packer SNR (in Lora modulation)*/
int8_t SnrValue = 0;
/* Led Timers objects*/
static UTIL_TIMER_Object_t timerLed;
/* device state. Master: true, Slave: false*/
bool isMaster = true;
/* random delay to make sure 2 devices will sync*/
/* the closest the random delays are, the longer it will
take for the devices to sync when started simultaneously*/
static int32_t random_delay;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/*!
* @brief Function to be executed on Radio Tx Done event
*/
static void OnTxDone(void);
/**
* @brief Function to be executed on Radio Rx Done event
* @param payload ptr of buffer received
* @param size buffer size
* @param rssi
* @param LoraSnr_FskCfo
*/
static void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t LoraSnr_FskCfo);
/**
* @brief Function executed on Radio Tx Timeout event
*/
static void OnTxTimeout(void);
/**
* @brief Function executed on Radio Rx Timeout event
*/
static void OnRxTimeout(void);
/**
* @brief Function executed on Radio Rx Error event
*/
static void OnRxError(void);
/* USER CODE BEGIN PFP */
/**
* @brief Function executed on when led timer elapses
* @param context ptr of LED context
*/
static void OnledEvent(void *context);
/**
* @brief PingPong state machine implementation
*/
static void PingPong_Process(void);
/* USER CODE END PFP */
/* Exported functions ---------------------------------------------------------*/
void SubghzApp_Init(void)
{
/* USER CODE BEGIN SubghzApp_Init_1 */
APP_LOG(TS_OFF, VLEVEL_M, "\n\rPING PONG\n\r");
/* Get SubGHY_Phy APP version*/
APP_LOG(TS_OFF, VLEVEL_M, "APPLICATION_VERSION: V%X.%X.%X\r\n",
(uint8_t)(APP_VERSION_MAIN),
(uint8_t)(APP_VERSION_SUB1),
(uint8_t)(APP_VERSION_SUB2));
/* Get MW SubGhz_Phy info */
APP_LOG(TS_OFF, VLEVEL_M, "MW_RADIO_VERSION: V%X.%X.%X\r\n",
(uint8_t)(SUBGHZ_PHY_VERSION_MAIN),
(uint8_t)(SUBGHZ_PHY_VERSION_SUB1),
(uint8_t)(SUBGHZ_PHY_VERSION_SUB2));
/* Led Timers*/
UTIL_TIMER_Create(&timerLed, LED_PERIOD_MS, UTIL_TIMER_ONESHOT, OnledEvent, NULL);
UTIL_TIMER_Start(&timerLed);
/* USER CODE END SubghzApp_Init_1 */
/* Radio initialization */
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
Radio.Init(&RadioEvents);
/* USER CODE BEGIN SubghzApp_Init_2 */
/*calculate random delay for synchronization*/
random_delay = (Radio.Random()) >> 22; /*10bits random e.g. from 0 to 1023 ms*/
/* Radio Set frequency */
Radio.SetChannel(RF_FREQUENCY);
/* Radio configuration */
#if ((USE_MODEM_LORA == 1) && (USE_MODEM_FSK == 0))
APP_LOG(TS_OFF, VLEVEL_M, "---------------\n\r");
APP_LOG(TS_OFF, VLEVEL_M, "LORA_MODULATION\n\r");
APP_LOG(TS_OFF, VLEVEL_M, "LORA_BW=%d kHz\n\r", (1 << LORA_BANDWIDTH) * 125);
APP_LOG(TS_OFF, VLEVEL_M, "LORA_SF=%d\n\r", LORA_SPREADING_FACTOR);
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, TX_TIMEOUT_VALUE);
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.SetMaxPayloadLength(MODEM_LORA, MAX_APP_BUFFER_SIZE);
#elif ((USE_MODEM_LORA == 0) && (USE_MODEM_FSK == 1))
APP_LOG(TS_OFF, VLEVEL_M, "---------------\n\r");
APP_LOG(TS_OFF, VLEVEL_M, "FSK_MODULATION\n\r");
APP_LOG(TS_OFF, VLEVEL_M, "FSK_BW=%d Hz\n\r", FSK_BANDWIDTH);
APP_LOG(TS_OFF, VLEVEL_M, "FSK_DR=%d bits/s\n\r", FSK_DATARATE);
Radio.SetTxConfig(MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
FSK_DATARATE, 0,
FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, 0, TX_TIMEOUT_VALUE);
Radio.SetRxConfig(MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true,
0, 0, false, true);
Radio.SetMaxPayloadLength(MODEM_FSK, MAX_APP_BUFFER_SIZE);
#else
#error "Please define a modulation in the subghz_phy_app.h file."
#endif /* USE_MODEM_LORA | USE_MODEM_FSK */
/*fills tx buffer*/
memset(BufferTx, 0x0, MAX_APP_BUFFER_SIZE);
APP_LOG(TS_ON, VLEVEL_L, "rand=%d\n\r", random_delay);
/*starts reception*/
Radio.Rx(RX_TIMEOUT_VALUE + random_delay);
/*register task to to be run in while(1) after Radio IT*/
UTIL_SEQ_RegTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), UTIL_SEQ_RFU, PingPong_Process);
/* USER CODE END SubghzApp_Init_2 */
}
/* USER CODE BEGIN EF */
/* USER CODE END EF */
/* Private functions ---------------------------------------------------------*/
static void OnTxDone(void)
{
/* USER CODE BEGIN OnTxDone */
APP_LOG(TS_ON, VLEVEL_L, "OnTxDone\n\r");
/* Update the State of the FSM*/
State = TX;
/* Run PingPong process in background*/
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
/* USER CODE END OnTxDone */
}
static void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t LoraSnr_FskCfo)
{
/* USER CODE BEGIN OnRxDone */
APP_LOG(TS_ON, VLEVEL_L, "OnRxDone\n\r");
#if ((USE_MODEM_LORA == 1) && (USE_MODEM_FSK == 0))
APP_LOG(TS_ON, VLEVEL_L, "RssiValue=%d dBm, SnrValue=%ddB\n\r", rssi, LoraSnr_FskCfo);
/* Record payload Signal to noise ratio in Lora*/
SnrValue = LoraSnr_FskCfo;
#endif /* USE_MODEM_LORA | USE_MODEM_FSK */
#if ((USE_MODEM_LORA == 0) && (USE_MODEM_FSK == 1))
APP_LOG(TS_ON, VLEVEL_L, "RssiValue=%d dBm, Cfo=%dkHz\n\r", rssi, LoraSnr_FskCfo);
SnrValue = 0; /*not applicable in GFSK*/
#endif /* USE_MODEM_LORA | USE_MODEM_FSK */
/* Update the State of the FSM*/
State = RX;
/* Clear BufferRx*/
memset(BufferRx, 0, MAX_APP_BUFFER_SIZE);
/* Record payload size*/
RxBufferSize = size;
if (RxBufferSize <= MAX_APP_BUFFER_SIZE)
{
memcpy(BufferRx, payload, RxBufferSize);
}
/* Record Received Signal Strength*/
RssiValue = rssi;
/* Record payload content*/
APP_LOG(TS_ON, VLEVEL_H, "payload. size=%d \n\r", size);
for (int i = 0; i < PAYLOAD_LEN; i++)
{
APP_LOG(TS_OFF, VLEVEL_H, "%02X", BufferRx[i]);
if (i % 16 == 15)
{
APP_LOG(TS_OFF, VLEVEL_H, "\n\r");
}
}
APP_LOG(TS_OFF, VLEVEL_H, "\n\r");
/* Run PingPong process in background*/
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
/* USER CODE END OnRxDone */
}
static void OnTxTimeout(void)
{
/* USER CODE BEGIN OnTxTimeout */
APP_LOG(TS_ON, VLEVEL_L, "OnTxTimeout\n\r");
/* Update the State of the FSM*/
State = TX_TIMEOUT;
/* Run PingPong process in background*/
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
/* USER CODE END OnTxTimeout */
}
static void OnRxTimeout(void)
{
/* USER CODE BEGIN OnRxTimeout */
APP_LOG(TS_ON, VLEVEL_L, "OnRxTimeout\n\r");
/* Update the State of the FSM*/
State = RX_TIMEOUT;
/* Run PingPong process in background*/
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
/* USER CODE END OnRxTimeout */
}
static void OnRxError(void)
{
/* USER CODE BEGIN OnRxError */
APP_LOG(TS_ON, VLEVEL_L, "OnRxError\n\r");
/* Update the State of the FSM*/
State = RX_ERROR;
/* Run PingPong process in background*/
UTIL_SEQ_SetTask((1 << CFG_SEQ_Task_SubGHz_Phy_App_Process), CFG_SEQ_Prio_0);
/* USER CODE END OnRxError */
}
/* USER CODE BEGIN PrFD */
static void PingPong_Process(void)
{
Radio.Sleep();
switch (State)
{
case RX:
if (isMaster == true)
{
if (RxBufferSize > 0)
{
if (strncmp((const char *)BufferRx, PONG, sizeof(PONG) - 1) == 0)
{
UTIL_TIMER_Stop(&timerLed);
/* switch off led2 */
BSP_LED_Off(LED2);
/* master toggles led1 */
BSP_LED_Toggle(LED1);
/* Add delay between RX and TX */
HAL_Delay(Radio.GetWakeupTime() + RX_TIME_MARGIN);
/* master sends PING*/
APP_LOG(TS_ON, VLEVEL_L, "..."
"PING"
"\n\r");
APP_LOG(TS_ON, VLEVEL_L, "Master Tx start\n\r");
memcpy(BufferTx, PING, sizeof(PING) - 1);
Radio.Send(BufferTx, PAYLOAD_LEN);
}
else if (strncmp((const char *)BufferRx, PING, sizeof(PING) - 1) == 0)
{
/* A master already exists then become a slave */
isMaster = false;
APP_LOG(TS_ON, VLEVEL_L, "Slave Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
}
else /* valid reception but neither a PING or a PONG message */
{
/* Set device as master and start again */
isMaster = true;
APP_LOG(TS_ON, VLEVEL_L, "Master Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
}
}
}
else
{
if (RxBufferSize > 0)
{
if (strncmp((const char *)BufferRx, PING, sizeof(PING) - 1) == 0)
{
UTIL_TIMER_Stop(&timerLed);
/* switch off red led */
BSP_LED_Off(LED1);
/* slave toggles green led */
BSP_LED_Toggle(LED2);
/* Add delay between RX and TX */
HAL_Delay(Radio.GetWakeupTime() + RX_TIME_MARGIN);
/*slave sends PONG*/
APP_LOG(TS_ON, VLEVEL_L, "..."
"PONG"
"\n\r");
APP_LOG(TS_ON, VLEVEL_L, "Slave Tx start\n\r");
memcpy(BufferTx, PONG, sizeof(PONG) - 1);
Radio.Send(BufferTx, PAYLOAD_LEN);
}
else /* valid reception but not a PING as expected */
{
/* Set device as master and start again */
isMaster = true;
APP_LOG(TS_ON, VLEVEL_L, "Master Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
}
}
}
break;
case TX:
APP_LOG(TS_ON, VLEVEL_L, "Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
break;
case RX_TIMEOUT:
case RX_ERROR:
if (isMaster == true)
{
/* Send the next PING frame */
/* Add delay between RX and TX*/
/* add random_delay to force sync between boards after some trials*/
HAL_Delay(Radio.GetWakeupTime() + RX_TIME_MARGIN + random_delay);
APP_LOG(TS_ON, VLEVEL_L, "Master Tx start\n\r");
/* master sends PING*/
memcpy(BufferTx, PING, sizeof(PING) - 1);
Radio.Send(BufferTx, PAYLOAD_LEN);
}
else
{
APP_LOG(TS_ON, VLEVEL_L, "Slave Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
}
break;
case TX_TIMEOUT:
APP_LOG(TS_ON, VLEVEL_L, "Slave Rx start\n\r");
Radio.Rx(RX_TIMEOUT_VALUE);
break;
default:
break;
}
}
static void OnledEvent(void *context)
{
BSP_LED_Toggle(LED1);
BSP_LED_Toggle(LED2);
UTIL_TIMER_Start(&timerLed);
}
/* USER CODE END PrFD */
5.编译下载
代码修改完成后,即可编译并烧录到两块开发板中,通过串口调试助手可观察到两个模块间的数据传输情况。