目录
1 前言
本章介绍SetTx和SetRx的使用方法,以及在使用时需要注意的点。Semtech的各个系列的transceiver使用大体相同,本章以SX126x为例展开介绍。
根据datasheet介绍,TX有两种模式,一种是TX single mode,一种是TX timeout mode。而RX有三种模式,有RX single mode、RX timeout mode和RX continuous mode。
注:有需要datasheet的可以去Semtech官网搜索即可,如SX1268。
2 TX mode
TX mode即是radio的发射模式,此寄存器的作用就是发包,下图为datasheet的截图。
其中timeout的值是指SX126x内部RC时钟的tick值,SX126x内部RC使用的是64kHz,而LR11xx内部RC使用的是32.768kHz,SX128x稍有不同,有兴趣的可以看看手册,在手册中也称为RTC。
但在写代码的时候并不需要自己去计算,因为官方driver已经封装好函数,使用者只需要传入毫秒(ms)值,函数会自己计算所需的tick值,如下图,为SX126x官方driver的函数封装。
#define SX126X_RTC_FREQ_IN_HZ 64000UL
uint32_t sx126x_convert_timeout_in_ms_to_rtc_step( uint32_t timeout_in_ms )
{
return ( uint32_t )( timeout_in_ms * ( SX126X_RTC_FREQ_IN_HZ / 1000 ) );
}
sx126x_status_t sx126x_set_tx( const void* context, const uint32_t timeout_in_ms )
{
if( timeout_in_ms > SX126X_MAX_TIMEOUT_IN_MS )
{
return SX126X_STATUS_UNKNOWN_VALUE;
}
const uint32_t timeout_in_rtc_step = sx126x_convert_timeout_in_ms_to_rtc_step( timeout_in_ms );
return sx126x_set_tx_with_timeout_in_rtc_step( context, timeout_in_rtc_step );
}
sx126x_status_t sx126x_set_tx_with_timeout_in_rtc_step( const void* context, const uint32_t timeout_in_rtc_step )
{
const uint8_t buf[SX126X_SIZE_SET_TX] = {
SX126X_SET_TX,
( uint8_t )( timeout_in_rtc_step >> 16 ),
( uint8_t )( timeout_in_rtc_step >> 8 ),
( uint8_t )( timeout_in_rtc_step >> 0 ),
};
return ( sx126x_status_t ) sx126x_hal_write( context, buf, SX126X_SIZE_SET_TX, 0, 0 );
}
2.1 SetTx的single mode
single mode也就是单次发送模式,从执行SetTx指令开始一直在TX模式,直到本包发送完,退回到STBY_RC模式,产生TX_DONE中断。那TX模式到底会持续多久呢?基本上就是本次发包的TOA(Time of arrive)时间。
设置single模式也很简单,将timeout的值设置为0即可,这种模式是最常用的也是推荐的。
sx126x_set_tx( context, 0 );
2.2 SetTx的Timeout模式
datasheet上解释使用timeout模式是为了更安全,如下图,但我认为只要代码逻辑上不出问题就不用使用timeout模式,而且官方的各个SDK代码的example中也没有使用。
如果想用这个模式,设置的timeout的值需要大于本包所用的TOA时间(经实验,timeout值等于TOA时间也行,但为了安全起见,稍微大几毫秒为好)。如果是小于,则会出现在发包过程中产生timeout中断,让radio从TX回到STBT_RC模式,导致本包发送失败。
3 RX mode
RX mode是指接收模式,下图为datasheet的截图。
RX的三种模式解释如下图:
以下为SX126x driver中的程序片段。
sx126x_status_t sx126x_set_rx( const void* context, const uint32_t timeout_in_ms )
{
if( timeout_in_ms > SX126X_MAX_TIMEOUT_IN_MS )
{
return SX126X_STATUS_UNKNOWN_VALUE;
}
const uint32_t timeout_in_rtc_step = sx126x_convert_timeout_in_ms_to_rtc_step( timeout_in_ms );
return sx126x_set_rx_with_timeout_in_rtc_step( context, timeout_in_rtc_step );
}
sx126x_status_t sx126x_set_rx_with_timeout_in_rtc_step( const void* context, const uint32_t timeout_in_rtc_step )
{
const uint8_t buf[SX126X_SIZE_SET_RX] = {
SX126X_SET_RX,
( uint8_t )( timeout_in_rtc_step >> 16 ),
( uint8_t )( timeout_in_rtc_step >> 8 ),
( uint8_t )( timeout_in_rtc_step >> 0 ),
};
return ( sx126x_status_t ) sx126x_hal_write( context, buf, SX126X_SIZE_SET_RX, 0, 0 );
}
3.1 SetRx的single mode
根据datasheet的解释,single mode会一直让radio处于RX模式,直到接收到一个包,产生RX Done,然后自动回到STBY_RC模式。将timeout值设置为0即可设置为single mode。
sx126x_set_rx( context, 0 );
3.2 SetRx的Timeout模式
同样,timeuot模式就是设定一个时间值,时间到仍然没有接收到包就退出RX回到STBY_RC模式,并产生timeout中断。Timeout的解释与TX一样,driver里同样已经封装成毫秒(ms)单位。比如要设置一个100ms的timeout:
sx126x_set_rx( context, 100 );
3.3 SetRx的continuous模式
continuous模式,也就是持续接收模式,radio会一直待在RX模式,直到host主动发送命令改变radio模式。与其他两种模式的区别是,continuous模式下,radio收到包后不会退出RX回到STBY_RC,它会一直在RX模式。
设置RX的continuous模式,需要将timeout的tick值设置为0xFFFFFF,但由上边的sx126x_set_rx()
函数封装可知,此函数传入的参数是毫秒值,并非tick值。所以需要使用函数sx126x_convert_timeout_in_ms_to_rtc_step()
进行设置。
正确的方式如下程序所示:
#define SX126X_RX_CONTINUOUS 0x00FFFFFF
sx126x_set_rx_with_timeout_in_rtc_step( context, SX126X_RX_CONTINUOUS );
另外一点需要注意的是在continuous模式下,读取payload buffer时,地址是自增长的,而single和timeout模式地址指针每次都会自动回到0,如下图手册解释:
所以应该先使用GetRxBufferStatus
寄存器读出上一包的data起始地址,使用寄存器如下图:
程序说明如下:
sx126x_rx_buffer_status_t rx_buffer_status;
sx126x_get_rx_buffer_status( context, &rx_buffer_status );
//sx126x_read_buffer( context, 0, buffer, rx_buffer_status.pld_len_in_bytes );
sx126x_read_buffer( context, rx_buffer_status.buffer_start_pointer, buffer, rx_buffer_status.pld_len_in_bytes );
当然,这种写法同样对single和timeout模式有效,只不过是每次读出rx_buffer_status.buffer_start_pointer
的值都是0而已。
4 小结
- 如没有特殊需求,SetTx只使用single模式即可。
- RX的三种模式都很常用,但使用continuous模式时需要注意上边提到的特殊用法。