1. 从“小毛病”到“大麻烦”:为什么我们需要CANable 2.5固件?
如果你玩过CAN总线,大概率听说过或者用过CANable这款小巧又便宜的USB转CAN适配器。它凭借开源和亲民的价格,成为了很多工程师、学生和爱好者的“瑞士军刀”。我自己也用它调试过不少车载ECU和工业设备,确实方便。但用久了,特别是开始接触CAN FD这种高速应用后,原版固件的一些“小毛病”就开始让人头疼了。
最典型的就是那个让人哭笑不得的“DFU幽灵”问题。你有没有遇到过,电脑重启一下,或者USB线稍微碰松了点,你的CANable就“变砖”了——红灯常亮,设备管理器里显示一个DFU设备,再也连不上CAN总线了?这不是你的操作失误,而是原版硬件设计的一个“先天缺陷”。它把处理器的CAN接收引脚(CAN RX)和启动模式引脚(BOOT0)复用了。一旦上电时这个引脚被意外拉高(比如CAN总线上的干扰,或者USB供电的瞬间波动),STM32就会直接进入固件更新模式,罢工给你看。想恢复?得拔掉USB线等上好几秒,等板子上的电容放完电才行。这在需要长时间稳定运行的测试环境里,简直是灾难。
这还只是硬件层面的“坑”。软件层面,原版固件的问题更多。比如,你想用它跑CAN FD?官方Candlelight固件压根没实现这个功能。你想设置一个精确的采样点来保证高速通信的稳定性?抱歉,旧版固件提供的选项非常有限,计算还不准。你的CAN总线出了错,数据发不出去?旧版Slcan固件像个“哑巴”,没有任何错误报告,你只能对着屏幕干瞪眼,不知道问题出在波特率、接线还是别的什么地方。更别提那低效的USB数据传输了,Slcan协议用ASCII字符传数据,发一个字节的CAN数据,USB得传两个字节,带宽浪费了一半,根本喂不饱高速的CAN FD总线。
所以,当我在实际项目中,从简单的CAN 2.0B诊断升级到需要处理大量数据的CAN FD通信时,原版CANable固件就成了瓶颈。它就像一个只能跑省道的老卡车,突然要它上高速公路,不仅跑不快,还动不动就抛锚。这时候,CANable 2.5固件的出现,就像给这辆老卡车换上了一套全新的动力总成和电控系统。它不仅仅是一次简单的Bug修复,更是一次针对专业CAN FD应用场景的深度优化和功能增强。接下来,我们就一层层剥开这个新固件,看看它到底是怎么从根源上解决这些老毛病,并变身成为一个可靠的专业工具的。
2. 固件“心脏”移植:Slcan与Candlelight的合二为一
在旧版时代,CANable用户通常面临一个选择:是用简单但慢的Slcan,还是用理论上更快但问题多多的Candlelight?这有点像选手机操作系统,一个开放但简陋,一个功能强但兼容性差。CANable 2.5固件做了一件很聪明的事:它把这两个原本独立的“心脏”移植到了一起,共用一套健壮的“血液循环系统”(代码库)。
2.1 协议双雄:效率与兼容性的抉择
我们先来快速回顾一下这两位“前辈”。Slcan协议最大的特点就是简单。它把CANable虚拟成一个串口(COM口),所有通信指令和数据都用ASCII字符发送。比如你想发送一个CAN ID为0x123,数据为0xAA 0xBB的数据包,你只需要通过串口发送字符串t1232AABB\r\n就行了。这种文本协议对人类友好,调试起来直观,用个串口助手就能玩起来,所以特别适合新手入门和快速验证。
但是,这种简单的代价是巨大的效率损失。每一个字节的CAN数据,都需要用两个十六进制ASCII字符来表示。再加上帧头、回车换行符,实际USB传输的数据量翻倍还不止。在CAN FD动辄几兆波特率、一帧数据64字节的场景下,USB 12 Mbps的带宽很快就会被这种低效协议塞满,导致数据堵塞、丢包。我实测过,在500kbps的传统CAN下,Slcan还能勉强应付;一旦切换到2Mbps以上的CAN FD,数据更新率就明显跟不上,用于实时数据采集或模拟节点根本不行。
而Candlelight协议走的是另一条路:二进制协议。它通过WinUSB直接与设备通信,数据打包得严丝合缝,没有冗余的字符开销,理论上能榨干USB的带宽。这才是应对高速CAN FD的正解。然而,官方提供的Candlelight固件一直是个“半成品”,对CAN FD的支持缺失,Windows驱动安装更是玄学,很多电脑死活认不出来,社区里求助无门,最后大家只能退回Slcan。
CANable 2.5固件带来的ElmüSoft Candlelight 2.5协议,终于补上了这块短板。它不仅是第一个为STM32G431完整实现Candlelight协议的固件,还引入了一种全新的、更高效的二进制协议格式。我对比了一下数据传输效率,同样发送一帧29位ID、16字节数据的CAN FD帧,旧版Slcan需要传输44字节,效率只有48%;而新的Candlelight 2.5协议只需要23字节,效率高达91%!这意味着在同样的USB带宽下,你能传输几乎多一倍的数据量,这对于需要高吞吐量的应用(如ECU标定、总线日志记录)是质的飞跃。
2.2 合二为一的架构优势
那么,把Slcan和Candlelight合并有什么好处呢?首先,核心功能模块得到了统一和强化。比如CAN控制器的初始化、波特率计算、错误处理、LED状态指示、DFU进入流程这些底层驱动,现在只用维护一套代码。这套代码经过了更严格的测试和优化,稳定性和可靠性比过去两个各自为政的版本要好得多。
其次,新功能可以同时惠及两个协议。比如后面会详细讲的完善的错误报告机制、精确的采样点设置、总线负载计算,无论是通过Slcan的ASCII命令还是Candlelight的二进制接口,你都能享受到。开发者不用再为两个协议分别实现和维护相同的功能。
最重要的是,它保留了最大的兼容性。新的Candlelight 2.5固件100%向下兼容旧的Candlelight协议。这意味着,如果你有旧的、基于官方Candlelight协议写的测试软件,理论上可以直接用新固件,无需修改。同时,新的Slcan协议也完全兼容旧的Slcan指令集。这种平滑的升级路径,对于已经部署了测试系统的用户来说非常友好,他们可以先升级固件获得稳定性和新硬件支持,再逐步迁移到更高效的新协议上。
从我自己的使用体验来看,这种“二合一”的设计非常务实。在开发初期或者快速调试时,我依然可以用Slcan协议,通过简单的Python脚本或者串口工具快速发送指令,验证硬件连接和基本通信。当进入正式的、需要高性能的测试阶段时,再切换到Candlelight协议,用C++或C#编写高效的上位机软件,确保数据完整性和实时性。一套硬件,两种用法,无缝切换。
3. 根治硬件“顽疾”:BOOT0引脚误触发的软件手术
让我们回到开头那个最恼人的问题:CANable动不动就“变砖”进入DFU模式。这个问题根源在于硬件设计上,STM32的BOOT0引脚和CAN RX引脚是同一个。在正常的电路设计中,BOOT0引脚应该通过一个明确的跳线帽或者开关来控制,决定芯片是从系统存储器(DFU模式)还是用户闪存(正常模式)启动。但在CANable V2.0上,这个引脚直接连到了CAN收发器上。
原版设计用了两个晶体管(Q1和Q2)来延迟给CAN收发器供电,试图确保在处理器上电复位时,CAN RX(也就是BOOT0)引脚是低电平。但这个设计并不完美。当USB供电出现任何微小的中断——比如你碰了一下线、电脑睡眠后唤醒、甚至主板USB端口供电不稳——导致5V电压有一个短暂的跌落再恢复,这个延迟电路就可能失效。此时CAN RX线如果被总线上的其他节点拉高,或者处于隐性状态(通常为高电平),就会在处理器复位的瞬间,让BOOT0引脚处于高电平,从而直接跳进DFU模式。
CANable 2.5固件提供了一个非常巧妙的软件解决方案来根治这个硬件缺陷:禁用BOOT0引脚功能。这个功能集成在配套的HUD ECU Hacker软件的固件更新程序里。在烧录固件时,你可以看到一个“Disable Pin Boot0”的按钮。点击它,固件会通过DFU接口,修改STM32的“选项字节”(Option Bytes)。
选项字节是STM32芯片内部一块特殊的存储区,用来配置芯片的一些底层行为,比如写保护、读保护、以及——最重要的——BOOT0引脚的有效性。通过编程选项字节,你可以告诉芯片:“忽略硬件BOOT0引脚的状态,永远从用户闪存启动”。这样一来,无论CAN RX线上是什么电平,芯片都不会再进入DFU模式了,彻底杜绝了因电源抖动导致的“幽灵”DFU问题。
那如果我真的需要进入DFU模式更新固件怎么办?别担心,新固件想得更周到。它新增了一条软件DFU进入命令。无论是通过Slcan协议发送“*DFU\r”指令,还是通过Candlelight协议发送特定的控制请求,都可以让固件在完成当前操作后,主动地、可控地重新启用BOOT0引脚并跳转到系统存储器。这个过程有300毫秒的延迟,确保命令能成功反馈给主机,然后再执行跳转,比硬件那种“猝死式”的进入方式要优雅和可靠得多。
我亲自测试了这个功能。在禁用BOOT0引脚后,我反复插拔USB线、快速重启电脑,甚至故意去晃动USB接口,CANable都稳稳地正常启动,蓝绿色LED交替闪烁,再也没有出现过红灯常亮的“砖头”状态。当需要升级时,通过HUD ECU Hacker软件一点击“Enter DFU mode”,设备立刻进入刷机状态,整个过程非常顺畅。这个修复,对于需要将CANable集成到产品中、或者部署在无人值守的测试台上的用户来说,价值巨大,它把硬件的一个不稳定因素,通过软件彻底消除了。
4. 迈向专业级:CAN FD应用的核心优化
如果说修复硬件缺陷是“治病”,那么对CAN FD的深度支持就是“强身”。CANable 2.5固件在面向专业CAN FD应用方面做了大量扎实的优化,让这个几十块钱的小板子,真正具备了应对严苛工业现场和汽车电子测试的能力。
4.1 时钟与采样点:高速通信的基石
CAN FD(Flexible Data-rate)相比传统CAN,最大的特点就是数据段可以切换到更高的波特率(比如5Mbps, 8Mbps甚至10Mbps)。但高速带来了更严格的时序要求,其中采样点的设置至关重要。采样点是指在一个比特位时间内,控制器读取总线电平的时刻。设置得太早,信号可能还没稳定;设置得太晚,留给同步调整的余地就小了。在CAN FD中,采样点还决定了波特率切换(BRS位)发生的精确时刻,如果设置错误,直接后果就是总线错误,通信失败。
旧版固件在这里做得非常粗糙。首先,它们使用的CAN时钟频率是170MHz。这个频率很尴尬,因为它无法精确地导出一些常见的波特率和采样点组合。比如你想要一个经典的500kbps波特率、87.5%采样点,或者2Mbps、75%采样点,用170MHz时钟算出来的参数可能不是整数,导致实际波特率有偏差。其次,旧版固件(尤其是Slcan)只提供了寥寥几种预定义的波特率选项(如S0-S9,Y0-Y8),采样点更是固定死的,完全无法满足真实CAN FD网络中多样化的参数配置需求。
CANable 2.5固件对此进行了彻底改造。第一,它将核心时钟频率从170MHz改为了160MHz。160MHz是一个“友好”得多的频率,它可以被许多常见的波特率整数整除,更容易计算出精确的预分频器、时间段1(Seg1)和时间段2(Seg2)参数,从而得到准确的波特率和采样点。
第二,它开放了底层参数的直接配置接口。对于Slcan协议,除了传统的“S”和“Y”命令,新增了“s”和“y”命令。后者允许你直接输入预分频器、Seg1、Seg2和同步跳转宽度(SJW)这四个核心参数。格式像这样:s4,69,10,7\r来设置标称波特率,y4,9,10,7\r来设置数据波特率。这给了开发者最大的灵活性。
第三,也是最重要的,固件内部加入了强大的校验和反馈机制。当你通过主机软件(如HUD ECU Hacker)设置波特率和采样点时,软件会将计算出的参数发送给固件。固件会自己重新计算一遍,并返回一个调试信息,比如:
Nominal: 500k baud, 87.5%; Data: 2M baud, 75.0%; Perfect match: Yes“Perfect match: Yes”这个提示太有用了!它告诉你,为标称段和数据段计算出的预分频器值是相同的,这是意法半导体推荐的最佳实践,可以确保在BRS位切换波特率时没有相位偏移,时序最稳定。如果匹配不上,它会警告你。这个功能帮我避免了好几次因参数计算不当导致的隐性通信故障。HUD ECU Hacker软件更是内置了智能算法,你只需要输入想要的波特率和采样点百分比,它会自动帮你计算出最优、最稳定的参数组合,完全不用自己啃手册算数学。
4.2 从“哑巴”到“话痨”:全方位的错误报告机制
调试CAN总线,最怕的就是“静默失败”。旧版Slcan固件在这一点上简直是“灾难”——它没有任何错误报告。发送失败?没反应。波特率设错了?连不上,但不知道为啥。总线关闭了?设备直接“装死”。你只能靠猜,或者接个示波器、逻辑分析仪去看波形,效率极低。
CANable 2.5固件在这方面做了史诗级的增强,建立了一套分层级、防轰炸的智能错误报告系统。无论是Slcan还是Candlelight协议,都能将总线和设备状态清晰地反馈给上位机。
对于CAN总线错误,固件能精确报告错误状态(总线活动、警告级别、总线被动、总线关闭)和错误类型(位填充错误、格式错误、ACK未收到、隐性/显性位错误、CRC错误)。更贴心的是它的报告策略:第一个错误立即报告,让你快速感知问题。100毫秒后,如果错误状态发生变化(比如从警告变成被动),再报告一次。之后,如果同样的错误持续存在,则改为每3秒报告一次。这种设计完美避免了旧版Candlelight固件可能发生的“错误风暴”——在总线持续错误时,疯狂向上位机发送海量相同的错误帧,把USB带宽和CPU都拖垮。
除了总线错误,命令执行错误也有了明确的反馈。在Slcan协议中,启用反馈模式(MF\r)后,任何指令执行成功会返回#\r,失败则有具体的错误码,比如#3\r表示适配器未打开,#8\r表示总线已关闭。这让你写的控制脚本非常健壮,可以准确判断每步操作的结果。
在实际使用中,这个功能帮我快速定位了一个棘手的干扰问题。当时我的CANable在一条长距离总线上偶尔会通信中断,旧版固件下毫无头绪。换成2.5固件后,错误报告立刻显示“Bus Passive, Bit stuffing error”。这提示我总线物理层有问题,可能是阻抗不匹配或干扰。顺着这个线索检查,最终发现是一段屏蔽层破损的电缆引入了噪声。没有明确的错误指向,这种问题排查起来就像大海捞针。
4.3 效率与可靠性:USB传输与数据处理的革新
专业应用不仅要求功能强大,更要求稳定高效。CANable 2.5固件在数据传输的“管道”上也做了大量优化。
首先是USB传输效率的极致优化。前面提到了新的ElmüSoft协议将CAN FD帧的传输开销降到了最低。此外,固件还修复了旧版Candlelight一个严重的Bug:当USB传输的数据包大小正好是64字节(USB全速端点的最大包大小)时,数据格式会出错。新固件彻底解决了这个问题,保证了任何大小数据包传输的可靠性。
其次是双缓冲区和智能流控。旧版Candlelight固件只使用一个共享缓冲区来处理CAN接收和发送,这在缓冲区溢出时会导致连错误状态都无法上报的窘境。新固件采用了分离的缓冲区,并实现了更好的流控机制。当CAN发送缓冲区满(例如,连续发送67个数据包都未收到ACK)时,固件会通过错误报告(#7\r)通知主机,而不是盲目地丢弃数据或崩溃。
第三是引入了“发送回波标记”机制。在旧协议中,主机发送一个数据包后,固件会立刻把一个完整的数据包副本(Tx Echo)通过USB发回来,作为“已发送”的确认。但这很浪费带宽,而且这个回波只代表“固件收到了”,不代表“总线发送成功了”。新固件改变了做法:主机在发送数据包时,可以附带一个1字节的标记(0-255)。只有当这个数据包真正成功发送到CAN总线并被确认后,固件才会将一个只包含该标记的简短事件发回主机。主机只需要维护一个很小的标记-数据包映射表,就能精确知道哪个数据包在什么时间发送成功了。这对于需要高可靠性和精确时序的单次传输模式(禁用自动重传)尤其重要。
最后是总线负载计算。固件可以实时计算CAN总线的负载率,并以可配置的间隔(比如每5秒)报告给主机。这对于监控网络健康状况、评估系统余量非常有用。虽然计算存在一定误差(约±10%),但足以反映总线的繁忙程度趋势。
这些优化加起来,使得CANable 2.5在应对高负载、高实时的CAN FD网络时,表现出了远超其价格定位的稳定性和专业性。我尝试用它长时间记录一辆车的CAN FD总线数据(混合动力系统,数据量很大),持续数小时没有出现丢包、卡死或异常进入DFU的情况,这对于之前的固件版本是不可想象的。
5. 实战指南:从烧录到上手的完整流程
说了这么多特性,我们来看看怎么把它用起来。整个过程比原版要顺畅得多,尤其是Windows下的兼容性问题得到了根本解决。
5.1 固件获取与烧录
首先,你需要准备一个CANable 2.0版本的硬件(主控是STM32G431)。然后去Elmue的GitHub仓库(https://github.com/Elmue/CANable-2.5-firmware-Slcan-and-Candlelight)下载最新的固件文件。或者,更推荐的方法是直接下载并安装HUD ECU Hacker这款上位机软件。它内置了固件更新程序,并且已经包含了编译好的固件。
HUD ECU Hacker的固件更新程序非常直观。连接你的CANable,软件会自动识别。你会看到四个固件选项,主要区别在于适配不同厂商的LED引脚定义:
STM32G431 - Slcan2.5 - MksMakerbase.dfu:适用于MKS Makerbase, DSD Tech, Walfront等品牌的适配器。STM32G431 - Slcan2.5 - OpenlightLabs.dfu:适用于Openlight Labs的适配器。STM32G431 - Candlelight2.5 - MksMakerbase.dfuSTM32G431 - Candlelight2.5 - OpenlightLabs.dfu
选择对应的Candlelight或Slcan固件,点击“Program”即可一键烧录。强烈建议在烧录前,先点击“Download”按钮备份你当前的固件。烧录完成后,重新插拔USB,你会看到蓝绿色LED开始交替闪烁,这表明新固件运行正常。
这里有个关键步骤:解决BOOT0问题。在烧录界面,你会看到一个“Disable Pin Boot0”按钮。如果你受够了随机进入DFU的困扰,一定要点一下这个按钮。它会修改芯片的选项字节,永久禁用硬件BOOT0引脚功能。以后想进DFU,只能通过软件命令(在软件里点“Enter DFU mode”按钮),彻底告别“幽灵”启动。
5.2 驱动安装与设备识别
烧录Candlelight 2.5固件后,Windows的即插即用体验堪称完美。旧版Candlelight驱动安装是噩梦,经常需要手动指定inf文件,还未必成功。新版固件包含了正确的Microsoft OS描述符,Windows 10/11在设备插入的瞬间就能在后台自动安装好WinUSB驱动,没有任何弹窗,速度极快。在设备管理器中,你会看到两个设备:“CANable Candlelight Interface”和“CANable DFU Interface”。前者用于正常通信,后者用于固件更新。这种100%的免驱兼容性,大大降低了部署门槛。
对于Slcan固件,行为和老版本一样,会被识别为一个USB串行设备(COM口)。你可以用任何串口工具(如Putty、HUD ECU Hacker自带的终端)打开它,波特率任意设置(实际通信速率是USB全速12Mbps)。
5.3 基础配置与快速测试
使用Slcan协议快速测试:
- 用串口工具打开对应的COM口。
- 发送关闭命令(
C\r)重置适配器到默认状态。 - 发送版本查询命令(
V\r)。如果返回类似+Board: MksMakerbase...的信息,说明你正在使用CANable 2.5固件。 - 发送
MF\r启用反馈模式(这样每个命令都会有成功或失败的回应)。 - 设置波特率。对于传统CAN,用
S6\r设置500kbps。对于CAN FD,你需要分别设置标称波特率和数据波特率,例如s4,69,10,7\r和y4,9,10,7\r(具体值需计算)。 - 发送
ON\r以正常模式打开适配器。 - 现在可以发送数据了。例如,发送一个标准帧:
t123401020304\r表示发送ID 0x123,数据长度为4,数据为01 02 03 04。
使用Candlelight协议进行专业开发: 对于C++或C#开发者,我强烈建议直接使用Elmue提供的演示应用程序作为起点。这个演示程序封装了所有复杂操作:
- 自动枚举所有连接的Candlelight设备。
- 获取设备详细信息(板卡类型、MCU、固件版本)。
- 设置精确的波特率和采样点。
- 配置硬件过滤器。
- 发送/接收数据包,并处理Tx回波标记。
- 解析和显示CAN错误。
- 执行禁用BOOT0、进入DFU模式等高级操作。
演示程序的代码结构清晰,注释详细,特别是展示了如何正确使用WinUSB API。这一点非常重要,因为像Cangaroo这样的旧软件,对WinUSB的使用方式存在缺陷,可能导致在高负载下数据包顺序错乱甚至丢失。新固件配合正确的调用方式,才能发挥其全部性能。
5.4 理解新的LED语言
升级后,LED指示灯的行为也更准确了:
- 红色LED:常亮表示供电正常。这不受处理器控制。
- 蓝绿色交替闪烁:上电后或进入DFU模式前,表示固件运行正常。
- 蓝色LED:接收到CAN数据包时闪烁(即使数据被过滤器过滤掉也会闪)。这能让你直观看到总线上的所有活动。
- 绿色LED:仅在CAN数据包成功发送到总线并被接收方确认(ACK)后闪烁。这是一个非常重要的改进!旧版固件只要试图发送就会闪绿,不管成功与否。现在,绿灯闪烁是你数据发送成功的可靠视觉确认。
如果红绿蓝三颗LED同时常亮,通常表示发生了严重错误,如总线关闭或缓冲区溢出,需要检查总线配置和负载。
6. 给开发者的深入建议:避开那些“坑”
基于我深度使用和测试的经验,这里分享几个关键建议,能帮你更好地驾驭CANable 2.5固件,避开一些潜在的坑。
第一,滤波器配置要趁早。STM32的CAN硬件滤波器有一个限制:一旦适配器打开(进入总线监听或发送状态),滤波器的配置就基本被锁定了,不能再添加或删除,只能替换一个同类型的滤波器。所以,务必在调用“打开”命令(O\r或 Candlelight的打开函数)之前,就规划好并设置好你需要的所有掩码过滤器。如果打开后才发现滤波器设错了,只能先关闭适配器,重新配置,再打开。
第二,谨慎使用自动重传。在Slcan协议中,A1\r命令或MA\r模式会启用自动重传。这意味着如果发送一个数据包后没有收到ACK(比如目标节点不存在或波特率错误),CAN控制器会不停地重发,可能导致总线负载瞬间飙到95%以上,影响其他节点通信。CANable 2.5固件引入了一个500毫秒的交易超时机制,能自动终止这种无限重试,并报告“Tx Timeout”错误。但在设计协议时,对于非关键性、周期性的发送,更推荐使用单次发送模式(A0\r或Ma\r),并结合发送回波标记来确认发送成功与否,这样对总线更友好。
第三,采样点是CAN FD的命门。如果你只是用两个CANable在桌面上对发测试,采样点设置可能不那么敏感。但一旦要接入真实的车辆或工业CAN FD网络,采样点必须和网络中的其他节点严格匹配。不要再用旧版固件里那些固定的“S”和“Y”命令了,它们给出的采样点很可能是错的。一定要使用能让你自定义采样点百分比的上位机软件(如HUD ECU Hacker),或者使用底层“s”和“y”命令直接输入计算好的参数。记住那个“Perfect match: Yes”的提示,尽量让标称段和数据段使用相同的预分频器值。
第四,善用错误报告做诊断。把错误报告功能(ME\r)一直开着。它不仅是出问题时才看的日志,更是了解总线健康状况的仪表盘。偶尔出现的“Bit stuffing error”可能提示有轻微干扰;“No ACK received”告诉你目标节点没响应;“Bus Off”则是严重错误,需要立刻检查物理连接和波特率设置。这些信息是线上问题定位的第一手资料。
第五,关于性能计数器时间戳的选择。新固件支持两种时间戳:一种是固件生成的1微秒精度时间戳(会占用额外USB带宽),另一种是利用主机CPU性能计数器生成的纳秒级时间戳。对于绝大多数应用,推荐使用主机时间戳。因为USB传输本身就有不确定的延迟,固件时间戳记录的是数据包进入CAN控制器FIFO的时刻,而不是主机真正收到它的时刻。主机时间戳在数据包到达应用层时打上,对于分析本机软件的处理延迟更准确,而且不增加USB负担。演示程序里给出了两种方法的实现,可以参考。
最后,如果你打算基于此进行二次开发,一定要仔细阅读Git仓库里Documentation文件夹下的PDF文档,特别是关于USB协议和DFU规范的部分。这个固件的代码质量很高,但正如作者所说,并不适合嵌入式开发新手。它对STM32 HAL层、USB协议栈以及CAN控制器有较深的使用,直接啃代码可能会有些吃力,但从演示程序开始模仿和修改,会是一个不错的起点。这个固件的出现,终于让CANable这块硬件宝藏,配上了它应有的软件实力。