
简介这份资源是面向嵌入式开发者的LT8920 2.4G无线模块测试程序基于STM8微控制器实现适合初学者入门2.4G无线通信也可作为有经验开发者的参考资料。压缩包共62个文件约825KB包含8个c源文件与8个h头文件如LT8920.c、spi.c、main.c、delay.c等驱动与应用代码、12个o目标文件、13个cout编译输出文件以及IAR工程配置ewp、ewd、eww、dep等和hex烧录文件结构完整可直接在IDE中打开运行。目前已有1056人学习下载。通过分析其中的驱动代码读者可掌握LT8920的初始化、参数配置与收发函数实现应用代码展示了数据打包解包与错误处理机制配合STM8的SPI、定时器与中断配置能快速理解GFSK调制下的通信流程。开发者还可基于此修改数据帧格式、调整发射功率与接收灵敏度适配不同短距离无线场景是学习2.4G无线通信与STM8编程的实用起点。1. 从一块吃灰的 LT8920 模块说起这套 STM8 测试程序到底能跑通什么手头有几片 LT8920 的 2.4G 模块丝印模糊引脚定义查不到卖家给的资料只有一张模糊的方框图——这种场景做硬件的应该都不陌生。LT8920 是一颗工作在 2.4GHz ISM 频段的射频收发芯片支持 GFSK 调制通过 SPI 接口跟主控通信常见于无线键鼠、遥控器、短距数据采集这类低速率场景。它便宜、外围简单但寄存器手册写得相当克制很多配置项只给了一个位定义具体该填什么值全靠试。这套基于 STM8 的测试程序解决的就是“模块到手之后怎么确认它能收发”这个问题。它把 LT8920 的初始化、寄存器配置、发送和接收流程都封装成了可调用的函数主控用的是 STM8S103 这类常见的小资源 MCU编译环境是 IAR 或 SDCC 都能凑合。适合两类人一是手里有 LT8920 模块但不确定好坏、想先点亮的硬件工程师二是想用 STM8 做低功耗无线节点、需要一份能跑的底层驱动做起点的人。下面按“先搞清楚它在干什么 → 怎么把工程跑起来 → 怎么改参数适配自己的板子 → 踩过哪些坑”的顺序拆一遍。2. LT8920 的 SPI 时序与寄存器配置测试程序里到底写了什么2.1 先看通信层SPI 模式 0 和那根被忽略的 CSNLT8920 的 SPI 接口不是标准四线 SPI 的简化版它有自己的脾气。测试程序里对 SPI 的初始化集中在LT8920_SPI_Init()这个函数核心是三点时钟极性 CPOL0、时钟相位 CPHA0、片选 CSN 由软件控制而不是硬件 NSS。很多 STM8 的 SPI 例程默认用硬件 NSS接上 LT8920 之后发现寄存器读出来全是 0xFF 或者 0x00八成就是这里翻的车。// STM8S103 SPI 初始化针对 LT8920 void LT8920_SPI_Init(void) { // 1. 配置 SCK 和 MOSI 为推挽输出MISO 为浮空输入 PB_DDR | (1 5) | (1 6); // SCK(PB5), MOSI(PB6) 输出 PB_CR1 | (1 5) | (1 6); // 推挽 PB_DDR ~(1 7); // MISO(PB7) 输入 PB_CR1 ~(1 7); // 浮空 // 2. CSN 用普通 GPIO 控制初始拉高 PC_DDR | (1 3); // CSN(PC3) 输出 PC_CR1 | (1 3); LT8920_CSN_HIGH(); // 3. SPI 配置主模式CPOL0, CPHA0, 时钟 fmaster/4 SPI_CR1 0x04; // MSTR1, CPOL0, CPHA0, 分频 4 SPI_CR2 0x03; // SSM1, SSI1软件从机管理 SPI_CR1 | 0x40; // SPE1使能 SPI }这段代码里最容易被忽略的是SPI_CR2 0x03。STM8 的 SPI 在主机模式下如果 SSM 位不置 1一旦 NSS 引脚被外部拉低SPI 会直接退出主模式表现就是发出去的数据没反应。LT8920 的 CSN 又必须由软件单独控制所以 SSM 和 SSI 都得置位把硬件 NSS 彻底旁路掉。时钟分频选了 4对应 STM8S103 在 16MHz 主频下 SCK 约 4MHzLT8920 的 SPI 最高支持 10MHz这个速率留了余量走线长一点也稳。2.2 寄存器读写地址的 bit7 是方向位LT8920 的寄存器操作跟很多射频芯片不一样它没有单独的读命令和写命令而是用地址的最高位区分方向bit70 表示写bit71 表示读。测试程序里封装了两个函数// 写寄存器addr 为 7 位地址value 为 8 位数据 void LT8920_WriteReg(uint8_t addr, uint8_t value) { LT8920_CSN_LOW(); SPI_WriteByte(addr 0x7F); // bit70写方向 SPI_WriteByte(value); LT8920_CSN_HIGH(); } // 读寄存器返回 8 位数据 uint8_t LT8920_ReadReg(uint8_t addr) { uint8_t val; LT8920_CSN_LOW(); SPI_WriteByte(addr | 0x80); // bit71读方向 val SPI_ReadByte(); // 读回数据 LT8920_CSN_HIGH(); return val; }注意读操作里SPI_ReadByte()之前没有额外的空写。有些 SPI 从机需要先发一个 dummy byte 才能读出数据LT8920 不需要它在地址字节的最后一个时钟沿之后就把数据推到 MISO 上了。如果你用的主控 SPI 外设带 FIFO 或者有固定的收发时序这里可能要调一下但 STM8 的 SPI 是单字节缓冲直接读就行。2.3 初始化序列那几个不能改的魔数测试程序里LT8920_Init()函数有一串看起来毫无规律的寄存器写入这些值是从手册的推荐配置和实际抓包对比里凑出来的。挑几个关键的寄存器地址写入值作用能不能改0x000x6F使能内部晶振和 PLL不能改了不工作0x010x56设置频段和信道间隔可改影响频点0x020x1E配置数据速率和调制方式可改影响速率0x030x0F设置发射功率可改影响距离0x040x9C使能 CRC 和自动应答按需改0x050x20设置地址宽度按需改0x060x00清状态标志每次发完要清0x00 那个 0x6F 是血泪经验——手册上写的是“保留”实际不写这个值晶振起不来SPI 读出来全是 0。0x01 和 0x02 决定了射频参数后面调距离和速率的时候主要动这两个。0x03 的发射功率有 4 档0x0F 是最大但电流也最大电池供电的场景要往下调。3. 把工程跑起来从编译到第一包数据的完整步骤3.1 工程文件结构和编译选项测试程序的文件不多但组织方式决定了你移植的时候要动哪里。目录结构大概是LT8920_STM8_Test/ ├── main.c // 主循环发送和接收的调度 ├── lt8920.c // 驱动层SPI 读写和初始化 ├── lt8920.h // 寄存器地址定义和函数声明 ├── stm8s_conf.h // STM8 标准外设库配置 ├── stm8s_it.c // 中断服务函数 └── Project/ └── IAR/ // IAR 工程文件如果你用 IAR直接打开Project/IAR/下的.eww文件就能编译。用 SDCC 的话需要自己写 Makefile核心是加上-lstm8 -mstm8和头文件路径。编译选项里有一个要注意优化等级建议用-O1或 IAR 的Low不要开最高优化。LT8920 的 SPI 时序对延时敏感高优化可能把LT8920_CSN_LOW()和SPI_WriteByte()之间的空操作优化掉导致 CSN 建立时间不够读出来数据错位。3.2 主循环里的发送和接收main.c的结构很直白初始化之后进一个大循环按键触发发送中断接收void main(void) { CLK_Init(); // 时钟初始化16MHz LT8920_SPI_Init(); // SPI 初始化 LT8920_Init(); // LT8920 寄存器初始化 UART_Init(9600); // 串口用于打印调试信息 while (1) { if (KEY_Read() 0) // 按键按下 { uint8_t tx_buf[4] {0xAA, 0xBB, 0xCC, 0xDD}; LT8920_TxPacket(tx_buf, 4); printf(TX done\r\n); } if (LT8920_RxAvailable()) // 收到数据 { uint8_t rx_buf[32]; uint8_t len LT8920_RxPacket(rx_buf); printf(RX %d bytes: , len); for (uint8_t i 0; i len; i) printf(%02X , rx_buf[i]); printf(\r\n); } } }发送函数LT8920_TxPacket()内部做了三件事写 TX FIFO、触发发送、等发送完成标志。接收部分用的是轮询LT8920_RxAvailable()没有用中断因为测试程序追求的是逻辑清晰不是实时性。实际产品里建议改成中断方式LT8920 的 GIO1 引脚可以配置成接收中断输出接在 STM8 的 EXTI 上。3.3 用串口确认第一包数据烧录之后打开串口助手波特率 9600。按一下按键应该看到TX done。如果手头有第二块模块和另一块 STM8 板子烧同样的程序按其中一块的按键另一块的串口应该打印出RX 4 bytes: AA BB CC DD。这一步跑通说明 SPI 通信、寄存器配置、射频收发的基本链路都对了。如果只有一块模块也有办法验证发送是否正常把 LT8920 配置成单载波发射模式用频谱仪或者带 2.4G 接收的 SDR 看有没有载波出来。测试程序里没有直接提供这个模式但可以手动改寄存器 0x02 的值把调制关掉只发载波。这个操作有风险发射前确认天线接好不然可能烧功放。4. 参数怎么调频点、速率、功率和地址的适配方法4.1 频点设置0x01 寄存器的位域拆解LT8920 的频点由寄存器 0x01 和 0x02 共同决定但 0x01 是主频段选择。测试程序默认写的 0x56 对应 2.400GHz 附近的某个信道。如果你要改到别的频点需要按手册的公式算Freq 2400 (reg01_val - 0x50) * 2 (MHz)比如写 0x50 就是 2400MHz写 0x5A 就是 2420MHz。但注意不是所有值都能用LT8920 的 PLL 在 2400~2483MHz 之间比较稳超出这个范围锁定时间会变长甚至失锁。改完频点之后收发双方必须写一样的值不然就是各说各话。4.2 数据速率0x02 寄存器里的取舍0x02 寄存器控制数据速率测试程序默认 0x1E 对应 250kbps。这个速率在近距离10 米内很稳但距离一拉远误码率就上来了。如果要降速增加距离可以改成 0x0E 对应 50kbps或者 0x06 对应 10kbps。降速的代价是空中传输时间变长同样一包数据耗电更多。电池供电的传感器节点一般选 10kbps 或 50kbps遥控器这种要求响应快的选 250kbps。改速率的时候有一个隐藏坑速率变了接收端的带宽滤波也要跟着调。LT8920 的接收带宽由另一个寄存器控制测试程序里没有暴露出来默认是跟 250kbps 匹配的。如果你只改了速率没改带宽接收灵敏度会掉 10dB 以上。常见做法是速率降一档带宽也降一档具体对应关系查手册的接收带宽表。4.3 发射功率0x03 寄存器的四档和电流关系0x03 的低四位控制发射功率测试程序写 0x0F 是最大档。实测在 3.3V 供电下四档的电流大概是寄存器值功率档位发射电流典型空旷距离250kbps0x00最低12mA10 米0x05中低18mA25 米0x0A中高26mA50 米0x0F最高35mA80 米这些数字是模块配 PCB 天线测的换天线会差很多。如果发现通信距离远低于预期先确认 0x03 写对了没有再检查天线匹配。LT8920 的差分射频输出需要巴伦或者 LC 匹配网络直接接一根导线当天线距离会缩到几米。4.4 地址过滤0x04 和 0x05 的配合测试程序里 0x04 写了 0x9C使能了 CRC 和自动应答0x05 写了 0x20 设置地址宽度为 4 字节。这意味着发送的时候前 4 个字节会被当作目标地址接收端只有地址匹配才会收。如果你不需要地址过滤把 0x04 的对应位清掉0x05 写 0x00就变成广播模式所有模块都能收到。地址过滤在多点通信里很有用但调试的时候容易把自己绕进去。常见情况是发送端地址写的是 A接收端地址写的是 B然后两边都以为对方没发。建议调试阶段先关掉地址过滤确认链路通了再打开。5. 避坑与排查LT8920 调试中最容易翻车的五个地方5.1 现象SPI 读寄存器全返回 0x00 或 0xFF原因CSN 时序不对或者 SPI 模式配错。LT8920 要求 CSN 拉低之后至少等 1 个时钟周期再发第一个 SCK 沿STM8 在 16MHz 下跑LT8920_CSN_LOW()之后直接调SPI_WriteByte()可能太快。另外 CPOL/CPHA 如果配成模式 3数据采样沿反了读出来就是全 1 或全 0。解决在 CSN 拉低之后加一个__no_operation()或者几个空循环。确认 SPI_CR1 的 CPOL 和 CPHA 位都是 0。用示波器看 SCK 和 MOSI 的相位关系第一个 SCK 上升沿应该对应 MOSI 上地址字节的最高位。5.2 现象初始化之后读 0x00 寄存器返回值不是 0x6F原因晶振没起振或者电源纹波太大。LT8920 的内部 PLL 对电源敏感如果 3.3V 上有超过 50mV 的纹波PLL 可能锁不住。另外晶振的负载电容如果选错起振时间会变长初始化之后立刻读寄存器可能读到默认值。解决在 VDD 引脚旁边加 100nF 和 10uF 电容越近越好。初始化之后加 10ms 延时再读寄存器。如果还是不对换一个晶振试试LT8920 常见配 16MHz 晶振负载电容 12pF 左右。5.3 现象能发送但接收不到或者接收距离极短原因收发频点不一致或者接收端的带宽配置跟发送速率不匹配。测试程序默认的 0x01 和 0x02 值只保证自己跟自己通如果你改了一边的频点没改另一边或者改了速率没改带宽就会出现“发送正常但收不到”。解决先把两边都恢复成测试程序的默认值确认能通。然后每次只改一个参数改完立刻测。频点、速率、带宽这三个参数是绑定的改一个就要检查另外两个。5.4 现象通信一段时间后死机复位才能恢复原因SPI 读写没有加超时LT8920 在某些状态下会把 MISO 拉低不放STM8 的 SPI 如果配置成硬件 NSS 模式会一直等主循环卡死。另外如果用了中断接收中断里调用了printf串口输出阻塞也会导致看门狗复位。解决SPI 读写函数里加超时计数超过一定次数直接返回错误。中断服务函数里只做标志位设置和数据搬运打印放到主循环。看门狗建议开但喂狗周期要大于最长的 SPI 操作时间。5.5 现象两块板子靠近时通信正常拉开几米就断原因天线匹配没做好或者发射功率档位太低。LT8920 的差分输出阻抗是 100 欧姆左右直接接单端天线需要巴伦转换。很多模块为了省成本用 LC 匹配代替巴伦匹配没调好的话发射效率可能只有 10%。解决先用 0x0F 最大功率档测距离如果还是只有几米基本就是天线问题。检查模块上的匹配元件常见的是两个电感和两个电容组成的巴伦。没有网络分析仪的话用频谱仪看发射频谱中心频点应该干净谐波抑制至少 20dB。6. 进阶用法用 LT8920 做低功耗无线节点的一个具体技巧测试程序跑通之后下一步通常是想把它改成电池供电的无线节点。这里有一个很具体的技巧利用 LT8920 的 WORWake-On-Radio模式做周期性唤醒配合 STM8 的 HALT 模式把平均电流压到微安级。WOR 模式的核心是让 LT8920 自己周期性地醒来监听前导码收到有效前导码再通过 GIO 引脚唤醒 MCU。测试程序里没有实现这个但寄存器层面是支持的。具体做法是配置 0x04 寄存器的 WOR 使能位设置 0x07 和 0x08 寄存器定义唤醒周期然后把 STM8 配成外部中断唤醒中断源接 LT8920 的 GIO1。// 配置 LT8920 WOR 模式周期约 100ms void LT8920_EnableWOR(void) { LT8920_WriteReg(0x04, 0x9C | 0x20); // 使能 WOR LT8920_WriteReg(0x07, 0x64); // 唤醒周期高字节 LT8920_WriteReg(0x08, 0x00); // 唤醒周期低字节 LT8920_WriteReg(0x09, 0x01); // GIO1 映射为 WOR 唤醒输出 } // STM8 进入 HALT 模式等 GIO1 下降沿唤醒 void MCU_EnterHalt(void) { EXTI_CR1 | 0x02; // PB 口下降沿触发 __asm(halt); // 进入 HALT }这个配置下LT8920 大部分时间在睡眠每 100ms 醒来监听一小段前导码没收到就继续睡。STM8 在 HALT 模式下电流约 1uALT8920 在 WOR 模式下平均电流约 20uA加起来不到 25uA。一节 200mAh 的纽扣电池能撑大半年。但这里有一个坑WOR 模式的唤醒周期和发送端的前导码长度必须匹配。如果发送端前导码太短接收端刚好在睡眠周期里就漏掉了。常见做法是发送端前导码长度至少是接收端唤醒周期的两倍。比如接收端 100ms 醒一次发送端前导码要发 200ms 以上。这个参数在 0x02 寄存器的高四位里调测试程序默认值可能不够需要自己算。从那以后我每次调 LT8920 的低功耗模式都会先用示波器抓 GIO1 的波形确认唤醒周期跟预期一致再测整机电流。这个习惯帮我省了很多次“以为配好了其实没睡下去”的返工。希望帮到你。本文还有配套的精品资源点击获取