4. LoRa模块初识:SX1278/SX126x芯片介绍、LoRa调制原理、SPI通信协议详解
好,咱们进入第四章节。前面几章我们把物联网网关的骨架搭起来了,也聊了GPS怎么拿位置。但网关的核心——无线通信,还没真正碰。这一章,我们就来啃这块硬骨头:LoRa模块。
说到LoRa,市面上主流的芯片方案就两家:Semtech的SX1278和SX126x系列。我最早接触LoRa时用的是SX1278,后来项目要求低功耗,才切到SX1262。这两兄弟有什么区别?LoRa调制到底是个什么魔法?单片机又是怎么通过SPI跟它们对话的?咱们一个一个拆开看。
4.1 SX1278与SX126x:两代LoRa芯片的对比
先看一张对比表,心里有个底。
| 特性 | SX1278 | SX126x (SX1261/62/68) |
|---|---|---|
| 频率范围 | 137 ~ 525 MHz | 150 ~ 960 MHz |
| 最大发射功率 | +20 dBm (100 mW) | +22 dBm (SX1262, 约158 mW) |
| 接收电流 | 约 12 mA | 约 4.6 mA (超低功耗模式) |
| 调制方式 | LoRa + (G)FSK + OOK | LoRa + (G)FSK + MSK |
| 接口 | SPI | SPI + 可选DIO中断 |
| 内部稳压器 | LDO | LDO + DC-DC (效率更高) |
| 典型应用 | 早期LoRa节点、网关 | 低功耗传感器、新一代网关 |
从表里能看出来,SX126x系列在功耗和集成度上明显更优。我个人习惯是:如果做电池供电的节点,优先选SX1262;如果是网关或者对成本敏感的项目,SX1278依然能打。
4.2 LoRa调制原理:为什么能传那么远?
LoRa这个名字,全称是Long Range,长距离。它凭什么能传几公里甚至十几公里?核心秘密在调制方式上。
传统的FSK(频移键控)调制,是把数据比特直接映射到频率变化上。LoRa不一样,它用的是扩频调制。具体来说,是把一个比特的信息,扩展到多个「啁啾」符号(Chirp)里传输。
你想想看,一个比特本来只需要一个符号就能传完。LoRa把它拆成128个、256个甚至更多的符号。接收端收到这些符号后,通过相关运算把它们「拼」回来。哪怕信号被噪声淹没了,只要符号之间的相关性还在,就能解调出来。
这就是LoRa的杀手锏:扩频增益。
扩频增益的大小,由扩频因子(Spreading Factor, SF)决定。SF值越高,扩得越狠,传输距离越远,但数据速率也越慢。
| 扩频因子 (SF) | 符号速率 (chip/s) | 数据速率 (bps, BW=125kHz) | 接收灵敏度 (典型) |
|---|---|---|---|
| SF7 | 125000 | 约 5470 | -123 dBm |
| SF9 | 125000 | 约 1760 | -129 dBm |
| SF12 | 125000 | 约 293 | -137 dBm |
从SF7到SF12,灵敏度提升了14 dBm。这是什么概念?发射功率每增加3 dBm,距离大约翻一倍。14 dBm的灵敏度提升,相当于把发射功率提高了20多倍。这就是LoRa能传几公里的物理基础。
数据速率 (bps) = SF * (BW / 2^SF) * (4 / (4 + CR))
其中BW是带宽,CR是编码率。SF越大,速率越慢,距离越远。
除了SF,还有两个参数影响通信质量:带宽(BW)和编码率(CR)。带宽越宽,速率越快,但抗干扰能力下降。编码率越高,冗余越多,纠错能力越强,但有效数据变少。
实际项目中,我一般这样配:
- 远距离、低速率场景:SF12, BW=125kHz, CR=4/8
- 中等距离、平衡场景:SF9, BW=250kHz, CR=4/6
- 近距离、高速率场景:SF7, BW=500kHz, CR=4/5
4.3 SPI通信协议详解:单片机怎么跟LoRa模块说话?
LoRa芯片内部有几十个寄存器,控制着频率、功率、调制参数、FIFO缓冲区等。单片机要读写这些寄存器,就得通过SPI接口。
SPI,全称Serial Peripheral Interface,串行外设接口。它用四根线搞定通信:
- SCLK:时钟线,由主机(单片机)产生
- MOSI:主机输出,从机输入
- MISO:主机输入,从机输出
- NSS:片选线,低电平有效
LoRa模块的SPI时序,跟标准SPI略有不同。它要求:
- 时钟极性(CPOL)= 0:空闲时时钟为低电平
- 时钟相位(CPHA)= 0:在第一个时钟沿采样数据
- 数据位序:MSB(最高位)先传输
- 最大时钟频率:SX1278约10 MHz,SX126x约16 MHz
读写寄存器的流程很简单:
- 拉低NSS,选中模块
- 发送一个字节的地址+读写标志位(写操作:地址 | 0x80;读操作:地址 & 0x7F)
- 如果是写操作,紧接着发送数据字节;如果是读操作,接收数据字节
- 拉高NSS,结束通信
看一个实际的写寄存器代码示例:
// 写LoRa寄存器函数
void LoRa_WriteRegister(uint8_t addr, uint8_t data) {
// 拉低片选
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);
// 发送地址(写标志:地址 | 0x80)
SPI_TransmitByte(addr | 0x80);
// 发送数据
SPI_TransmitByte(data);
// 拉高片选
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);
}
// 读LoRa寄存器函数
uint8_t LoRa_ReadRegister(uint8_t addr) {
uint8_t data;
// 拉低片选
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_RESET);
// 发送地址(读标志:地址 & 0x7F)
SPI_TransmitByte(addr & 0x7F);
// 接收数据(发送0xFF作为时钟)
data = SPI_TransmitReceiveByte(0xFF);
// 拉高片选
HAL_GPIO_WritePin(NSS_GPIO_Port, NSS_Pin, GPIO_PIN_SET);
return data;
}
这段代码看起来简单,但有几个坑要注意:
- 片选时序:两次SPI操作之间,NSS必须拉高至少一个时钟周期。我见过有人连续读写时忘了拉高,导致数据错位。
- 读操作时的填充字节:读寄存器时,主机必须发送一个字节(通常是0xFF)来产生时钟,从机才会在MISO上返回数据。
- FIFO操作:LoRa模块内部有个256字节的FIFO缓冲区。读写FIFO时,地址是固定的(SX1278的0x00),连续读写时地址会自动递增。
4.4 知识体系总览:一张图看懂本章核心
下面这张SVG图,把本章的三个核心知识点串起来了。你可以把它当作一个思维导图,快速回顾。
4.5 小结:这一章你该带走什么?
嗯,内容不少,咱们捋一捋重点:
- SX1278和SX126x:两代芯片,选型看功耗和成本。SX126x是未来趋势,但SX1278依然广泛。
- LoRa调制:扩频调制是远距离通信的基石。SF、BW、CR三个参数决定了距离和速率,需要根据场景权衡。
- SPI通信:四根线,时序固定。读写寄存器是基本功,FIFO操作是进阶。时钟频率别超限,片选时序别马虎。