2025-02-03 10:53 AM
Hello,
I'm using the B-WL5M-SUB1G, using Visual Studio as my programming environment, attempting to get LoRa TX working without using the middleware.
The code is below. The project serial output is below the code block. Referencing RM0453 Rev 6 (STM32WL5x reference manual), on page 204, there is the "Basic sequence for LoRa... transmit operation", and I believe I'm following all the steps, yet, get a command failure option when putting the radio into TX mode. Here are the steps I'm performing:
The radio immediately returns with the radio in RC13 standby mode, and a CmdStatus of 0x5, which is "command execution failure"
What am I missing? Are there any true examples anywhere of setting up LoRa sending/receiving while only using the HAL without middleware?
Some extra details:
This is a single core example, only using the M4 core, with sysclk being set to MSI 16MHz, all APB divisors set to 1, and the SUBGHZ prescaler set to 8.
//Used for printf
int _write(int file, char *data, int len)
{
UNUSED(file);
HAL_UART_Transmit(&huart2, (uint8_t*)data, len, HAL_MAX_DELAY);
return len;
}
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_I2C2_Init();
MX_SPI2_Init();
MX_USART2_UART_Init();
MX_ADC_Init();
MX_AES_Init();
MX_CRC_Init();
//MX_RNG_Init();
MX_RTC_Init();
MX_SUBGHZ_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
#define RADIO_MODE_BITFIELD 0x70
#define RADIO_STATUS_BITFIELD 0x0E
while (1)
{
HAL_Delay(500);
printf("Toggle 1\r\n");
HAL_GPIO_TogglePin(GPIOB, LED1_Pin);
HAL_Delay(500);
printf("Toggle 2\r\n");
HAL_GPIO_TogglePin(GPIOB, LED2_Pin);
HAL_Delay(500);
printf("Toggle 3\r\n");
HAL_GPIO_TogglePin(GPIOB, LED3_Pin);
uint8_t radioParam, radioResult;
uint8_t radioCmd[8] = {0};
uint8_t dataToSend[100] = {0};
for(int i = 0; i<100; i++){
dataToSend[i] = i;
}
radioParam = 0;
if(HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_SLEEP, &radioParam, 1) != HAL_OK){
printf("Sleep Failed\r\n");
}
radioParam = 0; //RC13 used
if(HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_STANDBY, &radioParam, 1) != HAL_OK){
printf("Standby Failed\r\n");
}
if(HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1) != HAL_OK){
printf("Get Status Failed\r\n");
}
printf("Status is: 0x%02x\r\n", radioResult);
radioParam = 1; //lora mode
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACKETTYPE, &radioParam, 1);
//verify lora mode
HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_PACKETTYPE, radioCmd, 2);
printf("Should be 1 for lora mode: 0x%02x 0x%02x\r\n", radioCmd[0], radioCmd[1]);
radioCmd[0] = 0x00;
radioCmd[1] = 0x0C; //preamble = 12
radioCmd[2] = 0; //explicit header
radioCmd[3] = 0; //payload length, 0 for explicit header?
radioCmd[4] = 0; //Disable CRC
radioCmd[5] = 0; //Disable IQ inversion
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACKETPARAMS, radioCmd, 6);
//Set syn word to "W"
HAL_SUBGHZ_WriteRegister(&hsubghz, 0x740, 0);
HAL_SUBGHZ_WriteRegister(&hsubghz, 0x741, 0x57);
//Verify sync word
HAL_SUBGHZ_ReadRegister(&hsubghz, 0x740, radioCmd);
printf("Sync word MSB: 0x%02x\r\n", radioCmd[0]);
HAL_SUBGHZ_ReadRegister(&hsubghz, 0x741, radioCmd);
printf("Sync word MSB: 0x%02x\r\n", radioCmd[0]);
radioCmd[0] = 0;
radioCmd[1] = 0;
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_BUFFERBASEADDRESS, radioCmd, 2);
//Should be fulfilled in reg 0x802 and 0x803 (tx and rx respective)
HAL_SUBGHZ_ReadRegister(&hsubghz, 0x802, radioCmd);
printf("TX Pointer: 0x%02x\r\n", radioCmd[0]);
HAL_SUBGHZ_ReadRegister(&hsubghz, 0x803, radioCmd);
printf("RX Pointer: 0x%02x\r\n", radioCmd[0]);
//Write data
HAL_SUBGHZ_WriteBuffer(&hsubghz, 0, dataToSend, 32);
//Set Frequency to 915MHz
uint32_t rf915 = 0x39300000;
radioCmd[0] = (rf915 >> 24) & 0xFF;
radioCmd[1] = (rf915 >> 16) & 0xFF;
radioCmd[2] = (rf915 >> 8) & 0xFF;
radioCmd[3] = (rf915) & 0xFF;
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_RFFREQUENCY, radioCmd, 4);
//To Transmit at +14dBm in LP Mode
//PaDutyCycle = 0x4
//HpMax = 0x0
//PASel = 1
//Power = 0xE
radioCmd[0] = 0x4;
radioCmd[1] = 0x0;
radioCmd[2] = 0x1;
radioCmd[3] = 0x1;
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_PACONFIG, radioCmd, 4);
radioCmd[0] = 0xE;
radioCmd[1] = 0x06; //1.7ms ramp
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_TXPARAMS, radioCmd, 2);
radioCmd[0] = 0x9; //SF
radioCmd[1] = 0x4; //BW
radioCmd[2] = 0x4; //CR = 4/8
radioCmd[3] = 0x0; //low data optimize off
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_MODULATIONPARAMS, radioCmd, 4);
//Enable bit 0 on line 0(txdone) and bit 9 on line 1(tx timeout)
radioCmd[0] = 0;
radioCmd[1] = 0x1;
radioCmd[2] = 0x2;
radioCmd[3] = 0;
for(int i = 4; i<8; i++){
radioCmd[i] = 0;
}
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_CFG_DIOIRQ, radioCmd, 8);
if(HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1) != HAL_OK){
printf("Get Status Failed\r\n");
}
HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
uint8_t result = (radioResult & RADIO_MODE_BITFIELD) >> 4;
uint8_t status = (radioResult & RADIO_STATUS_BITFIELD) >> 1;
printf("Status is: 0x%02x 0x%02x\r\n", result, status);
for(int i = 0; i<8; i++){
radioCmd[i] = 0;
}
//Disable timeout, transmit
HAL_SUBGHZ_ExecSetCmd(&hsubghz, RADIO_SET_TX, radioCmd, 3);
uint32_t startTime = HAL_GetTick();
HAL_Delay(100);
HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
printf("%lums have elapsed, status: 0x%02x\r\n", HAL_GetTick() - startTime, radioResult);
if((radioResult & (1 << 6)) & (radioResult & (1 << 4)) ){
printf("Probably in TX Mode\r\n");
}
if((radioResult & (1 << 5)) ){
printf("Probably in Standby Mode\r\n");
}
if(radioResult == 0xAA){
printf("error...\r\n");
HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_STATUS, &radioResult, 1);
uint8_t result = (radioResult & RADIO_MODE_BITFIELD) >> 4;
uint8_t status = (radioResult & RADIO_STATUS_BITFIELD) >> 1;
printf("Status is: 0x%02x 0x%02x\r\n", result, status);
for(int i = 0; i<8; i++){
radioCmd[i] = 0;
}
HAL_SUBGHZ_ExecGetCmd(&hsubghz, RADIO_GET_ERROR, radioCmd, 4);
printf("Error is: 0x%02x 0x%02x 0x%02x 0x%02x\r\n", radioCmd[0], radioCmd[1], radioCmd[2], radioCmd[3]);
while(1);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
And the output:
Toggle 1
Toggle 2
Toggle 3
Status is: 0xa2
Should be 1 for lora mode: 0x01 0x00
Sync word MSB: 0x00
Sync word MSB: 0x57
TX Pointer: 0x00
RX Pointer: 0x00
Status is: 0x02 0x01
101ms have elapsed, status: 0xaa
Probably in Standby Mode
error...
Status is: 0x02 0x05
Error is: 0x00 0x20 0x0a 0x00
2025-02-03 11:21 AM
Hello @zbaltzer
The only example available for transmission based only on the hal without midleware is the SUBGHZ_Tx_Mode so you can use it as a reference. There is also this tutorial that is not tested on my side but it may be really helpful.
Best Regards.
STTwo-32
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.