【github 有趣项目】通信库 RadioLib简介:早期版本+协议支持+HAL模块+发展历程(LoRa、FSK、OOK 等)
·
简介
- RadioLib 是嵌入式无线通信领域比较流行的一个开源库,主要用于 Arduino / ESP32 / STM32 等微控制器控制各种无线射频模块(如 LoRa、FSK、OOK 等)。它的发展历史其实和开源硬件社区的发展密切相关。下面按时间梳理其主要发展阶段。
- 项目最早由开发者 jgromes 2018 年 3 月 6日创建于 GitHub(下图就是初始提交的内容)。 最初并不是一个通用库,而是为了支持一个硬件项目 RadioShield。由于需要同时驱动不同射频芯片,作者开始开发一个 统一的无线驱动库,这就是 RadioLib 的最初版本。

早期版本
- 早期版本的 RadioLib 主要解决一个核心问题:为不同无线射频芯片提供统一的 API 接口。在当时的 Arduino 社区中,各类无线模块通常使用完全不同的驱动库,例如 LoRa 芯片(SX1276、SX1278)以及 FSK 芯片(RFM69、CC1101)都依赖各自独立的库,接口设计和使用方式差异很大,这给开发者带来了较高的学习成本和代码迁移难度。为了解决这一问题,RadioLib 提出了 “One radio library to rule them all.” 的设计目标,通过统一接口封装不同芯片的底层驱动,使开发者能够用相似的方式控制不同的无线模块。其核心特点包括:提供统一的通信接口、支持多种射频芯片、对 Arduino 平台友好,以及采用 C++ 面向对象的设计结构,从而提高代码的可复用性和可扩展性。

- 同日的第三次提交放入了主要的核心代码,主要实现Arduino C++ 类,用于封装无线模块或外设模块的通信接口,实现对模块的统一管理与控制。同时支持 串口 AT 指令通信和 SPI 寄存器读写两种方式,其中通过
SoftwareSerial实现与模块的串口通信,用于发送 AT 指令并获取模块响应;通过SPI接口实现对射频芯片寄存器的读取和写入,包括单寄存器操作、批量(Burst)读写以及部分位(bit 位)修改等功能。
:
#ifndef _KITELIB_MODULE_H
#define _KITELIB_MODULE_H
#include <SPI.h>
#include <Wire.h>
#include <SoftwareSerial.h>
#include "TypeDef.h"
#define SPI_READ 0b00000000
#define SPI_WRITE 0b10000000
class Module {
public:
Module();
Module(int cs, int tx, int rx, int int0, int int1);
SoftwareSerial* ModuleSerial;
uint32_t baudrate = 9600;
uint8_t init(uint8_t interface, uint8_t gpio);
void ATemptyBuffer();
bool ATgetResponse();
bool ATsendCommand(String& cmd);
bool ATsendCommand(const char* cmd);
uint8_t SPIgetRegValue(uint8_t reg, uint8_t msb = 7, uint8_t lsb = 0);
uint8_t SPIreadRegisterBurst(uint8_t reg, uint8_t numBytes, uint8_t* inBytes);
uint8_t SPIreadRegisterBurstStr(uint8_t reg, uint8_t numBytes, char* str);
uint8_t SPIreadRegister(uint8_t reg);
uint8_t SPIsetRegValue(uint8_t reg, uint8_t value, uint8_t msb = 7, uint8_t lsb = 0);
void SPIwriteRegisterBurst(uint8_t reg, uint8_t* data, uint8_t numBytes);
void SPIwriteRegisterBurstStr(uint8_t reg, const char* data, uint8_t numBytes);
void SPIwriteRegister(uint8_t reg, uint8_t data);
bool getInt0State();
bool getInt1State();
private:
int _cs;
int _tx;
int _rx;
int _int0;
int _int1;
uint32_t _ATtimeout = 15000;
};
#endif
协议
- 随后,RadioLib 进入快速发展阶段,并逐渐成长为 Arduino 无线通信领域中具有重要影响力的开源库。在这一阶段,库的功能不断扩展。首先,在硬件支持方面,RadioLib 新增了对更多射频芯片的支持,例如 SX1262、SX1268、SX1280、LR1110 以及 NRF24 等,使其能够适配更广泛的无线模块。其次,在软件功能方面,RadioLib 不再仅限于提供物理层驱动,而是进一步扩展到协议层,实现了对 LoRaWAN、AX.25、APRS 以及 Pager 等通信协议的支持。此外,库中还加入了多种业余无线电常用的数字通信模式,例如 RTTY(无线电电传)、SSTV(慢扫描电视)以及 Hellschreiber。这些扩展使得 RadioLib 不仅能够完成基础的无线收发功能,还能够支持更复杂的无线通信应用和实验场景。

- HTTP、UDP、MQTT等是最先实现的:

// https://github.com/jgromes/RadioLib/blob/a6b7540508354d470b588c7b408cf7f0203a86a0/src/ESP8266.cpp
uint16_t ESP8266::HttpGet(const char* url, String& response) {
String urlString(url);
// get the host address and endpoint
int32_t resourceIndex = urlString.indexOf("/", 7);
if(resourceIndex == -1) {
return(ERR_URL_MALFORMED);
}
String host = urlString.substring(7, resourceIndex);
String endpoint = urlString.substring(resourceIndex);
// build the GET request
String request = "GET ";
request += endpoint;
request += " HTTP/1.1\r\nHost: ";
request += host;
request += "\r\n\r\n";
// create TCP connection
uint8_t state = startTCP(host.c_str());
if(state != ERR_NONE) {
return(state);
}
// send the GET request
state = send(request);
if(state != ERR_NONE) {
return(state);
}
// read the response
String raw = receive();
// close the TCP connection
state = closeTCP();
if(state != ERR_NONE) {
return(state);
}
// parse the response
int32_t numBytesIndex = raw.indexOf(":");
if(numBytesIndex == -1) {
return(ERR_RESPONSE_MALFORMED_AT);
}
response = raw.substring(numBytesIndex + 1);
// return the HTTP status code
int32_t spaceIndex = response.indexOf(" ");
if(spaceIndex == -1) {
return(ERR_RESPONSE_MALFORMED);
}
String statusString = response.substring(spaceIndex + 1, spaceIndex + 4);
return(statusString.toInt());
}
uint16_t ESP8266::HttpPost(const char* url, String content, String& response, const char* contentType) {
String urlString(url);
String contentTypeString(contentType);
// get the host address and endpoint
int32_t resourceIndex = urlString.indexOf("/", 7);
if(resourceIndex == -1) {
return(ERR_URL_MALFORMED);
}
String host = urlString.substring(7, resourceIndex);
String endpoint = urlString.substring(resourceIndex);
// build the POST request
String request = "POST ";
request += endpoint;
request += " HTTP/1.1\r\nHost: ";
request += host;
request += "\r\nContent-Type: ";
request += contentTypeString;
request += "\r\nContent-length: ";
request += content.length();
request += "\r\n\r\n";
// create TCP connection
uint8_t state = startTCP(host.c_str());
if(state != ERR_NONE) {
return(state);
}
// send the POST request
state = send(request);
if(state != ERR_NONE) {
return(state);
}
// close the TCP connection
state = closeTCP();
if(state != ERR_NONE) {
return(state);
}
// read the response
String raw = receive();
// parse the response
int32_t numBytesIndex = raw.indexOf(":");
if(numBytesIndex == -1) {
return(ERR_RESPONSE_MALFORMED_AT);
}
response = raw.substring(numBytesIndex + 1);
// return the HTTP status code
int32_t spaceIndex = response.indexOf(" ");
if(spaceIndex == -1) {
return(ERR_RESPONSE_MALFORMED);
}
String statusString = response.substring(spaceIndex + 1, spaceIndex + 4);
return(statusString.toInt());
}
HAL
-
为了减少对 Arduino 平台的依赖,RadioLib 在后续发展中引入了 HAL(Hardware Abstraction Layer,硬件抽象层) 机制。通过这一机制,库将底层的硬件操作(如 GPIO 控制和 SPI 通信)进行统一抽象,使其不再直接依赖 Arduino 的硬件接口,从而能够在更多平台上运行。借助 HAL,RadioLib 可以支持 ESP-IDF、STM32 HAL、Raspberry Pi 以及其他标准 C++ 运行环境。这一设计大大提升了库的可移植性,使 RadioLib 从最初主要面向 Arduino 的无线驱动库,逐渐发展为一个 通用的嵌入式无线通信库。
-
RadioLib 包含一个轻量级的硬件抽象层(HAL)类。以下是最常用平台的HAL列表:https://github.com/jgromes/RadioLib/tree/master/src/hal

-
在 RadioLib 中,HAL(Hardware Abstraction Layer,硬件抽象层) 是通过在库内部引入 平台接口类(接口抽象) 的方式逐步加入的,其核心思想是 把所有与具体硬件平台相关的操作从驱动代码中分离出来,让无线芯片驱动只依赖统一的接口,而不是直接调用 Arduino 的函数。

当前
- Radiolib从一个 Arduino LoRa 驱动逐渐发展成支持多芯片、多协议、跨平台的通用无线通信库。,昨天还在更新(20260307):

CG
- 还有更多内容请阅读官方文档,一些其他关键内容会后续添加。
更多推荐

所有评论(0)