LoRa 之一旧版驱动(sx12xxDrivers-V2.1.0)移植及驱动架构详解
在之前的项目中,一直使用 LoRa 通信。很早之前就想写写文章记录一下学习过程。怎奈一直是一知半解的状态,想写不敢写!LoRa 这个东西在国内用的貌似不是太多。
对于无线通信,各个国家或者地区都有严格的限制。例如,我们国家就有<<*无线电频率划分规定>>。前两年,工信部出了个指导意见还是啥东西来着,差点把 LoRa 搞黄了!LoRa 是工作在免费频段的。关于免费频段各个国家或者地区是有区别的!我们国家的各种规定在工信部官网可以找到!废话不多说,想要了解 LoRa 是啥的自己去搜索,我们重点说用法!
LoRa 和 LoRaWAN
在介绍使用之前,我们必须要先区分好这两个概念!LoRa 是低功耗广域网通信技术中的一种,而按照 LoRa 联盟官方白皮书《what is LoRaWAN》的介绍,LoRaWAN 是为 LoRa 远距离通信网络设计的一套通讯协议和系统架构。类比于我们的网络通信,LoRa 定了物理层,而 LoRaWAN 定义了 MAC 层、数据链路层。LoRaWAN 定义了一套通信系统的架构,底层使用的是 LoRa 通信。这个应该就和我们的网络协议栈差不多吧。
在我们的实际使用中,我们可以仅仅使用 LoRa 进行最基本的通信,通信的应用层协议则有我们自己定义。当然,我们的通信只能和我们自己定义的应用层协议的设备通信。Semtech 出了好几款 LoRa 收发器芯片供我们选择。当然也可以按照 LoRaWAN 的要求来实现系统中的通信,这个就要复杂好多了,完整的 LoRaWAN 网络架构中包含了终端、网关、NS(网络服务器)、应用服务器这四个部分。
当前有好多公司都出了各种各样的 LoRa 模块以及 LoRa 网关模块。我的环境是自己画的 LoRa 模块,使用了的芯片时 SX1276。我这里也不需要 LoRaWAN。
驱动
首先,我们需要知道 Semtech 的 LORA 芯片支持 LORA 模式和 FSK 模式,所以驱动中是包含对这两种模式的处理的。目前,Semtech 官网有两款驱动,一款是旧的驱动,驱动内部只实现了对于 LoRa 芯片的基本操作,另一个款是最新的包含对 LoRa 芯片的基本操作和 LoRaWAN 定义的实现。老版驱动 Semtech 已经停止更新了,也不建议用在新的生成环境中。两种驱动对比如下图:
这里我们重点来介绍一下旧版的驱动。下面来具体说说移植!
驱动架构
驱动的架构并不复杂,如下图所示:
在初始化阶段,驱动内部首先将全部寄存器的值读取到 uint8_t SX1276Regs[0x70];
中,而后所有接口的操作都是按照上面的图,先修改 uint8_t SX1276Regs[0x70];
中的寄存器,然后在通过 SPI 将 uint8_t SX1276Regs[0x70];
中的数据写入到芯片中。我们以 sx1276 为例来说明一下:
-
sx1276.h/c:该文件主要是以上两种模式(LORA、FSK)的统一的对外接口。通过 radio.h 中宏 LORA 是否为 1 区分以上两种模式。此外该文件中还定义了一个与芯片中寄存器一一对应的全局变量
uint8_t SX1276Regs[0x70];
。 - sx1276-LoRaMisc.c/h:该文件主要是提供一些 LORA 参数的设置接口
- sx1276-LoRa.c/h:该文件定义了 LORA 寄存器以及各种寄存器的具体数值、LORA 的初始化及配置,LORA 处理状态机。
下面是对各文件(夹)的一个简单的介绍:
* src
* │ main.c 这其中有个给出了使用方法(初始化、收发数据等),作为参考在自己的项目中使用。!!!知道如何测试后删除即可!!!
* ├─platform
* │ │ platform.h 在此文件中对驱动进行配置。!!!这个必须要保留!!!
* │ ├─bleeper 以下这些平台自己在移植时其实我们就需要其中的某个文件即可。所以所谓的平台对我自己的项目来说根本无用。
* │ ├─stm32libs 其他代码文件都是一些针对测试开发版的文件,我们不需要。
* │ ├─sx1200dvk 因为,我们自己的项目中必然有自己的实现。
* │ ├─sx1243ska 其实,最终我们就需要其中一个文件:xxx-Hal.c(根据自己的芯片类型)
* │ └─sx12xxEiger <- 这里以它为例,我们只需要以下文件,其他平台(以上俩目录)的文件和该目录下类似。!!!都不需要使用,直接删除即可!!!
* │ │ sx1232-Hal.c
* │ │ sx1272-Hal.c
* │ │ sx1276-Hal.c 我们仅需要自己选择的芯片对应的硬件抽象层文件,根据自己的MCU修改里面的代码(各GPIO、函数中的SPI接口)即可。!! 函数名不能更改!!
* └─radio 这个是 LORA的驱动源码,针对每个不同信号芯片的不同调制模式都有独立文件。!!!必须根据自己的LoRa芯片选择对应文件。!!!
* radio.c 对于不同LORA芯片的部分操作接口的封装。这两文件非常简单。
* radio.h
* !!-----这里省略其他文件,其他文件与以下文件类似。以sx1276来进行说明------!!
* sx1276-Fsk.c Fsk模式的源码文件,主要就是对Fsk模式下各寄存器的读写函数
* sx1276-Fsk.h
* sx1276-FskMisc.c Fsk模式的参数配置函数
* sx1276-FskMisc.h
* sx1276-Hal.h 硬件抽象层对应的头文件,对应的.c文件在platform目录下,这俩文件主要就是初始化LORA使用的GPIO及SPI通信。函数在.h文件中以给出。只需要根据自己的平台实现.c文件即可。
* sx1276-LoRa.c LoRa 模式的源码文件,主要就是LORA模式下各寄存器的读写函数。注意:LoRa模式下可以读取Fsk模式的寄存器。
* sx1276-LoRa.h
* sx1276-LoRaMisc.c LoRa 模式的参数配置函数,用户可以直接使用该文件的中的函数对LoRa进行配置(例如频率、带款等等)。
* sx1276-LoRaMisc.h
* sx1276.c 主要是以上两种模式(LORA、FSK)的统一的对外接口。通过 radio.h 中宏 LORA 是否为 1 区分以上两种模式
* sx1276.h
驱动文件整理
移植的第一步就是整理源码文件。旧源代码在使用 Ride 7 作为 IDE(Ride 7 使用 gcc-arm 作为编译器)写出来的,所以在源码中有些 Ride 7 的文件。下面我们整理一下需要的驱动文件:
配置
移植的第二步就是修改驱动的配置项!
platform.h
由于源码实际是一个 Ride 7 项目示例,同时针对多个测试平台(开发板)的,因此配置文件中有一些和测试平台相关的代码。我习惯于不再代码中残留一些无用的代码,所以该清理的清理。清理后如下:
/*!
* Radio choice. Please uncomment the wanted radio and comment the others
* or add/change wanted radio definition on the compiler Defines option
* 这里其实就是选择使用的 LORA 芯片型号,我们使用的是 SX1278,其与SX1276基本一样。Semtech 给出的驱动源码中,SX1278 可以直接使用 SX1276 的驱动源码。
* 后面也会看到,所有驱动文件的名字均为 SX1276 开头的文件名,却没有一个是 SX1278 开头的文件。具体原因也是这里所说的原因。
* 但是,需要对源码进行一定的修改,具体修改见下面的说明!
*/
//#define USE_SX1232_RADIO
//#define USE_SX1272_RADIO
#define USE_SX1276_RADIO
//#define USE_SX1243_RADIO
/*!
* Module choice. There are three existing module with the SX1276.
* Please set the connected module to the value 1 and set the others to 0
* 这个模块选择:这里主要是指Semtech官方给出的不同的外围电路设计用例。因为其给出的三种电路设计中,使用的芯片引脚等时有区别的。
* 因此,这里需要根据硬件设计。来选择合适的模块。以下三种硬件电路设计用例,可直接在Semtech官网找到!
* 以下几个宏值,仅在调用初始化时才会用到,具体可查看函数void SX1276LoRaInit( void );这里也需要注意:频率的问题,源码对于不同频率,
* 其会选择不同的配置。
*/
#ifdef USE_SX1276_RADIO
#define MODULE_SX1276RF1IAS 0
#define MODULE_SX1276RF1JAS 0
#define MODULE_SX1276RF1KAS 1
#endif
整理之后,就上面两个宏值是必须的!对于每个宏上面的注释已经很详细了,不再多说!
sx1276-Hal.c
这个文件看名字就知道,负责实现驱动库与实际芯片的通信的封装。如果看源码中的示例文件,会发现其中也是很多和测试平台相关的配置。同样该清理的清理,最终该文件大体可以分为两大部分:
- 包含自己需要的头文件
- 实现必须的函数接口。函数接口总的可以分为四大类:
-
LORA 芯片使用 MCU 的 IO 的配置及复位。函数
void SX1276InitIo(void)
用来初始化使用的各 IO。函数void SX1276SetReset( uint8_t state )
用来复位模块。 -
SPI 通信使用的接口。LORA 芯片是使用 SPI 进行通信的。
void SX1276Write( uint8_t addr, uint8_t data );
void SX1276Read(uint8_t addr, uint8_t *data)
void SX1276WriteBuffer(uint8_t addr, uint8_t *buffer, uint8_t size)
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
void SX1276WriteFifo( uint8_t *buffer, uint8_t size )
void SX1276ReadFifo( uint8_t *buffer, uint8_t size )
我们只需要根据自己的 SPI 的配置,修改
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
和void SX1276WriteBuffer(uint8_t addr, uint8_t *buffer, uint8_t size)
即可,其他几个接口都是直接调用上面这俩接口的!不知道为啥驱动库要放出这么多函数。 -
LORA 芯片 独立 IO 的配置。LORA 芯片有几个 IO 是需要直接和 MCU 相连的,这些 IO 的高低状态指示了 LORA 芯片的一些工作状态。
inline uint8_t SX1276ReadDio0( void )
inline uint8_t SX1276ReadDio1( void )
inline uint8_t SX1276ReadDio2( void )
inline uint8_t SX1276ReadDio3( void )
inline uint8_t SX1276ReadDio4( void )
inline uint8_t SX1276ReadDio5( void )
需要注意的是,根据我们的需求,以上 5 个 IO 并不一定全部使用。例如我的就只使用 DIO0、DIO1、DIO3。至于如果选择,在手册中有说明这 5 个 IO 的说明。
-
天线切换接口。
inline void SX1276WriteRxTx( uint8_t txEnable )
。在 Semtech 给出的设计原理图中,是需要进行天线状态的切换的!如果是买的其他厂家的现成的模块,可能不需要该函数,留空即可!
-
sx1276-Hal.h
还是由于驱动测试遗留的问题,我们必须要修改该文件中的部分代码。清理一些测试过程中引入的文件,同时定义一个函数函数。具体如下:
这个文件如果设计的足够好的话,是不需要用户来更改的!
至此,LORA 的驱动移植完成了,接下来就是在自己的开发环境中添加使用的文件、头文件路径,然后编译即可!
使用
驱动库通过 radio.h/c
对驱动库的接口进行了封装。正常的初始化、收发数据等都是使用 tRadioDriver
中的函数指针。当然,该结构体仅仅是封装了部分接口。有些功能接口我们还是需要直接使用对应驱动库头文件中的函数。
- 首先调用初始化驱动库
- 周期调用
Radio->Process()
以处理驱动库的状态机
- 收发数据
Radio->GetRxPacket( const void *buffer, uint16_t size );
和Radio->SetTxPacket( const void *buffer, uint16_t size );
注意
- 只有 LORA 参数都一致的情况下,两者才能通信!
- 默然情况下,LORA 驱动内部是开启了低速率优化的。
参考
本文地址:https://blog.csdn.net/ZCShouCSDN/article/details/110183620