2、开发环境搭建:编译工具链、模拟器选择、源码下载与首次编译

好,咱们正式开始动手了。

上一章聊了CANopenNode的整体架构,你可能觉得有点虚。没关系,这一章我们就把环境搭起来,让代码真正跑起来。我个人习惯是先把环境搞利索了,再去看代码,不然心里不踏实。

2.1 编译工具链的选择

CANopenNode是用纯C写的,所以编译工具链其实不挑。但这里有个现实问题——你最终要把代码烧到嵌入式设备里,所以工具链得跟你的目标芯片匹配。

我常用的组合是:

目标平台 工具链 备注
Linux (x86/ARM) gcc + make 最省事,适合纯学习
STM32 (ARM Cortex-M) arm-none-eabi-gcc 工业项目最常见
Windows 模拟 MinGW 或 MSVC 调试方便,但坑多

如果你只是想把CANopenNode跑起来看看效果,我建议先在Linux上搞。为什么呢?因为Linux下的socketCAN是现成的,你不用买硬件就能模拟CAN总线。我在项目中遇到过好几次,开发板还没到货,环境已经调通了。

我的小建议: 初学者别一上来就搞交叉编译。先在Ubuntu上用gcc编译一遍,跑通demo,再移植到嵌入式平台。这样出问题了你能分清是代码问题还是工具链问题。

2.2 模拟器选择——没有硬件也能玩

说实话,CANopen开发最头疼的就是硬件。以前我做个协议栈调试,得抱着开发板到处跑。现在好了,有模拟器了。

这里推荐两个方案:

  • 方案一:socketCAN + can-utils
    这是Linux内核自带的虚拟CAN接口。你只需要执行:
    sudo modprobe can
    sudo modprobe vcan
    sudo ip link add dev vcan0 type vcan
    sudo ip link set up vcan0
    然后你的Linux系统里就多了一个虚拟CAN口。CANopenNode可以直接往这个口上发数据。
  • 方案二:CANopen 模拟器软件
    比如 CANopen for Python 或者 PCAN-View(如果你有硬件)。我个人更推荐先用socketCAN,零成本,而且跟CANopenNode的集成度最高。
注意: 如果你用Windows,socketCAN这条路走不通。可以考虑用Virtual CAN Bus Driver(比如Lawicel的虚拟驱动),或者干脆装个WSL2。我曾经在Windows上折腾了一整天,最后还是切到Linux虚拟机才搞定。

2.3 源码下载——从哪里拿代码

CANopenNode的源码托管在GitHub上,地址是:
https://github.com/CANopenNode/CANopenNode

下载方式很简单:

git clone https://github.com/CANopenNode/CANopenNode.git
cd CANopenNode

嗯,这里要注意一下版本。我建议你拉最新的稳定版,别用master分支。为什么呢?因为master上可能有一些实验性的改动,编译不过去。我吃过这个亏,当时拉下来编译报错,查了半天发现是某个新提交的bug。

推荐的做法是:

git tag -l          # 看看有哪些版本号
git checkout v4.2   # 选一个稳定的版本

目前v4.2是比较稳的,文档也齐全。

2.4 首次编译——跑起来再说

好,代码到手了,咱们开始编译。

CANopenNode的编译系统用的是CMake。你想想看,这玩意儿跨平台,比直接写Makefile省心多了。

编译步骤:

  1. 创建build目录
    mkdir build && cd build
  2. 运行CMake
    cmake ..
    如果你是在Linux上,默认会生成Unix Makefiles。如果你想用别的生成器,可以加参数,比如:
    cmake .. -G "Ninja"
  3. 编译
    make -j4
    -j4表示用4个线程并行编译,能快不少。
  4. 运行测试
    ./test/unit/test_runner
    如果看到一堆绿色的PASS,恭喜你,环境搭好了。
第一次编译常见问题:
- 找不到CMake?
  安装:sudo apt install cmake
- 找不到socketCAN头文件?
  安装:sudo apt install libsocketcan-dev
- 编译报错说某个宏未定义?
  检查一下你是不是用了master分支,切到稳定版试试。

我第一次编译CANopenNode的时候,卡在了socketCAN的依赖上。当时我用的是一台精简版Ubuntu,缺了不少库。后来学乖了,先跑一遍sudo apt build-dep把依赖装全。

2.5 验证环境——让心跳跑起来

编译通过只是第一步。咱们得确认CANopenNode真的能工作。

CANopenNode自带了一个demo程序,在demo/目录下。编译完之后,你可以这样运行:

./demo/canopendemo vcan0

这个demo会创建一个CANopen节点,然后开始发送心跳报文。你可以在另一个终端用candump看看:

candump vcan0

如果看到类似这样的输出:

vcan0  701  [1]  05

嗯,说明节点ID为1的设备正在发送心跳,状态是05(Operational)。

到这一步,你的开发环境就算彻底搭好了。后面咱们就可以开始啃源码了。

避坑指南: 如果你在虚拟机上跑socketCAN,记得把虚拟机的网络适配器设置成「桥接模式」或者「仅主机模式」。NAT模式下有时候会丢包,我当初排查了半天才发现是这个问题。

好,环境搭完了,下一章咱们开始真正看代码。先从CANopenNode的启动流程入手,看看一个节点从复位到运行都经历了什么。