简单通信落地:FPGA 实现 CAN 总线接口与数据帧解析

https://pan.baidu.com/s/1rDsLAXGj8WbX82teSkhuIw?pwd=1234
这份FPGA 系统学习详细资料包是个人花大量时间精心整理的,超多干货全覆盖,从基础到实战一站式搞定,不用再到处薅资料!网盘链接随时可能失效,提取码 1234,先保存再学习,别等失效拍大腿!🔗链接:https://pan.baidu.com/s/1rDsLAXGj8WbX82teSkhuIw?pwd=1234
————————————————

简单通信落地:FPGA 实现 CAN 总线接口与数据帧解析

CAN 总线在工业现场和汽车电子中应用极其广泛,它的可靠性、实时性和多主特性是 UART、SPI、I2C 无法比拟的。从零实现一个完整的 CAN 控制器确实有一定复杂度,但掌握核心的数据帧收发解析能力,就能应对大多数 FPGA 与 CAN 总线交互的场景。下面我带你一步步落地。


1. 先理解 CAN 协议的核心特点

在写代码前,必须理解 CAN 总线与众不同的地方:

特性说明
物理层差分信号(CAN_H 和 CAN_L),显性(逻辑 0)覆盖隐性(逻辑 1)
多主通信任何节点都可主动发送,通过标识符(ID)仲裁决定谁获得总线控制权
非破坏性仲裁ID 值越小(显性位越多),优先级越高。仲裁失败的节点自动转为接收
短帧结构一帧最多携带 8 字节数据,有效降低干扰概率
强大的检错机制CRC 校验、位填充、格式检查、应答确认等

对比一下:UART 需要约定波特率,SPI 需要片选线,I2C 有地址。而 CAN 的仲裁机制使得多个节点可以同时发送,靠 ID 决定谁说话,这是它最核心的魅力。


2. CAN 数据帧结构详解

我们最常用的是标准数据帧(CAN2.0A),它的组成如下:

帧起始(1bit) + 仲裁段(12bit) + 控制段(6bit) + 数据段(0~8byte) + CRC段(16bit) + ACK段(2bit) + 帧结束(7bit) 

逐段拆解

  • 帧起始(SOF):1 个显性位(0),标志一帧开始,用于同步。
  • 仲裁段
    • 11 位标识符(ID),高位先发。
    • RTR 位(远程传输请求):数据帧为显性(0),远程帧为隐性(1)。
  • 控制段
    • IDE 位(标识符扩展):标准帧为显性(0)。
    • 保留位 r0(显性)。
    • DLC(数据长度码):4 位,表示数据段字节数(0~8)。
  • 数据段:0~8 字节,MSB 先行。
  • CRC 段:15 位 CRC 校验码 + 1 位隐性 CRC 界定符。
  • ACK 段:发送节点发送 2 位隐性位,接收节点在 ACK 槽位发送显性位应答。
  • 帧结束:7 个隐性位(1)。

扩展帧(CAN2.0B)有 29 位 ID,我们暂不涉及。


3. FPGA 实现 CAN 接口的两种路径

路径 A:使用外部 CAN 控制器芯片

这是最稳妥的**“快速落地”**方式。FPGA 只负责与 CAN 控制器(如 SJA1000、MCP2515)通过并行或 SPI 接口通信,控制器完成繁琐的协议处理。

  • 优点:协议稳定,开发周期短。
  • 缺点:增加 BOM 成本,占用 PCB 面积。
  • 适用:对可靠性要求高、项目周期紧的场景。
路径 B:FPGA 内部实现 CAN 控制器软核

这是我们本次的重点——用 Verilog 自己实现 CAN 协议核心。

  • 优点:高度集成,可定制,无额外芯片成本。
  • 挑战:需要完整实现位时序、同步、仲裁、CRC、位填充、错误处理等。
  • 适用:希望掌握 CAN 核心技术、追求集成度的场合。

4. 自研 CAN 控制器核心模块设计

一个完整的 CAN 控制器通常包含以下模块:

模块功能
寄存器模块配置波特率、验收滤波、状态查询
位定时模块产生位时间,实现硬同步和重同步
位流处理器(BSP)并串/串并转换,位填充/去填充
CRC 模块发送时计算 CRC,接收时校验
验收滤波器判断接收到的 ID 是否匹配
状态机模块控制发送、接收、错误处理等状态
错误计数器统计错误,决定是否总线关闭
4.1 位定时与同步(最关键的物理层)

CAN 是异步通信,每个节点有自己的时钟,通过位同步来保持步调一致。

一个位时间分为 4 段:

  • 同步段(Sync_Seg):1 个时间份额(Tq),期望跳变沿在此段发生。
  • 传播段(Prop_Seg):补偿物理延迟。
  • 相位缓冲段 1(Phase_Seg1):用于补偿相位误差,可被延长。
  • 相位缓冲段 2(Phase_Seg2):用于补偿相位误差,可被缩短。
  • 采样点:位于 Phase_Seg1 结束处。

波特率计算公式

波特率 = 系统时钟频率 / (分频系数 × (Sync_Seg + Prop_Seg + Phase_Seg1 + Phase_Seg2)) 

采样点位置一般设置在 70%~90% 位时间处,例如 87.5%。

硬同步:在帧起始的下降沿,所有节点强制将位时间对齐到 Sync_Seg。

重同步:在后续位中,如果跳变沿偏离了 Sync_Seg,通过缩短 Phase_Seg2 或延长 Phase_Seg1 来调整。

4.2 位填充(Bit Stuffing)

CAN 协议规定:在发送时,如果连续出现 5 个相同极性的位,必须在第 5 位后插入一个相反极性的填充位。接收时,如果检测到连续 6 个相同位,则视为填充错误。

作用:提供足够的跳变沿用于时钟同步,防止 DC 分量累积。

FPGA 实现:发送时用计数器监控,满 5 个相同位就插入一个相反位;接收时同样计数,遇到第 6 个相同位报错。

4.3 CRC 计算

CAN 标准帧使用 15 位 CRC,生成多项式为:

X^15 + X^14 + X^10 + X^8 + X^7 + X^4 + X^3 + 1 

计算范围包括:帧起始、仲裁段、控制段、数据段。发送时计算并附加,接收时重新计算并与接收到的 CRC 比较。

4.4 主状态机设计

CAN 控制器的状态机比 UART/SPI 复杂得多,主要包括:

IDLE → 发送/接收 → 仲裁 → 错误处理 → 间歇 
  • 总线空闲:检测到连续 11 个隐性位。
  • 发送:有发送请求且总线空闲,发送 SOF 开始。
  • 接收:作为接收器,监测总线并接收数据。
  • 仲裁:多个节点同时发送时,逐位比较 ID,如果发送位为隐性而总线上为显性,则丢失仲裁,转为接收。
  • 错误处理:根据错误计数器决定是否进入总线关闭状态。

5. 数据帧解析实战(从波形到数据)

假设我们已经有了一个 CAN 收发器(如 TJA1050)连接到 FPGA,FPGA 接收到的 RX 信号是经过电平转换的逻辑信号。解析一帧数据的流程如下:

5.1 检测帧起始

总线空闲时,RX 为隐性(1)。检测到下降沿(1→0)表示 SOF 到来,启动接收状态机。

5.2 采样数据位

根据位定时配置,在每个位时间的采样点读取 RX 电平。建议采用3 次采样取多数的方式提高抗干扰性。

5.3 解析 ID 和 RTR

接下来的 11 位是 ID(MSB first),第 12 位是 RTR。如果是远程帧(RTR=1),则没有数据段。

5.4 解析控制段
  • IDE 位(第 13 位):标准帧应为 0。
  • 保留位:应为 0。
  • DLC(第 14~17 位):得到数据长度(0~8)。
5.5 接收数据段

根据 DLC,接收后续字节。每个字节 MSB 先行。

5.6 CRC 校验

接收完数据段后,接下来 16 位是 CRC 段(15 位 CRC + 1 位界定符)。FPGA 边接收边计算 CRC,最后与收到的 CRC 比较。

5.7 ACK 段

CRC 界定符后,发送节点释放总线(隐性)。如果本节点正确接收,应在 ACK 槽位(第 1 位 ACK 段)拉低总线(发送显性)作为应答。

5.8 帧结束

检测到 7 个隐性位,一帧结束。

5.9 代码示例(伪代码)
always @(posedge clk) begin case (rx_state) IDLE: if (rx_falling_edge) begin rx_state <= GET_ID; bit_cnt <= 0; end GET_ID: if (sample_point) begin id_reg[10-bit_cnt] <= rx; if (bit_cnt == 10) begin bit_cnt <= 0; rx_state <= GET_RTR; end else bit_cnt <= bit_cnt + 1; end GET_RTR: if (sample_point) begin rtr <= rx; rx_state <= GET_DLC; bit_cnt <= 0; end GET_DLC: if (sample_point) begin dlc[3-bit_cnt] <= rx; if (bit_cnt == 3) begin bit_cnt <= 0; rx_state <= (dlc>0) ? GET_DATA : GET_CRC; end else bit_cnt <= bit_cnt + 1; end // 后续状态类似... endcase end 

6. 多帧数据打包与解包(实用技巧)

由于 CAN 每帧最多 8 字节,当需要传输超过 8 字节的数据时,必须进行多帧传输。工业应用中常用自定义的数据包格式来简化处理:

字段长度说明
帧头1 字节标识数据包起始
总长度2 字节有效数据总字节数
帧序号1 字节当前是第几帧
数据0~4 字节实际有效数据
校验1 字节累加和或异或校验

示例:要发送 20 字节数据,分成 5 帧,每帧数据段放 4 字节,再加上帧序号等信息。接收端根据帧序号重组。


7. 调试与验证

7.1 仿真验证
  • 编写 Testbench,模拟多个 CAN 节点同时发送,测试仲裁机制。
  • 注入位错误,验证错误处理逻辑。
  • 使用 $display 打印关键状态跳转。
7.2 板级调试
  • 必备工具:CAN 总线分析仪(如周立功 USBCAN)、示波器。
  • 测试步骤
    1. FPGA 与 CAN 收发器(如 TJA1050)连接,接入 CAN 网络。
    2. 用分析仪发送标准数据帧,FPGA 接收并解析,通过串口或 LED 显示结果。
    3. FPGA 发送数据,分析仪接收验证。
    4. 双节点对发,测试长时间稳定性。
7.3 常见问题排查
现象可能原因排查方法
无 ACK 应答波特率不匹配 / 节点未上电检查终端电阻(120Ω),用示波器测波形
CRC 校验错误位定时配置不当 / 采样点偏移调整波特率分频和采样点位置
总线一直显性某个节点故障逐个断开节点,找出故障源
偶发性丢帧同步问题 / 干扰检查屏蔽和接地,调整采样点

8. 总结与建议

实现层级内容难度
入门用外部 CAN 控制器 + FPGA 简单读写★★☆
进阶自研 CAN 控制器核心(位定时 + 状态机)★★★★
精通完整实现错误处理、总线关闭、TTCAN★★★★★

对于初学者,建议先从路径 A 入手:用 SJA1000 或 MCP2515 这类成熟的控制器,FPGA 只需实现 SPI 或并行总线读写,快速搭建起 CAN 通信链路。在这个过程中理解 CAN 协议,再用示波器观察波形,逐步深入。

当你能熟练解析数据帧、处理多帧传输后,再挑战自己用 Verilog 实现一个完整的 CAN 控制器软核。那时候,你就真正掌握了这个工业级通信协议的灵魂。

Read more

1000多万次播放背后的AIGC方法论:从爆款视频《牌子》开始思考

这篇深度分析文章,基于《牌子》(SIGN)这部现象级AIGC短片的全面拆解,构建一套完整的AIGC内容创作方法论。将分章节系统性地展开,涵盖技术解析、创作方法论、产业影响和未来展望等多个维度。 引言:一个内容事件的诞生 2026年初,中国视频平台Bilibili上出现了一条名为《牌子》(SIGN)的7分钟短片。这部由独立创作者使用AI工具制作的奇幻短片,在一周内获得了超过1000万次播放、80多万点赞、30多万投币,被著名导演郭帆转发点赞,在YouTube上引发国际观众的热议,甚至专业影视后期团队都在上班时间逐帧分析其制作技术。 这不是一次简单的"技术展示",而是一个内容事件的诞生——它标志着AIGC(人工智能生成内容)从"实验室玩具"正式迈入"大众审美"的领域。更重要的是,它证明了一件事:在正确的创作方法论指导下,单个创作者借助AI工具,可以产出媲美专业团队的内容。 本文将从《牌子》的逐帧技术解析出发,深入探讨其背后的创作逻辑,提炼出一套可复用的AIGC内容创作方法论,

2026 最新版|学生认证白嫖 GitHub Copilot Pro 保姆级教程

2026 最新版|学生认证白嫖 GitHub Copilot Pro 保姆级教程

2026 最新版|学生认证白嫖 GitHub Copilot Pro 保姆级教程 作为编程党,谁能拒绝免费的 Copilot Pro?每月省 10 $,解锁无限制代码补全、Anthropic Claude Sonnet 4, GPT-5, Gemini 2.5 Pro等高级模型、每月 300 次 Premium 请求,学生身份认证就能直接白嫖,全程零成本,亲测 2026 年有效!这篇教程把所有步骤、避坑点都捋清楚了,跟着做一遍过,再也不用受免费版额度的气! 前言 先说说为什么一定要冲 Copilot Pro:免费版每月只有 2000 次代码补全 + 50 次聊天请求,写代码刚进入状态就提示额度用完,体验感拉胯;而 Pro

【Stable Diffusion安装及常见问题】详细安装步骤及问题解决方案

Stable Diffusion(SD)可以在多种操作系统上运行,其中主流选择是Windows,但macOS和Linux也都有成熟的方案,不同系统的体验和要求差别不小,这里以Windows系统为例,其他操作系统可以参考官方运行说明,按要求配置 一、安装过程 1.1 git安装 后续安装需要使用git拉取Stable Diffusion的官方仓库文件,使用git拉取相比于下载zip可以通过修改运行文件实现每次运行时自动更新最新版本 (1)访问下方连接,下载git安装包  Git - Install for Windowshttps://git-scm.com/install/windows (2)下载完成后运行执行程序,选项保持默认即可 1.2 Python3.10.6安装 Stable Diffusion 依赖 Python,是因为其核心框架(如 PyTorch)、模型库(如 diffusers)、用户界面(如

发那科机器人指令详解:从入门到精通

发那科机器人指令详解:从入门到精通

发那科机器人指令详解:从入门到精通 工业机器人领域的王者,掌握这些指令让你效率提升三倍 工业机器人作为自动化生产的核心装备,发那科(FANUC)机器人凭借其卓越的性能和可靠性,已成为全球众多制造企业的首选。本文将深入解析发那科机器人的核心指令体系,帮助初学者和专业人士全面掌握机器人编程技巧。 一、发那科机器人基础概述 发那科机器人采用专有编程语言KAREL(基于Pascal)和更为通用的TP(Teach Pendant)语言进行编程。 在实际操作中,我们主要使用TP语言在示教器上编写程序,而KAREL则用于更复杂的算法和数据处理任务。 发那科机器人的程序由一系列指令构成,这些指令控制着机器人的运动、I/O操作、流程控制等各个方面。程序中的形参列表支持定义输入参数和输出参数,各个参数之间以逗号分隔。 每个形参变量都定义为局部变量,只在程序中有效。 二、运动指令详解 运动指令是机器人编程中最核心的部分,它决定了机器人的运动轨迹、速度和精度。 1. 关节运动指令(JOINT) JOINT VJ=50.0% SPEED V=100.0mm/s 关节运动指令控制机器人各