04 USB数据协议
适用:USB 接口的 HVS 相机(APX003 / APX014 传感器)。本页描述相机 USB 出流的底层线上协议——设备标识、APS/EVS 帧的二进制封装、ep0 控制命令与时间戳域,供绕过 SDK 直接读取 USB 流(libusb / pyusb 等)的驱动级开发使用。常规开发请从 Toolkit SDK 与 编程指引 入手;录制文件格式(RAW8 / EVT2 / CSV)见 数据格式参考。
协议版本 2(2026-10)。 两种传感器、两种底板已统一为同一套自描述协议:每帧 APS 图像带 80 字节帧头,EVS 以变长 EVT2 包流出。2026-10 之前的旧固件设备流出的是旧裸格式,见文末附录。官方上位机检测到旧格式设备会提示"固件过旧,请先 OTA 升级",如需更新最新固件请联系我们。
设备标识
- VID:
0x1D6BPID:0x0105 - 接口 0,3 个 bulk 端点:EP1 IN = APS 图像,EP2 IN = EVS 事件,EP3 OUT = 升级
传感器识别
读第一帧 APS 并解析其 80 字节帧头(见下),按 format 与 width×height 判别:
帧头 format | width×height | 传感器 | 负载 |
|---|---|---|---|
3(NV12) | 1632×1224 | APX003(彩色) | Y + 交错 UV,2,996,352 B |
0(GRAY8) | 640×1024 | APX014(黑白) | 仅 Y,655,360 B |
不解析帧头的速判法:APS 帧总长 = 2,996,432 B(003)vs 655,440 B(014)。
底板识别用 GET_VERSION(0x11):RK_VERSION=EVB1_… = EVB1 板,RK_VERSION=NRS3_… = CF-NRS3 板。
APS 帧(EP1 IN)
每帧 = 80 字节帧头(小端、packed) + 负载。帧头两传感器完全一致。
| 偏移 | 类型 | 字段 | 说明 |
|---|---|---|---|
| +0x00 | u16 | magic | 固定 0xCF14 |
| +0x02 | u8 | format | 0=GRAY8,1=GRAY16(预留),2=RAW10(预留),3=NV12 |
| +0x03 | u8 | hdr_version | 固定 1 |
| +0x04 | u32 | payload_len | 003:2,996,352 · 014:655,360 |
| +0x08 | u32 | ts_sec | 帧到达时间戳,µs 域 |
| +0x0C | u32 | ts_usec | 同上(与 EVS 包时间戳同源同域) |
| +0x10 | u64 | t_trigger | 外触发锁存时间戳(无触发 = 0) |
| +0x18 | u32 | exposure_us | 积分时间(µs) |
| +0x1C | u32 | analog_gain_x256 | 模拟增益,Q8.8(256 = 1.0×) |
| +0x20 | u32 | digital_gain_x256 | 数字增益,Q8.8(256 = 1.0×) |
| +0x24 | u32 | gray_brightness | 平均亮度(Y 平面稀疏采样) |
| +0x28 | u16 | gamma_index | 0 = 线性 |
| +0x2A | u32 | frame_counter | 逐帧 +1 |
| +0x2E | u32 | ext_trigger_count | 外触发计数(与 EVS 触发词对账) |
| +0x32 | u32 | width | 自描述几何(见上表) |
| +0x36 | u32 | height | 同上 |
| +0x3A | u32 | roi_x | 未启用,恒 0 |
| +0x3E | u32 | roi_y | 未启用,恒 0 |
| +0x42 | i16 | sensor_temp_x01 | 温度 0.1℃(不支持时 0) |
| +0x44 | u16 | status_flags | bit0 = 帧间隔超 35,000µs |
| +0x46 | u16 | crc16 | CRC-16/CCITT-FALSE,覆盖 [0, 0x46) |
| +0x48 | u8[8] | reserved | 0 |
负载布局:
| APX003(彩色) | APX014(黑白) | |
|---|---|---|
| 格式 | NV12(YUV420 半平面) | Gray8 |
| 几何 | 1632×1224(传感器原生) | 640×1024(传感器原生) |
| 字节 | Y = 1,997,568 + 交错 UV = 998,784(612 行 × 1632 B) | Y = 655,360 |
| 帧总长(头+负载) | 2,996,432 B | 655,440 B |
帧校验(建议):magic 0xCF14、CRC16、hdr_version == 1、payload_len 与 format/几何交叉一致(GRAY8:W*H == payload_len;NV12:W*H*3 == payload_len*2)。
EVS 流(EP2 IN)
EVS 以变长 EVT2 包流出。一个传感器帧(003 为时间片)由 1..4 个连续包承载。
包封装
包的整体结构:
| 段 | 长度 | 说明 |
|---|---|---|
len | 4 B (u32 LE) | 包长(字节),不含本字段自身;有效域 [40, 32,832] |
| 包头 | 40 B | 见下表(小端,结构体原样 memcpy) |
| 负载 | payload_size B | [TIME_HIGH 词] [可选 EXT_TRIGGER 词] [CD 事件词 ×N] |
40 字节包头字段:
| 偏移 | 类型 | 字段 | 说明 |
|---|---|---|---|
| +0x00 | char[4] | 魔数 | "DVS1"(0x44565331) |
| +0x04 | u16 | version | 协议版本 |
| +0x06 | u8 | packet_type | 1 = EVT2 |
| +0x07 | u8 | flags | 保留 |
| +0x08 | u32 | sequence_num | 逐包 +1(检测丢包) |
| +0x0C | u32 | device_id | 恒 0 |
| +0x10 | u32 | timestamp_sec | 片/帧起始时间,µs 域 |
| +0x14 | u32 | timestamp_usec | 同上(与 APS 帧头同源同域) |
| +0x18 | u32 | payload_size | 包头后的负载字节数 |
| +0x1C | u32 | event_count | 包内 CD 事件数(不含触发词) |
| +0x20 | u32 | checksum | CRC-32(zlib):校验位清零的 40B 头续算全部负载段 |
| +0x24 | u32 | frame_number | 按 fn 聚合 1..4 包为一帧 |
包长读前导 u32;每个包最后一次 bulk 传输的短包即包界(见帧边界)。
EVT2 事件编码(4 字节词,Prophesee EVT2 标准)
CD 事件: type = 0x0(负极性 OFF)/ 0x1(ON),位于 bits[28:31]
x = bits[0:10],y = bits[11:21],timestamp_low6 = bits[22:27]
TIME_HIGH: type = 0x8,时间戳高 28 位(值 >>6)
→ 完整事件 t = (TIME_HIGH<<6 | low6),µs 域
EXT_TRIGGER:type = 0xA,ts 低 6 位、触发计数、极性——仅带外触发硬件的
APX014 设备会有事件坐标在传感器事件网格内:003 = 768×608,014 = 640×1024。(两传感器内部极性约定相反——003 的 ON/OFF 与 014 互为镜像——但已在打包源头归一化,线上 type 0x1 恒为正事件,无需开发者关心差异。)
每帧/每片事件数默认上限 32,768(超限时均匀抽样);运行时可经 SET_EVT_RATE_LIMIT(0x1D)调整,范围 1..32,768。
ep0 控制命令(vendor request)
所有命令:bmRequestType = vendor | interface,wIndex = 0。
| bRequest | 名称 | 方向/负载 | 说明 |
|---|---|---|---|
| 0x00 | GET_STATUS | IN, 2 B | [状态, 错误码]:状态 1=升级进行中;错误码 0=无 1=文件大小无效 2=板型不匹配 3=无板型标签(升级被拒) |
| 0x05 | ENTER_UPGRADE | OUT | 暂停取流,进入升级模式 |
| 0x06 | SET_UPGRADE_SIZE | OUT, 8 B(u64 小端) | 声明升级镜像大小 |
| 0x07 | REBOOT | OUT | 执行待处理的升级并重启(非升级会话下为普通重启) |
| 0x08 / 0x09 | SET / GET_SENSOR | OUT/IN | AE 参数(模式/曝光/增益;仅 APX014) |
| 0x0A | CLEAR_SHM | OUT, 1 B | 主机读流门控:1 = 主机正在读 |
| 0x10 | GET_SN | IN, ≤24 B | 产品 SN(第 8-9 位:01=003,02=014) |
| 0x11 | GET_VERSION | IN, 字符串 | RK_VERSION=EVB1_… / NRS3_…(底板身份) |
| 0x12 / 0x13 | SET / GET_IP | OUT/IN | 网络配置 |
| 0x14 / 0x15 | SET / GET_EVS_FPS | OUT/IN, 2 B(u16 大端) | EVS 帧率;切换会重启管线 |
| 0x16 / 0x17 | SET / GET(按传感器分派) | OUT/IN, 4 B 大端 | APX003:EVS 事件阈值,on、off 各 u16 大端,钳制 0x3F。APX014:外触发极性(0/1/2) |
| 0x18 / 0x19 | SET / GET_TRIG_DEBOUNCE | OUT/IN, 2 B 小端 µs | 触发去抖 0..1000µs(APX014 + 触发硬件) |
| 0x1A / 0x1B | SET / GET_EVT_DENOISE | OUT/IN, 8 B | EVS 去噪参数(APX014) |
| 0x1C | SET_MIRROR | OUT, 2 B | 水平/垂直翻转(APX014) |
| 0x1D / 0x1E | SET / GET_EVT_RATE_LIMIT | OUT/IN, 4 B 小端 | 每帧事件上限(1..32,768;两传感器通用) |
| 0x1F | SET_ACQUISITION | OUT, 1 B | 采集暂停/恢复 |
| 0x20 / 0x21 | SET / GET_SYNC_OUT | OUT/IN, 9 B | 同步输出 PWM(仅 CF-NRS3 板) |
发到"非本传感器"的命令(如对 003 发去噪)会被消耗并 ACK 后忽略——绝不 STALL;底板不具备的硬件功能(如 EVB1 板的外触发)优雅降级为无操作 + 正常应答。
固件升级(OTA)流程:ENTER_UPGRADE → SET_UPGRADE_SIZE → 将 update.img 流式写入 EP3 OUT → REBOOT。设备在刷写之前校验镜像板型标签与自身底板是否匹配;不匹配则拒绝升级(GET_STATUS 错误码 2),相机保持可用。
帧率档位:003 = 120/240/500/750/1000;014 = 240/300/480/600。
帧边界
- APS:每帧拆为 4 个等大的 1024 整数倍块 + 尾部短块(帧长 mod 块长),尾短包即帧界——按帧总长读取
- EVS:包长以前导
u32为准;包长非 bulk 最大包整数倍时以短包收尾 = 包界;按frame_number聚合 1..4 包为一帧
时间戳单位
流上全部时间戳(APS 帧头 ts_sec/usec、EVT2 包头、EVT2 TIME_HIGH 事件词)共用同一微秒时基。旧协议的 tick/µs 混域(见附录)已废止。
附录:旧流格式(2026-10 之前)
2026-10 协议统一前的旧固件设备流出以下格式。官方上位机会识别为旧设备(提示"固件过旧,请先 OTA 升级")并不解码;此处保留供现场识别旧设备之用,如需更新最新固件请联系我们。
旧 APS 帧(无帧头,尾随时间戳)
NV12 裸帧 + 尾 8B 小端 u64 时间戳
003: 768×608 = 700,416 B + 8 B = 700,424 B,尾时间戳 µs 域
014: 640×1024 = 983,040 B + 8 B = 983,048 B,尾时间戳原始 tick(~24MHz)旧 EVS 流(裸传感器 chunk,无包封装)
APX003——chunk = 524,288 B = 16 子帧 × 32,768 B;每子帧覆盖一个空间象限(384×304 @2bit),4 象限拼成 768×608 事件网格:
子帧头(16 B):
+0x00 u64 bits[0:15]=0xFFFF 魔数, bits[24:63]=40bit 时间戳(5ns/tick, ÷200=µs)
+0x08 u64 bits[44:47]=象限号(0-3)
+0x10 ... 事件载荷 29,184 BAPX014——chunk = 定长 164,864 B = 32 子帧 × 5,152 B;每子帧覆盖 320×64 @2bit:
子帧头(24 B):
+0x00 u32 低24bit = 0x0000FFFF 魔数
+0x04 u32 时间戳(原始 tick)
+0x0C u32 帧号(低24bit;帧内32子帧差≤1)
+0x16 u16 SubFrame=bits[5:10], Vflip=bit11, Hflip=bit12
+0x18 ... 事件载荷 5,120 B
尾 8B 填充像素编码(两传感器同):每 u64 含 32 像素(2bit/px, LSB-first),code>0 为事件,polarity=code>>1。校验:任一子帧魔数非法或帧号极差>1 → 整帧丢弃。
