第2章 LoRa射频芯片SX1278详解

好,咱们直接进入正题。SX1278这颗芯片,可以说是LoRa技术的灵魂。我做了这么多年物联网项目,用过的射频芯片少说也有十几款,但SX1278给我的印象最深。为什么?因为它把「远距离」和「低功耗」这对矛盾体,硬是给揉到了一起。

今天我就带你把这颗芯片扒开看看。从引脚功能到内部寄存器,从工作模式到SPI通信,咱们一个一个过。

2.1 芯片引脚功能

先看引脚。SX1278是QFN28封装,28个脚,不算多。但每个脚都有讲究。我刚开始用的时候,就因为在DIO2上少接了个上拉电阻,折腾了两天。嗯,这种坑咱们后面再说。

我把关键引脚分成几类,你记一下:

电源与地

  • VDD:主电源,1.8V~3.7V。我习惯用3.3V,稳定。
  • VBAT:电池供电引脚,如果你用电池供电就走这里。
  • VREG:内部稳压器输出,接个1μF电容到地就行。
  • GND:地。别小看它,铺地没铺好,灵敏度直接掉3dB。

射频接口

  • RFI_P / RFI_N:接收差分输入。我建议走差分线,抗干扰好。
  • RFO_LF:低频段发射输出,137MHz~525MHz。
  • RFO_HF:高频段发射输出,862MHz~1020MHz。
我的经验:如果你只用470MHz~510MHz频段(国内LoRa常用),用RFO_LF就够了。匹配网络用LC π型,调试时用网络分析仪看S11,调到-15dB以下才算合格。

数字控制接口

  • NSS:片选,低电平有效。SPI通信时拉低。
  • SCK:SPI时钟,最高10MHz。我一般跑5MHz,稳。
  • MOSI / MISO:数据线,标准SPI四线制。
  • DIO0~DIO5:数字IO,用来输出中断信号。DIO0最常用,映射到TxDone或RxDone。
  • RESET:复位,低电平有效。上电后必须复位一次,否则芯片不干活。
注意:DIO引脚内部没有上拉!我曾经在项目中忘了加外部上拉,结果中断信号一直高电平,MCU死活收不到。排查了整整一天...后来在DIO0上加了个10kΩ上拉到3.3V,问题解决。

2.2 内部寄存器映射

SX1278内部有上百个寄存器,地址从0x00到0x7F。说实话,你不需要全记住。但有几个关键寄存器,你必须烂熟于心。

我整理了一张表,你直接收藏:

地址 寄存器名 功能
0x01 RegOpMode 工作模式选择,最常用的寄存器
0x0D RegFrfMsb 频率设置高位
0x0E RegFrfMid 频率设置中位
0x0F RegFrfLsb 频率设置低位
0x1D RegModemConfig1 调制解调配置1,含带宽和编码率
0x1E RegModemConfig2 调制解调配置2,含扩频因子
0x40 RegDioMapping1 DIO引脚功能映射
0x4C RegHopPeriod 跳频周期设置

频率怎么算?公式很简单:

RF频率 = (RegFrfMsb << 16 | RegFrfMid << 8 | RegFrfLsb) * Fstep
其中 Fstep = 61.035 Hz(晶振32MHz时)

举个例子,我想设到490MHz:

频率值 = 490000000 / 61.035 ≈ 8028160 = 0x7A8000
所以 RegFrfMsb = 0x7A, RegFrfMid = 0x80, RegFrfLsb = 0x00
核心要点:写频率寄存器时,一定要先进入Sleep模式,写完再切回Standby。否则芯片可能不认。我踩过这个坑,代码里加了模式切换后,再也没出过问题。

2.3 工作模式配置

SX1278有6种工作模式,通过RegOpMode寄存器控制。说白了,就是让芯片在不同状态下干活。

  • Sleep(睡眠):功耗最低,~0.2μA。配置寄存器前必须进这个模式。
  • Standby(待机):晶振工作,但射频关闭。~1.6mA。我一般在这里做初始化。
  • FS_TX(频率合成发射):PLL锁定发射频率。很少单独用。
  • FS_RX(频率合成接收):PLL锁定接收频率。也很少单独用。
  • TX(发射):发射数据。电流最大,~120mA@20dBm。
  • RX(接收):接收数据。~12mA。连续接收模式最常用。

模式切换的代码,我习惯这么写:

void SX1278_SetMode(uint8_t mode) {
    uint8_t reg = ReadRegister(REG_OPMODE);
    reg = (reg & 0xF8) | mode;  // 保留高5位,设置低3位
    WriteRegister(REG_OPMODE, reg);
}

你想想看,为什么切换模式时要保留高5位?因为高5位里包含了LoRa/Fsk模式选择位。你要是直接写0,就把LoRa模式给清了。嗯,细节决定成败。

避坑指南:从Sleep切到Standby后,要等晶振稳定。我一般加1ms延时。曾经有同事没加延时,结果频率漂了十几kHz,通信距离直接减半。

2.4 SPI通信协议

SX1278的SPI协议,说简单也简单,说复杂也复杂。标准四线制:NSS、SCK、MOSI、MISO。但有个坑——地址格式。

SPI读写命令是一个字节:

  • 写操作:地址 + 0x00(最高位为0)
  • 读操作:地址 + 0x80(最高位为1)

举个例子,读RegOpMode(地址0x01):

// 伪代码
NSS = 0;                    // 拉低片选
SPI_Write(0x01 | 0x80);     // 发送读命令,0x81
uint8_t val = SPI_Read();   // 读取数据
NSS = 1;                    // 拉高片选

写操作类似:

NSS = 0;
SPI_Write(0x01);            // 写命令,0x01
SPI_Write(0x08);            // 写入数据,比如切到Standby模式
NSS = 1;
注意:SPI时钟空闲时必须是低电平,数据在上升沿采样。这是Mode 0。我见过有人用了Mode 3,结果读回来的数据全是0xFF。查了半天才发现是SPI极性配反了。

还有一个技巧——突发读写。如果你要连续读写多个寄存器,可以保持NSS为低,连续发地址和数据。比如初始化时,我经常用突发写来批量配置:

void SX1278_BurstWrite(uint8_t addr, uint8_t *buf, uint8_t len) {
    NSS = 0;
    SPI_Write(addr);        // 起始地址
    for(uint8_t i = 0; i < len; i++) {
        SPI_Write(buf[i]);  // 连续写数据
    }
    NSS = 1;
}

这样做的好处是快。你想想看,如果每个寄存器都单独拉一次NSS,光片选切换的时间就够你受的。尤其是在实时性要求高的场景,比如跳频通信,突发读写能省下不少时间。

小结

这一章的内容,说白了就是SX1278的「使用说明书」。引脚怎么接,寄存器怎么配,模式怎么切,SPI怎么通信。你把这些搞懂了,后面写驱动就是水到渠成的事。

我个人建议,拿到芯片后先别急着写代码。拿示波器看看SPI波形,确认通信正常。再用逻辑分析仪抓一下DIO中断,看看时序对不对。硬件调通了,软件才有意义。

下一章,咱们开始写LoRa驱动。到时候我会把初始化流程、发送接收的代码,一行一行给你讲清楚。准备好了吗?