ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 Flipper Zero 复现 DCF77 授时信号:flipper-dcf77 源码解析与实战指南

用 Flipper Zero 复现 DCF77 授时信号:flipper-dcf77 源码解析与实战指南 用 Flipper Zero 复现 DCF77 授时信号flipper-dcf77 源码解析与实战指南【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/FlipperFlipper Zero 常见的玩法是收发 433MHz 遥控信号但它的 125kHz 低频 RFID 天线还有另一种冷门玩法——把 Flipper Zero 变成一台 DCF77 长波授时信号发射机用来喂家里的无线电钟电波钟。本文以 flipper-dcf77 这个实验性插件为对象完整讲解它的信号格式、软件定时器基带生成、报文编码实现与实测限制并给出基于源码的引脚、频率与参数依据帮助你理解甚至复刻这一用 Flipper 校准电波钟的玩法。DCF77 是什么为什么电波钟需要它DCF77 是德国法兰克福附近 Mainflingen 的长波授时台工作在 77.5kHz覆盖欧洲大部分地区。它每秒发送一位数据每分钟组成一个 59 位严格说是 60 秒的完整时间帧内容包含分钟、小时、日期、星期、年份以及夏令时、闰秒等辅助信息。电波钟内置长波接收机收到完整一帧后即可校准本地时间。flipper-dcf77 的思路非常直接让 Flipper Zero 的 125kHz LFRFID 天线在 DCF77 的频率上辐射出同样的时间编码信号让附近的电波钟以为收到了授时台信号而自行对表。作者在 README 中直言这是badly勉强实现——因为无论从天线匹配还是定时精度上Flipper 都不是为长波发射设计的但它最终能在我拥有的每一只钟上生效。项目结构与构建配置插件位于仓库的Applications/Official/source-OLDER/xMasterX/flipper-dcf77/目录共 6 个源文件加一个图标文件职责dcf77_app.c应用主入口、定时器状态机、GPIO/射频输出控制、GUI 渲染dcf77_app.h宏定义、AppFSM状态结构体、60 位信号位名表dcf77_util.cset_dcf_message()把日期时间编码成 8 字节 DCF77 报文dcf77_util.h编码函数声明与BBIT取位宏application.famFlipper 应用的构建清单FAP 描述文件README.md作者对实现原理与限制的说明application.fam说明了它如何被编译成 Flipper 应用包FAPApp( appiddcf77, nameDCF77 Transmitter, apptypeFlipperAppType.PLUGIN, entry_pointdcf77_app_main, cdefines[APP_DCF77], requires[gui], stack_size1 * 1024, order10, fap_iconicons/app.png, fap_categoryMisc_Extra, )这是一个 1KB 栈、依赖gui的插件型应用入口函数为dcf77_app_main安装后在 Flipper 的Misc_Extra分类下显示为 DCF77 Transmitter。由于它属于source-OLDER旧版源码存档目录实际运行时需要将该目录下的插件源码放入对应版本的 Flipper 固件源码树中编译为.fap再拷贝到 SD 卡的apps目录运行。发射链路与频率选择关键宏直接决定发射频率dcf77_app.h 中的几个宏是理解整个发射链路的核心#define TIMER_HZ 30 #define TIME_ZERO 24 #define TIME_ONE 27 #define LF_FREQ 77500 * 2 #define OUTPUT_PIN gpio_ext_pc3LF_FREQ 77500 * 2 155000即代码默认在155kHz上发射而不是 DCF77 的标准 77.5kHz。README 解释用原始 77.5kHz 也能发但 155kHz 的传输距离更好OUTPUT_PIN指向gpio_ext_pc3C3 引脚README 明确说明基带信号输出在 C3TIMER_HZ 30是软件定时器频率TIME_ZERO / TIME_ONE是决定 0/1 位脉冲宽度的基带计数值。天线失谐物理层面的妥协发射频率 77.5kHz 对应约 3.87km 波长而 Flipper 的 RFID 天线是按 125kHz 设计的。作者给出的失谐数据是用 125kHz 天线发射 77.5kHz偏离约33%发射 155kHz 二次谐波偏离约20%有人曾用扬声器在 15.5kHz 产生的电磁场成功触发过电波钟接收。正因为慢速信号 不稳定的软件定时器 严重失谐的天线三者叠加README 给出的预期是YMMV效果因人而异。要在仓库内搭建可用的便携式 LF/VLF 天线作者表示留作读者练习。DCF77 信号格式与 ASK 调制DCF77 采用ASK幅移键控调制载波被基带信号按秒切割。flipper-dcf77 在 dcf77_app.h 的结构体注释中定义了基带脉冲宽度// bit0 800ms 16; bit1 900ms 18; bit2 1000ms 20结合 README 可以归纳出它的编码规则信号含义本实现位 0每分钟开始标记第 0 秒载波拉低标记帧起点位值为 00.8 秒的 mark载波开启基带输出约 800ms 后停止位值为 10.9 秒的 mark基带输出约 900ms 后停止第 59 秒结束标记载波持续开启一整秒mark 之间DCF77 标准是载波关闭本实现不关闭载波只是降低功率代码中的get_dcf_message_bit()dcf77_app.c对 bit 59 和 bit 0 直接返回 0把帧边界当作数据位 0 处理而on_timer_tick()则单独判断dt.second 59时强制output true实现第 59 秒载波连续的结束标记。另外 README 明确指出DCF77 还有一种PSK相移键控调制方式用于传输某些附加信息Flipper 只做了 ASK 部分PSK 未实现——这是影响接收成功率的一个已知局限。载波本身的产生方式载波由 Flipper 的 RFID 定时器产生。dcf77_lf_init()中furi_hal_rfid_tim_reset(); furi_hal_gpio_init_simple(gpio_ext_pa7, GpioModeOutputPushPull); furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app_fsm); furi_hal_rfid_pins_read(); furi_hal_rfid_tim_read(freq, 0.5);即把 RFID 读取定时器配置为LF_FREQ155kHz、50% 占空比同时把 PA7 作为比较器触发输出。dcf77_mark()通过furi_hal_rfid_comp_start()与furi_hal_rfid_tim_read_start()启动载波dcf77_space()则调用comp_stop()与tim_read_stop()停止——二者配合 30Hz 定时器用软件开关载波的方式拼出 ASK 波形。软件定时器与基带生成状态机为什么用软件定时器而不是硬件README 透露了实现的核心机制Implementation is using a software kernel timer (furi_timer_start) to generate the signal在app_init()中FuriTimer* timer furi_timer_alloc(timer_tick_callback, FuriTimerTypePeriodic, app_fsm-_event_queue); furi_timer_start(timer, furi_kernel_get_tick_frequency() / TIMER_HZ);定时器以TIMER_HZ 30Hz 周期触发向事件队列投递EventTimerTick主循环取出事件后在FURI_CRITICAL_ENTER/EXIT临界区内调用on_timer_tick()dcf77_app.c保证基带切换不被并发打断。基带计数的实现逻辑on_timer_tick()每 tick 读取 RTC 得到当前秒dt.second并以此作为信号位编号bit_number。当秒数变化时重置baseband_counter 0否则递增。随后按当前位的类型决定是否关闭载波if (app_fsm-baseband_counter TIME_ZERO app_fsm-bit_value 0) output false; else if (app_fsm-baseband_counter TIME_ONE app_fsm-bit_value 1) output false;在 30Hz 的 tick 频率下TIME_ZERO 24tick ≈800ms对应 0 位TIME_ONE 27tick ≈900ms对应 1 位。每次输出状态翻转时set_outputs()同步切换两颗 LEDmark 时红 LED 全亮、绿 LED 微弱亮space 时全部熄灭作为可视指示dcf77_mark()/dcf77_space()与gpio_mark()/gpio_space()同时操作 RFID 载波与 C3 引脚上的基带信号。定时精度的先天不足README 用了不少篇幅交代软件定时器的问题虽然 Flipper 跑的是 FreeRTOS但软件定时器时好时坏30Hz 是实测最佳折中中断太密集会相互重叠、显著延迟中断太少则偶尔漏 tick而漏掉 tick 会让基带脉冲变形更严重因此接收端有时一次成功有时要等 5 次以上——DCF77 一分钟才发一帧一次失败就要再等整整一分钟。这些描述与dcf77_app.h中保留的注释掉的备选值// #define TIME_ZERO 15、// #define TIME_ONE 5相互印证说明作者确实做过多组参数实验。报文编码set_dcf_message 的逐位实现DCF77 一帧共 60 位flipper-dcf77 用 8 字节64 位数组承载set_dcf_message()dcf77_util.c负责把时间字段编码进去函数签名void set_dcf_message(uint8_t* dest, uint8_t minute, uint8_t hour, uint8_t day, uint8_t month, uint8_t year, uint8_t dow, bool dst, bool predst, bool abnormal, bool leap, uint16_t civbits);编码过程分两步1. 二进制转 BCD。DCF77 的分钟、小时、日期、月份、年份都以 BCD 码传输代码用移位与位或完成转换bcd_minute ((minute / 10) 4) | (minute % 10);2. 计算奇偶校验位。分钟、小时、日期各带一个偶校验位代码对 BCD 值的每一位做异或累计。日期校验p_date的计算在源码中写得比较实验性——循环里反复被!!(...)覆盖最后一位生效与 README 自嘲的 Implementation is wonky 风格一致。随后按 DCF77 位序把各字段填进dest[0..7]例如字节 3/4 的位 24–35 对应分钟 BCD 高位、分钟校验位、小时 BCD 与校验位字节 6/7 的位 50–57 对应年份 BCD位 58 是日期校验位。字节 0/1 承载 civil bits通过civbits参数传入字节 2 顶部的位 15–19 则承载predst夏令时切换预告、dst夏令时指示、!dst标准时间指示、leap闰秒指示等状态位。60 位信号的位名对照dcf77_app.h 中的dcf77_bitnames[]数组完整列出了 60 个位的位置含义是理解报文布局的最佳索引位号含义位号含义0Start minute帧起始标记28Minutes P分钟偶校验1–14Civil 1–14民用告警位29–34Hours 1–6小时 BCD15Abnormal异常告警35Hours P小时偶校验16DST change夏令时切换36–41Day 1–6日期 BCD17UTC02夏令时指示42–44Weekday 1/2/4星期18UTC01标准时间指示45–49Month 1–5月份 BCD19Leap sec闰秒预告50–57Year 1–8年份 BCD20Start time时间信息起点58Date P日期偶校验21–27Minutes 1–7分钟 BCD59End结束标记运行界面与 RTC 同步应用启动后通过update_dcf77_message_from_rtc()读取 Flipper 的 RTCfuri_hal_rtc_get_datetime把当前时间写入tx_hour/tx_minute/...并编码进next_message缓冲区随后以双缓冲 原子换入的方式更新待发送报文buffer_swap_pending标志。render_callback()在 128×64 屏幕上实时绘制dcf77_app.c当前待发射时间如17:41 27.12.22当前信号位编号与取值形如2.31该位名称来自dcf77_bitnames[]8 字节报文的十六进制与当前字节的二进制位图并用下划线标出正在发射的位。输入方面方向键目前只记录状态不产生动作OK键会触发一个调试用的计数器复位Back键退出。这也呼应了 README 的 todo菜单尚未实现还谈不上更 Flipper的交互。已知限制与踩坑清单综合 README 与源码实测中需要接受的现实包括成功率不保证每台电波钟最终都能收到但需要等待从 1 次到 5 次以上不等因为一分钟仅一帧定时不准软件定时器在 FreeRTOS 上存在延迟/丢 tick30Hz 是平衡干扰与失真的折中值天线严重失谐125kHz 天线发 77.5kHz 偏 33%发 155kHz 偏 20%发射效率与距离都受限mark 之间并非静默载波只是降功率而非完全关闭这在德国境外很少被察觉但确实不符合标准PSK 未实现只有 ASK 部分依赖 PSK 的接收特性可能失效数据不可配置报文完全来自设备 RTCREADME 提到的模拟编码 25:69 这种非法时间以及按夏令时偏移量调钟都列在 todo 中尚未实现。后续路线来自项目 todoREADME 末尾列出了作者计划的方向也可以作为读者自行扩展的切入点增加菜单让操作更Flipper支持可配置的模拟数据例如故意编码非法时间25:69支持仅作为时区偏移模式方便按各国夏令时习惯批量调整家中电波钟扩展其他长波授时信号RBU俄罗斯 66.67kHz、ALS162英国、WWVB美国 60kHz等。小结flipper-dcf77 是一个典型的用现成硬件做不寻常事的实验项目它以 155kHz 二次谐波驱动 125kHz 天线用 30Hz 软件定时器拼出 DCF77 的 ASK 基带波形用set_dcf_message()完成 BCD 奇偶校验的报文编码并以 C3 引脚输出基带、PA7 输出载波。它的全部细节——频率宏、脉冲宽度、位布局、UI 与限制——都可以在 README.md 与 dcf77_app.c、dcf77_util.c 中逐行核对。理解了这些你不仅能复现它还能在 todo 的方向上继续打磨这套Flipper 版长波授时发射机。【免费下载链接】FlipperPlayground (and dump) of stuff I make or modify for the Flipper Zero项目地址: https://gitcode.com/GitHub_Trending/fl/Flipper创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表