
简介面向LoRa物联网开发者的SX126x系列驱动源码包覆盖SX1261、SX1262与SX1268三款芯片适用于远距离低功耗无线传输适合有C语言和嵌入式基础、想快速上手新一代LoRa芯片的开发者。资源共611个文件以328个h头文件、261个c源文件为主体另含少量s汇编文件、uvprojx工程文件及stm32系列HAL驱动文件压缩包整体约3.64MB便于在STM32平台直接查阅和移植。包内包含Cad_Example相关示例演示信道活动检测CAD配置与调用可判断信道空闲、降低数据碰撞概率开发者可据此编写自己的驱动代码。已有2374人学习下载内容覆盖芯片初始化、收发数据、状态管理及频率、功率、扩频因子、编码率等核心参数配置结合HAL库能快速完成硬件适配为远距离IoT节点、传感数据回传等应用提供完整参考。1. 为什么 SX126x 值得单独维护一套驱动从选型到链路的三个理由手里同时压着 SX1262 和 SX1268 两颗 LoRa 芯片驱动却散在三个工程里每次换板都要重抠寄存器——这是做数传和中继的人常有的狼狈。SX126x 和上一代 SX1276 相比命令模型、状态机、睡眠行为差异都不小旧驱动直接搬过来会在 BUSY 处理、TCXO 时序、射频开关这几处翻车。这套 sx126x 驱动源码按 SX1262/SX1268 的 LoRa 收发链路组织SPI 底层、命令封装、缓冲区管理、TX/RX 状态切换都对齐了手册命令集。适合做低功耗数传、LoRaWAN 节点或网关中继的固件工程师也适合从 SX127x 迁移过来的开发者——照它移植省去挨个查手册的时间。2. 驱动底层SPI 状态机、BUSY 等待与 DIO 引脚映射SX126x 对外接口几乎全部走命令opcode 参数不像 SX1276 那样大量暴露寄存器地址。判断一份驱动源码好不好用先看 SPI 读写函数和 BUSY 处理写得规不规范。这一层写扎实了上层频率、调制、封包配置才有讨论的意义。2.1 SPI 读写与 BUSY 等待每条命令前的必经关卡SX126x 有一根 BUSY 引脚芯片在“执行上一条命令”期间会把 BUSY 拉高命令处理完再拉低。手册要求发命令前必须先等 BUSY 为低命令发出后芯片开始处理时 BUSY 会再次拉高处理完恢复。这个引脚不处理好第一发命令就会卡死而且这种卡死不是偶发是必现。/* 等待 BUSY 拉低带超时保护超时强制复位芯片 */ static void sx126x_wait_busy( void ) { uint32_t timeout 0; while( gpio_read( GPIO_BUSY ) 1 ) { if( timeout 20000 ) { /* 玄学场景BUSY 卡死多半是前面命令参数给错直接复位最省事 */ sx126x_reset( ); return; } delay_us( 1 ); } } /* 写一条命令opcode 参数NSS 低电平时钟送出 */ static void sx126x_write_cmd( uint8_t opcode, const uint8_t* args, uint8_t len ) { sx126x_wait_busy( ); nss_set_low( ); spi_write_byte( opcode ); if( len 0 ) { spi_write_bytes( args, len ); } nss_set_high( ); sx126x_wait_busy( ); }wait_busy 实际要调两次发命令前一次保证芯片空闲能接收新命令发完再等一次保证命令已经内部执行完紧接着读状态不会读到旧值。超时计数 20000 次约 20ms链路正常时 BUSY 一般在几百微秒内就拉低超过 2ms 就要怀疑 SPI 时钟极性配错或者晶振没起来。SPI 模式必须用 Mode 0CPOL0, CPHA0时钟建议 8MHz 起步我一般保守压在 8MHz有些评估板标称能跑 16MHz实际长线缆连探头时 16MHz 会偶发错位。2.2 DIO1/DIO2/DIO3 的分工与初始化顺序DIO1 是中断输出TX_DONE、RX_DONE、CAD_DETECTED 都从这里出来DIO2 在多数公版上接射频开关TX/RX 通路切换DIO3 接 TCXO 供电使能。三个引脚的复用功能可以在驱动里配置但初始化顺序有讲究调错一步就是收不到包或者烧后级。void sx126x_init_hw( void ) { uint8_t arg; /* 复位低电平保持 5ms足够覆盖手册 100us 的下限 */ reset_set_low( ); delay_ms( 5 ); reset_set_high( ); sx126x_wait_busy( ); arg 0x00; /* STDBY_RC */ sx126x_write_cmd( 0x80, arg, 1 ); /* SetStandby */ /* SetDIO3AsTCXOCtrl0x97 电压档(1B) 超时(2B) */ sx126x_write_tcxo_ctrl( TCXO_CTRL_3V0, 3000 ); arg 0x01; sx126x_write_cmd( 0x9D, arg, 1 ); /* DIO2 作射频开关控制 */ arg 0x7F; /* 所有模块 */ sx126x_write_cmd( 0x89, arg, 1 ); /* Calibrate */ } static void sx126x_write_tcxo_ctrl( uint8_t volt, uint16_t timeout ) { uint8_t args[3]; args[0] volt; args[1] ( timeout 8 ) 0xFF; args[2] timeout 0xFF; sx126x_write_cmd( 0x97, args, 3 ); }顺序为什么不能乱TCXO 的供电由 DIO3 给出如果先 Calibrate 再开 TCXO芯片校准期间没有稳定时钟校准结果会偏移表象是频率偏差大、收包成功率低。DIO2 控制射频开关的配置要在发射之前设好否则 TX 时开关还在 RX 通路功率出不去甚至反射打坏 PA。我在两个项目里都吃过这个亏后来强制把 TCXO → Calibrate → RF switch 写死在 init业务代码不许绕过。另外 DIO1 对应中断源不是默认全开的初始化末尾要用 SetDIO1IRQParams0x08把 RX_DONE、TX_DONE、TIMEOUT 映射到 DIO1这一步漏了后面中断永远不来。3. 参数配置链频率字、调制参数与封包缓冲区的三步走3.1 频率与调制参数从 Hz 到寄存器值的换算SX126x 的频率字是 24 位由 32MHz 晶振换算公式是 freq_word 频率 × 2^25 / 32MHz。很多移植代码直接照搬 SX1276 的写法用 61.035 之类的整数因子近似在 470MHz 频段会偏出几十 kHz收包率立刻难看。uint32_t sx126x_freq_word( uint32_t freq_hz ) { /* 注意用 64 位中间量32 位平台直接左移会溢出 */ return (uint32_t)( ( (uint64_t)freq_hz 25 ) / 32000000UL ); } void sx126x_set_frequency( uint32_t freq_hz ) { uint8_t args[4]; uint32_t fw sx126x_freq_word( freq_hz ); args[0] ( fw 16 ) 0xFF; args[1] ( fw 8 ) 0xFF; args[2] fw 0xFF; args[3] 0; /* 保留字节必须写 0 */ sx126x_write_cmd( 0x86, args, 4 ); /* SetRfFrequency */ }SetRfFrequency0x86第四字节是保留位必须填 024 位频率字按大端拆成三个字节。SX1268 工作在 410~810MHzSX1262 覆盖 150MHz~960MHz超出频段芯片不会报错但性能曲线很难看——这是“参数看起来对了距离就是不对”的常见来源。调制参数 SetModulationParams0x8B共 4 个字节SF、带宽、编码率、LDRO对应关系如下表。参数常用取值说明SF7~12扩频因子越大速率越低、灵敏度越高SF6 有额外限制不建议用BW 寄存器值0x07125k0x08250k0x09500k与 SF 组合决定空中速率CR0x014/5 … 0x044/8纠错开销越大抗干扰越强LDRO0 或 1SF≥11 且 BW≤125k 时强制为 1void sx126x_set_lora_modulation( uint8_t sf, uint8_t bw_reg, uint8_t cr, uint8_t ldro ) { uint8_t args[4]; args[0] sf; /* 7~12 */ args[1] bw_reg; /* 0x07 / 0x08 / 0x09 */ args[2] cr; /* 0x01 ~ 0x04 */ args[3] ldro ? 1 : 0; sx126x_write_cmd( 0x8B, args, 4 ); }LDROLow Data Rate Optimization是最容易漏的参数SF≥11 且带宽 ≤125kHz 时一个 LoRa 符号时长接近甚至超过解调窗口LDRO 不置 1 就会丢符号。有人把 SF12/BW125 的板子调到丢包率奇高查到最后是 LDRO 没写。这个规则在移植时经常被当成“可选优化”其实是必选项。3.2 封包参数与缓冲区写数据前先把基址定好SetPacketParams0x8C六个字节前导码 2 字节、header 类型、payload 长度、CRC、IQ。void sx126x_set_lora_packet( uint16_t preamble, uint8_t header_type, /* 0可变长 1固定长 */ uint8_t payload_len, uint8_t crc_on, uint8_t invert_iq ) { uint8_t args[6]; args[0] ( preamble 8 ) 0xFF; args[1] preamble 0xFF; args[2] header_type; args[3] payload_len; args[4] crc_on ? 1 : 0; args[5] invert_iq ? 1 : 0; sx126x_write_cmd( 0x8C, args, 6 ); }坑在缓冲区。SX126x 内部 RAM 有两个指针TX base 和 RX base默认都是 0x00。每次收发前必须先 SetBufferBaseAddress0x8F把读写偏移指对再 WriteBuffer0x0E写数据最后 SetTx/SetRx 启动。顺序错一步发出去的包是空白或杂质。void sx126x_send( uint8_t* data, uint8_t len ) { uint8_t base[2] { 0x00, 0x00 }; uint8_t tmo[3] { 0x00, 0x00, 0x00 }; /* 1. 收发基址都指到 0 */ sx126x_write_cmd( 0x8F, base, 2 ); /* 2. WriteBuffer 必须是同一次 NSS 低电平内完成的事务 */ nss_set_low( ); spi_write_byte( 0x0E ); /* WriteBuffer */ spi_write_byte( 0x00 ); /* offset */ spi_write_bytes( data, len ); /* 有效载荷 */ nss_set_high( ); sx126x_wait_busy( ); /* 3. SetTxtimeout0 表示不启用超时收尾靠 DIO1 的 TX_DONE */ sx126x_write_cmd( 0x83, tmo, 3 ); }这里最容易写错WriteBuffer 不能拆成两条 SPI 事务offset 必须紧跟 opcode、data 在前同一个 NSS 周期送完。有人先发 WriteBuffer 空命令、再单独写数据NSS 一拉高芯片就认为事务结束数据全丢。RX 侧同理DIO1 中断来之后先 GetRxBufferStatus0x13读出 payloadLength 和 payloadStartOffset再用 ReadBuffer0x1E取数顺序反了读出来的是错位数据。4. 常见问题排查五个踩过的坑与解决记录4.1 现象收包 CRC 全部失败但 RSSI 正常信号强度看着没问题就是收不上来。原因多半在两处同步字不对LoRa 私网同步字要写 0x1424LoRaWAN 是 0x3444混用会导致解调器直接丢包或者两端 invertIQ 配置反了。解决先用寄存器 0x0740/0x0741 核对同步字再确认收发两端 IQ 配置一致最后才动硬件。调试顺序一定是先软件后硬件别一上来就改匹配电路。4.2 现象第一条命令就卡在 BUSY 等不到拉低发 SetStandby 就死等。原因常见SPI 极性配错用了 Mode 1/2/3芯片根本没收到正确命令或复位脉冲太短或晶振没起振。解决先量 BUSY 电平若持续为高用示波器抓 NSS、SCLK、MOSI 确认 Mode 0 相位复位低电平保持 5ms 再释放释放后等 BUSY 拉低再发命令。我上一次翻车就是把复位脚极性搞反波形看着有脉冲芯片其实一直在复位状态。4.3 现象发射电流异常高或射频开关没切换TX 时整机电流比预期高一截或者对端收不到。原因大多是 DIO2 没配置成射频开关控制或 PA 参数按错了芯片型号。SX1261 和 SX1262 的 PA 配置不一样SX1262 上到 22dBm 要用 paDutyCycle0x04、hpMax0x07、deviceSel0x00、paLut0x01 这组搭配SX1261 最大 15dBm参数完全不同。解决先 SetDIO2AsRfSwitchCtrl(1)再按型号查 SetPaConfig 推荐值同时把 OCP过流保护寄存器按发射功率设好否则要么烧片要么限流掉功率。4.4 现象睡眠唤醒后第一包正常第二包开始错乱SetSleep 之后唤醒第一包还能通后面越来越差。原因睡眠配置选了冷启动sleepConfig0x00RAM 被清零频率字、调制参数全部丢失唤醒后没重新 init等于拿错误配置在跑。解决用 Warm Start——SetSleep 配置写 0x02保留配置不使能 RTC 唤醒或 0x03保留配置RTC 唤醒。唤醒后补一条 SetStandby 再走业务。注意 NSS 拉低唤醒后至少延时 1ms 再送 SPI 时钟给芯片留足起振时间。4.5 现象DIO1 中断一直不来或触发了却读不到数据RX_DONE 没反应。原因DIO1 对应中断源没设置SX126x 中断不是默认全开的必须先 SetDIO1IRQParams0x08把 RX_DONE、TX_DONE、TIMEOUT 映射到 DIO1另外收完包必须 ClearIrqStatus0x02不清的话下一包中断可能被吞。解决初始化时执行 SetDIO1IRQParams中断服务里读 GetIrqStatus0x12判断事件处理完立即 ClearIrqStatus。有人把这三个命令漏成两个现象就是“偶发丢包”非常难查。5. 进阶验证用回环计数与 RSSI 读数验证驱动完整性驱动移植完第一件事不是接网关而是两块板对测。我的验收套路固定三步。第一步A 板连续发射每包发累加计数和固定填充B 板用 SetRx 连续模式timeout0xFFFFFF挂着收连续跑 5 分钟看计数是否连续、CRC 是否全过。这一步能同时暴露频率偏差、LDRO 漏配、同步字不一致三个问题。第二步读 GetPacketStatus0x14里的 RSSI 和 SNR和同频段同速率下的已知板卡对比差 5dB 以上基本是频率字算错或前端匹配没到位。第三步验证睡眠Warm Start 配置下进睡眠用 RTC 定时唤醒醒来读配置是否还在再用电流钳测睡眠电流SX126x 系列睡眠电流在微安级如果测到几百 µA多半是 DIO2/DIO3 外设没关或复位脚悬空。CAD 也值得顺手验证。做 LBT先听后发时用 SetCadParams0x88配好检测门限DIO1 上 CAD_DETECTED 中断检测到信道忙就退避。检测门限是个经验值建议从 -10dB 起步在真实环境里用频谱仪校准一次代码里写死即可代价是 CAD 期间不进睡眠功耗预算要留出这部分。从那以后我每次移植完 SX1262 或 SX1268 驱动都强制走一遍这三步再进业务联调宁可多花半小时测板也不让玄学问题拖着整个项目。希望帮到你。本文还有配套的精品资源点击获取