ARTICLE DETAIL

资讯详情

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

Ubuntu下创芯科技CAN分析仪驱动配置与SocketCAN调试指南

Ubuntu下创芯科技CAN分析仪驱动配置与SocketCAN调试指南 1. 为什么一块CAN分析仪在Ubuntu上会让人抓狂如果你是从Windows环境转到Ubuntu做嵌入式开发或者汽车电子调试的大概率经历过这样一个场景兴冲冲地把创芯科技CANalyst-II或者类似的USB-CAN分析仪插到Ubuntu机器上打开终端敲下lsusb设备是认到了但接下来就不知道该干什么了。没有厂商提供的Linux安装包没有图形化的一键安装向导甚至连一个像样的官方Linux文档都找不到。这不是创芯科技一家的问题。国内大部分CAN总线分析仪厂商的软件生态都是围绕Windows搭建的上位机软件、驱动、API全是Windows那一套。到了Linux下面要么自己编译内核模块要么用SocketCAN把设备接管过来要么干脆放弃Linux回Windows。但现实情况是越来越多的嵌入式团队把开发环境整体迁移到了Ubuntu你不可能因为一个CAN分析仪就切回Windows。这篇文章要解决的问题很具体在Ubuntu系统下让创芯科技的CAN分析仪正常工作起来能收发报文能用candump看数据能用Python脚本做自动化测试。我会从驱动识别、内核模块编译、SocketCAN配置、实际收发测试、常见报错排查这几个维度把整个流程拆开讲清楚。适合已经有一定Linux基础、正在做CAN总线相关开发或测试的工程师也适合刚接触Ubuntu但需要快速把设备跑起来的嵌入式新手。先说一个核心结论创芯科技的CAN分析仪在Ubuntu下能不能用取决于你手里的具体型号和固件版本。早期型号用的是专用的USB协议Linux下没有现成驱动需要自己写或者找第三方移植较新的型号如果支持SocketCAN兼容模式那事情就简单很多。下面我会分情况讨论你对照自己的设备型号来操作。2. 先搞清楚你手里的设备到底是什么方案2.1 创芯科技CAN分析仪的常见型号与芯片方案创芯科技的产品线比较杂市面上常见的有CANalyst-II、CANalyst-II、USBCAN-2E、USBCAN-1等。这些设备内部的核心方案大致分两类第一类是基于STM32 独立CAN控制器的方案USB通信通过STM32自带的USB外设实现走的是厂商自定义的USB批量传输协议。这类设备在Windows下依赖厂商提供的驱动通常是.inf文件在Linux下没有官方支持需要自己实现USB通信层。第二类是基于带CAN控制器的MCU USB转串口芯片的方案比如用CH340、CP2102、FT232这类芯片做USB转串口MCU那边再通过串口和CAN控制器通信。这类设备在Linux下反而好办因为CH340和FT232的驱动是内核自带的你只需要把设备当成一个串口设备来操作就行。怎么判断你手里的是哪一类插上设备后在终端执行lsusb看输出里的VID和PID。如果看到的是1a86:7523这类那是CH340方案如果是10c4:ea60那是CP2102如果是0403:6001那是FT232。如果看到的是厂商自定义的VID/PID比如创芯科技自己的VID那基本就是第一类自定义USB协议方案。2.2 用dmesg确认内核识别到了什么lsusb只能告诉你USB层面认到了设备但内核具体把它当成了什么设备要看dmesg的输出。插上分析仪之后立刻执行dmesg | tail -30如果看到类似ch341-uart、cp210x、ftdi_sio这样的字样说明内核已经加载了对应的串口驱动设备会被映射成/dev/ttyUSB0或者/dev/ttyACM0。这种情况下你的调试路径就是串口通信。如果看到的是usb 1-2: new full-speed USB device number 5 using xhci_hcd之后没有任何驱动绑定的信息那说明内核没有匹配到现成驱动你需要走自定义USB通信或者找厂商要Linux驱动源码。提示有些设备虽然用的是CH340芯片但厂商在EEPROM里改了VID/PID导致内核的ch341驱动不自动绑定。这种情况可以用modprobe ch341手动加载或者用echo 1a86 7523 /sys/bus/usb-serial/drivers/ch341-uart/new_id强制绑定。2.3 判断是否需要自己编译内核模块如果你确认设备是自定义USB协议方案接下来要确认厂商是否提供了Linux驱动源码。创芯科技的部分型号会随Windows驱动包附带一个Linux文件夹里面可能有.c和Makefile文件。如果有那恭喜你编译一下就能用。如果没有你有两个选择一是联系厂商技术支持要Linux驱动二是用SocketCAN的gs_usb驱动尝试兼容前提是设备固件支持gs_usb协议这个概率不高。我实测过几个型号创芯科技官方对Linux的支持态度比较暧昧有的型号给源码有的型号只给Windows驱动。所以第一步一定是先确认你手里的设备有没有Linux驱动源码。没有的话后面的操作会比较折腾。3. 驱动安装的完整操作链路3.1 方案一串口方案设备的驱动配置如果你的设备是CH340/CP2102/FT232方案驱动配置相对简单。Ubuntu 20.04及以后的版本这些驱动都已经集成在内核里了你只需要确认设备节点是否正确生成。插上设备后执行ls -l /dev/ttyUSB*如果看到/dev/ttyUSB0说明设备已经就绪。如果没有先检查驱动模块是否加载lsmod | grep ch341 lsmod | grep cp210x lsmod | grep ftdi_sio如果没有加载手动加载sudo modprobe ch341 sudo modprobe cp210x sudo modprobe ftdi_sio加载之后再看dmesg | tail应该能看到设备被识别并绑定到ttyUSB0。接下来要解决权限问题。默认情况下/dev/ttyUSB0的属主是root普通用户没有读写权限。你可以用sudo运行所有命令但更好的做法是把当前用户加入dialout组sudo usermod -aG dialout $USER执行完之后需要重新登录或者重启才能生效。验证方法groups看输出里有没有dialout。有的话以后操作串口设备就不需要sudo了。3.2 方案二自定义USB协议设备的驱动编译如果你的设备是自定义USB协议方案且厂商提供了Linux驱动源码操作流程如下。首先安装编译依赖sudo apt update sudo apt install build-essential linux-headers-$(uname -r)linux-headers这个包非常关键它提供了当前内核版本的编译头文件。如果你之前编译过其他内核模块失败大概率就是缺这个包。进入驱动源码目录通常里面会有一个Makefile。直接执行make如果编译成功会生成一个.ko文件比如canalyst2.ko。加载模块sudo insmod canalyst2.ko然后用dmesg | tail看内核日志确认模块加载成功并且设备被识别。如果编译报错常见原因有几个一是内核头文件版本和当前运行内核不匹配用uname -r确认版本号二是源码里的内核API过时了比如init_timer在新内核里已经改成timer_setup需要手动改源码三是缺少某些依赖头文件根据报错信息安装对应的-dev包。注意每次内核升级之后之前编译的.ko文件都会失效需要重新编译。如果你不想每次都手动编译可以写一个DKMS配置让内核升级时自动重新编译模块。DKMS的配置方法这里不展开但思路是把源码放到/usr/src/下面然后写一个dkms.conf。3.3 方案三用SocketCAN接管设备SocketCAN是Linux内核自带的CAN子系统它把CAN设备抽象成网络接口你可以用ip命令管理用candump抓包用Python的socket库编程。如果创芯科技的设备支持SocketCAN兼容固件那是最理想的方案。检查设备是否被SocketCAN识别ip link show如果看到can0或者can1这样的接口说明设备已经被SocketCAN接管了。如果没有说明设备固件不支持或者驱动没有注册SocketCAN接口。对于支持SocketCAN的设备配置步骤如下sudo ip link set can0 type can bitrate 500000 sudo ip link set can0 upbitrate要根据你的实际总线速率设置常见的有125000、250000、500000、1000000。设置错误的话总线上收不到任何报文。配置完成后用candump测试candump can0如果总线上有其他节点在发报文你应该能看到数据。如果没有可以用cansend发一帧测试cansend can0 123#11223344556677883.4 udev规则固化设备权限不管走哪种方案设备节点每次插拔之后权限都可能重置。为了避免每次都要手动改权限可以写一条udev规则。创建文件/etc/udev/rules.d/99-can.rulessudo nano /etc/udev/rules.d/99-can.rules内容根据你的设备类型来写。如果是串口方案SUBSYSTEMtty, ATTRS{idVendor}1a86, ATTRS{idProduct}7523, MODE0666, GROUPdialout如果是自定义USB方案把VID/PID换成你设备的实际值。保存之后重新加载udev规则sudo udevadm control --reload-rules sudo udevadm trigger这样以后插上设备权限就自动设置好了。4. 调试环节从candump到Python自动化4.1 用can-utils工具集做基础收发测试can-utils是SocketCAN生态里最常用的工具集包含candump、cansend、cangen、canplayer等命令。安装sudo apt install can-utilscandump的常用参数参数作用-l把收到的报文记录到文件-t在每行前面加时间戳-a以ASCII格式显示数据-d显示报文之间的时间差实际使用示例candump -ta can0这条命令会以带时间戳和ASCII格式显示can0上的所有报文。如果你在做总线逆向或者协议分析这个输出格式最方便阅读。cansend用来发送单帧报文cansend can0 7DF#0201050000000000这是发送一个标准帧ID是0x7DF数据是02 01 05 00 00 00 00 00。注意#前面是CAN ID后面是数据数据必须是偶数个十六进制字符。cangen用来生成随机报文做压力测试很有用cangen can0 -g 10 -I 123 -L 8这条命令会以10毫秒的间隔用ID0x123发送8字节的随机数据。4.2 Python脚本实现CAN报文收发如果你需要做自动化测试或者数据分析Python是更好的选择。python-can库封装了SocketCAN接口用起来很方便。安装pip install python-can一个最简单的收发脚本import can import time bus can.interface.Bus(channelcan0, bustypesocketcan) # 发送一帧 msg can.Message(arbitration_id0x123, data[0x11, 0x22, 0x33, 0x44], is_extended_idFalse) bus.send(msg) print(发送成功) # 接收 for i in range(10): received bus.recv(timeout1.0) if received: print(fID: {received.arbitration_id:03X}, Data: {received.data.hex()}) else: print(超时未收到报文) bus.shutdown()这个脚本先发一帧然后尝试接收10帧。recv的timeout参数是超时时间单位秒。如果总线上没有其他节点你会看到10次超时。实际项目中我通常会把收发逻辑封装成类加上错误处理和日志记录。比如总线断开时的重连机制、报文过滤、周期发送等。python-can的文档写得不错需要高级功能的时候直接查官方文档就行。4.3 用Wireshark抓CAN报文做协议分析Wireshark从3.0版本开始支持SocketCAN接口可以直接抓can0上的报文。安装sudo apt install wireshark安装过程中会问你是否允许非root用户抓包选“是”。然后把当前用户加入wireshark组sudo usermod -aG wireshark $USER重新登录后打开Wireshark在接口列表里应该能看到can0。选中它就可以开始抓包了。Wireshark的CAN解析器支持标准帧和扩展帧还能根据DBC文件解析信号做协议分析非常方便。如果你没有DBC文件Wireshark也能显示原始数据你可以手动分析。对于CAN FD报文Wireshark 3.6以后的版本支持得比较好。4.4 长时间运行的稳定性注意事项CAN总线调试经常需要长时间运行比如跑一晚上的压力测试。这时候有几个坑要注意。第一USB设备的电源管理可能导致设备休眠。可以在udev规则里加上POWER_MANAGEMENT相关的设置或者用powertop把USB自动挂起关掉。第二candump长时间运行可能会因为缓冲区满而丢包。可以用-b参数指定缓冲区大小或者把输出重定向到文件避免终端阻塞。第三如果用的是自定义USB驱动长时间运行可能会出现USB通信超时。这种情况下需要在驱动层加心跳检测和重连机制。我遇到过连续跑8小时之后设备无响应的情况后来在应用层加了定时重连才解决。5. 踩坑实录那些让我折腾半天的报错5.1 “SIOCGIFINDEX: No such device”的排查过程这个报错通常出现在你执行ip link set can0 up的时候。意思是内核里没有can0这个网络接口。原因可能有几个一是驱动模块没有加载。用lsmod | grep can确认can、can_raw、can_dev这几个模块是否加载。如果没有手动加载sudo modprobe can sudo modprobe can_raw sudo modprobe can_dev二是设备驱动没有注册SocketCAN接口。即使can模块加载了如果你的设备驱动没有调用alloc_candev和register_candev也不会有can0接口。这种情况下要检查驱动源码确认SocketCAN部分是否正确实现。三是设备根本没被识别。回到lsusb和dmesg确认USB层面是否正常。排查顺序建议是先确认USB识别再确认驱动加载最后确认SocketCAN接口注册。每一步都用对应的命令验证不要跳步。5.2 编译驱动时的内核头文件版本冲突这个坑我踩过不止一次。现象是make的时候报错说找不到某个头文件或者结构体定义不匹配。根本原因是linux-headers-$(uname -r)的版本和当前运行内核不一致。验证方法uname -r dpkg -l | grep linux-headers如果uname -r的输出是5.15.0-91-generic但linux-headers只装了5.15.0-88-generic那就会出问题。解决方法是安装对应版本的头文件sudo apt install linux-headers-$(uname -r)如果apt源里没有这个版本比如你手动升级过内核那就需要去内核官网下载对应的头文件包或者用apt-get install linux-headers-generic让它自动匹配。还有一种情况是源码里的API和新内核不兼容。比如老代码用init_timer新内核要求用timer_setup。这种只能改源码没有捷径。5.3 权限问题导致的“Permission denied”candump can0报Permission denied或者Python脚本打开SocketCAN时报错基本都是权限问题。SocketCAN接口的权限和普通网络接口不太一样。ip link set can0 up需要root权限但candump读取数据理论上不需要root。如果你遇到权限问题检查以下几点一是can0接口是否已经up。用ip link show can0看状态如果是DOWN先up起来。二是当前用户是否在dialout组。虽然SocketCAN不走/dev/tty但某些发行版会把CAN设备归到dialout组管理。三是SELinux或AppArmor是否拦截了。Ubuntu默认用AppArmor一般不会拦CAN操作但如果你装过其他安全软件可能会有影响。用sudo dmesg | grep -i apparmor看有没有相关拒绝日志。5.4 总线速率不匹配导致的“收不到数据”这个坑最隐蔽因为设备状态看起来一切正常can0是UP的candump也在运行但就是没有任何输出。CAN总线要求所有节点的速率必须一致。如果你的分析仪设的是500k但总线上其他节点是250k那你什么都收不到。更麻烦的是速率不匹配不会报错只会静默丢包。确认速率的方法查总线设计文档或者用示波器测CAN_H和CAN_L的波形根据位时间算速率。如果没有文档也没有示波器那就逐个速率试125k、250k、500k、1M每个试一遍看哪个能收到数据。设置速率的命令sudo ip link set can0 down sudo ip link set can0 type can bitrate 250000 sudo ip link set can0 up注意每次改速率之前要先down掉接口否则会报Device or resource busy。5.5 设备插拔后接口消失的处理USB设备的热插拔在Linux下有时候会出问题。你拔掉分析仪再插上can0接口可能就没了或者变成了can1。这是因为驱动在设备断开时没有正确清理重新插入时内核分配了新的接口名。解决方法有两个一是用ip link命令手动重命名sudo ip link set can1 down sudo ip link set can1 name can0 sudo ip link set can0 up二是写udev规则让设备每次插入时都固定映射到同一个接口名。这需要在udev规则里用NAME或者SYMLINK指定。我个人的习惯是写一个启动脚本每次插上设备后跑一下自动完成接口重命名和速率配置。脚本内容大概是这样#!/bin/bash IFACE$(ip link show | grep -o can[0-9] | head -1) if [ -n $IFACE ]; then sudo ip link set $IFACE down sudo ip link set $IFACE type can bitrate 500000 sudo ip link set $IFACE up echo $IFACE is up at 500kbps else echo No CAN interface found fi6. 几个能省时间的实操建议6.1 用虚拟CAN接口做前期验证如果你还没有拿到硬件或者驱动还没搞定可以先创建虚拟CAN接口来验证你的上位机代码。Linux内核支持vcan模块sudo modprobe vcan sudo ip link add dev vcan0 type vcan sudo ip link set up vcan0然后你就可以像操作真实CAN接口一样操作vcan0。candump vcan0和cansend vcan0都能正常工作。这对于开发阶段验证代码逻辑非常有用不用等硬件到位。6.2 把常用命令写成aliasCAN调试涉及的命令比较多每次都敲完整命令很烦。可以在~/.bashrc里加几个aliasalias canupsudo ip link set can0 type can bitrate 500000 sudo ip link set can0 up alias candownsudo ip link set can0 down alias canmoncandump -ta can0 alias cansend123cansend can0 123#这样日常操作会快很多。当然alias只是个人习惯团队协作的话还是建议写脚本方便共享。6.3 记录每次调试的配置参数CAN总线调试涉及很多参数速率、采样点、终端电阻、报文ID、周期等。建议每次调试都记录一份配置清单包括硬件连接方式、软件配置、测试结果。这样下次遇到类似问题可以快速对照也方便团队其他成员复现。我自己的做法是在项目目录下放一个can_debug.md文件每次调试都往里追加记录。时间长了就形成了一份很有价值的参考文档。6.4 关于创芯科技设备选型的个人看法如果你正在选型还没买设备我的建议是优先考虑原生支持SocketCAN的型号。SocketCAN是Linux的标准CAN接口工具链成熟社区支持好遇到问题容易找到解决方案。创芯科技的设备在Windows下确实方便但Linux支持一直是短板。如果团队主要用Linux开发选型时要把Linux兼容性作为重要考量因素。如果已经买了创芯科技的设备那就按这篇文章的流程走。串口方案的设备基本即插即用自定义USB方案的设备需要多花点时间折腾驱动。实在搞不定的话联系厂商技术支持要Linux驱动是最直接的路径。6.5 一个容易被忽略的细节终端电阻CAN总线两端需要各接一个120欧姆的终端电阻。很多USB-CAN分析仪内部已经集成了终端电阻可以通过跳线或者软件开关控制。如果你的分析仪终端电阻是使能的而总线上其他节点也有终端电阻那总电阻就会偏低导致通信不稳定甚至完全无法通信。排查方法用万用表测CAN_H和CAN_L之间的电阻正常应该是60欧姆左右两个120欧姆并联。如果测出来是40欧姆或者更低说明终端电阻太多了。如果测出来是120欧姆说明只有一端有电阻。如果测出来是无穷大说明两端都没有电阻。这个问题在实验室环境下特别容易遇到因为大家经常把多个设备挂到同一总线上做测试终端电阻的配置很容易乱。我建议每次搭建测试环境时都先测一下总线电阻确认无误再上电通信。
返回列表