STM32WL系列单片机包括基于Semtech SX1261和SX1262收发器的嵌入式Sub-GHz无线电。与SX126x器件一样,Sub-GHz无线电系统由SPI接口、BUSY线和三根中断(IRQ)线控制。唯一的区别在于,由于无线电集成在STM32WL器件中,因此这些信号(在图1中突出显示)会在内部连接到SoC的其他部分。
因此,STM32WL Sub-GHz无线电系统的中断线路与Semtech SX126x收发器相同。也就是说,有十个可启用/禁用并映射到任意三个IRQ线路的中断源。下表描述了这些中断源。
表 1 : Sub-GHz无线电系统中断源(源自RM0453中的表37)
位 | 源 | 描述 | 数据包类型 | 操作 |
---|---|---|---|---|
0 | TxDone | 数据包传输已完成 | LoRa和GFSK | TX |
1 | RxDone | 数据包接收已完成 | LoRa和GFSK | RX |
2 | PreambleDetected | 前导码已检测 | LoRa和GFSK | RX |
3 | SyncDetected | 同步字有效 | GFSK | RX |
4 | HeaderValid | 标头有效 | LoRa | RX |
5 | HeaderErr | 标头CRC错误 | LoRa | RX |
6 | Err | 前导码、同步字、地址、CRC或长度错误 | GFSK | RX |
6 | CrcErr | CRC错误 | LoRa | RX |
7 | CadDone | 频道活动检测已完成 | LoRa | CAD |
本文将使用Sub-GHz PhyMiddleware的低级驱动程序与STM32WL进行接口连接。提供的代码也可以应用于使用完整Middleware(包括高级驱动程序)的应用,但这样做可能并不必需,因为大部分实现细节已经被上层抽象化。有关在STM32WL项目中使用低级Sub-GHz驱动程序的更多信息,请参阅使用STM32WL系列的初级Sub-GHz无线电驱动程序。
以下代码片段演示了利用STM32WL无线电中断的基本过程。第一步(列表1中显示)是将回调函数的指针作为参数传递给驱动程序的初始化例程。每当Sub-GHz无线电系统发出中断时,系统都会执行此回调函数。为了确定中断源(参见表1),此函数必须包含一个RadioIrqMasks_t类型的单个参数,从而允许使用switch语句(或其他条件逻辑)来处理每个单独的中断源。
列表 1 : 设置和实施Sub-GHz无线电回调函数的模板
// Initialize the hardware (SPI bus, TCXO control, RF switch)
SUBGRF_Init(RadioOnDioIrq);
.
.
.
// Callback function - executed once for each (enabled) interrupt issued from sub-GHz radio
void RadioOnDioIrq(RadioIrqMasks_t radioIrq)
{
switch (radioIrq)
{
case IRQ_TX_DONE:
// do something
break;
case IRQ_RX_DONE:
// do something
break;
case IRQ_RX_TX_TIMEOUT:
// do something
break;
case IRQ_CRC_ERROR:
// do something
break;
default:
break;
}
}
为了使Sub-GHz无线电子系统生成中断请求,必须全局启用一个或多个中断源,并将其映射到任一IRQ线路中。如列表2所示,这可以通过调用SUBGRF_SetDioIrqParams()
函数来实现。该函数的第一个参数是全局中断使能掩码,用于启用/禁用指定的中断源。后三个参数是用于单个IRQ线路的掩码,可将中断源映射到相应的线路上。例如,在列表2中,第一个参数全局启用了TxDone、Timeout和RxDone中断。第二个参数用于指示,当TxDone或Timeout中断发生时,IRQ1线路应从低电平变为高电平。类似地,当RxDone中断发生时,IRQ2线路应从低电平变为高电平。在此示例中,没有将中断源映射到IRQ3线路。
列表 2 :启用Sub-GHz无线电系统的中断
SUBGRF_SetDioIrqParams( IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT | IRQ_RX_DONE,
IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT,
IRQ_RX_DONE,
IRQ_RADIO_NONE );
备注:如果同时触发了映射到同一IRQ线路上的多个中断源,则回调函数将被多次调用以处理每个源事件。
然而,除非直接修改Sub-GHz Phy Middleware,否则无法为单个IRQ线路分配单独的回调函数。也就是说,无论触发的中断映射到哪个IRQ线路,系统都会执行相同的回调函数。因此,大多数应用通常只使用IRQ1线路。如果应用必须确定被触发的是哪个IRQ线路,可以使用列表3中提供的代码。该代码采用了一种解决方法,即,将内部IRQ线路变成外部线路,从而允许轮询GPIO IDR(输入数据寄存器)来获取每个线路的状态。有关将内部Sub-GHz无线电信号变成外部线路的详细信息,请参阅将内部STM32WLSub-GHz无线电接口信号映射到GPIO引脚。
列表 3 : 将IRQ[0:2]线路由到GPIO引脚并查看它们的当前状态。
#define GPIO_PIN_RF_IRQ1 GPIO_PIN_3
#define GPIO_PIN_RF_IRQ2 GPIO_PIN_5
#define GPIO_PIN_RF_IRQ3 GPIO_PIN_8
/**************************** Initialization Code *****************************/
// Enable GPIOB Clock
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure RF_{IRQ0, IRQ1, IRQ2} pins
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_RF_IRQ1 | GPIO_PIN_RF_IRQ2 | GPIO_PIN_RF_IRQ3;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_RF_BUSY;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/************ Conditional logic to be placed in callback function *************/
// Check status of each IRQ line
if (READ_BIT(GPIOB->IDR, GPIO_PIN_RF_IRQ1))
{
// IRQ1 line triggered
}
else if (READ_BIT(GPIOB->IDR, GPIO_PIN_RF_IRQ2))
{
// IRQ2 line triggered
}
else if (READ_BIT(GPIOB->IDR, GPIO_PIN_RF_IRQ3))
{
// IRQ3 line triggered
}
在大多数情况下,管理STM32WL系列器件上的Sub-GHz无线电系统中断和与外部射频收发器进行接口连接完全相同。只不过由于无线电控制信号的内部化,略微影响了灵活性。STM32CubeWL MCU封装中提供了几个利用无线电中断的完整示例应用。