RTT小师弟 · 2022年03月22日

【N32G457 】基于RT-Thread和N32G457的USB2CAN调试器

在这里插入图片描述本文是RT-Thread用户@文武兵兵原创发布,是用于参加RT-Thread与国民技术联手推出N32G457 RT-Thread设计大赛,原文:https://club.rt-thread.org/as...

介绍

一个简洁方便的的usb2can调试器,可用于can总线数据调试和一般的can总线故障排查。在基于RT-Thread和N32G457的软硬件平台的基础上,使用SLCAN协议配合USB CDC类通信可以实现将can数据转发到PC或者上位机上,供上位机软件进行分析。

主要功能

  • 可以实现接收can总线数据收发功能,从can总线发送到usb上位机或者从usb上位机发送到can总线。
  • 可以设置can波特率,支持扩展帧和远程帧。
  • slcan通用协议,ascii字符可以直接通过串口查看数据,linux工具can-utils中的slcan_attach、slcand、slcanpty可以直接驱动此协议转换成linux下的socketcan。
  • usb cdc免驱可以实现win10、linux即插即用。
  • 同时还有 python-can 、cantact-app等多种工具实现can数据采集分析。

硬件和软件框架

硬件上使用 国民技术提供的N32G45XVL-STB v1.1开发版加上一个TJA1050的can收发器。

硬件描述
芯片型号N32G457VEL7
CPUARM Cortex M4
主频144M 180DMIPS
片内SRAM144K
片内FLASH512K
串口7路 (UART4路 USART3路)
USB全速USB 2.0接口
CAN2路 CAN 2.0A/B总线接口
从硬件到软件

硬件上主要使用USB和CAN功能。

  • USB作为USB device设备,实现一个全速的usb cdc功能,再通过rtthread的device框架注册成为一个字符设备 vcom 。上层应用可以通过vcom设备直接与PC上位机通信。
  • CAN接口,原本N32G457应该有两路can接口,但是由于使用了usb device,can1和usb是公用fifo和中断号的所以没法同时使用。所以只使用了can2,同样can2也是注册到rtthread的device框架上的。可以直接通过rtdevice的api进行读写配置波特率等操作,这也方便后面的slcan进行配置can参数。同时slcan的核心代码可移植性更高。
从软件到硬件

硬件部分实现好后,软件部分通过rtthread的api就可以完成大部分操作了。主要驱动代码和应用层代码,逻辑处理代码。

USB CDC驱动代码,主要是usb cdc的vcom驱动,因为暂时还没有N32G457的usb device驱动能注册到rtdevice去,所以直接用N32G457的SDK提供的例程做出来的USB CDC,然后在此基础上注册一个字符设备vcom到rtdevice框架上,提供对cdc的读写接口。

can驱动,还有就是can驱动。在做这个东西的时候发现没有can驱动,于是参考sdk的例程写了一个驱动注册到rtdevice框架上。

slcan代码,接下来就是最重要的slcan应用层代码了。

应用层代码主要通过一个rt_slcan_t结构体记录slcan的配置和上下文状态。然后通过启动一个线程用来监听vcom和can的数据,接收到数据立马处理。

如果是来自vcom端的数据,是以\r结尾ascii字符串,需要做一个帧完整性判断用来判断是不是接收到完整的一帧ascii字符数据包。接收完整性判断通过后再判断发送的哪些命令,然后根据具体的命令需要发送CAN数据包到CAN控制器的发送到can设备去,需要执行命令的执行命令然后返回ack。

主要的ascii命令格式是

第一个字节格式描述
t<cmd> <id> <dlc> <data><time>发送11bit ID的数据帧
r<cmd> <id> <dlc><time>发送11bit ID的远程帧
T<cmd> <id> <dlc> <data><time>发送29bit ID的数据帧
R<cmd> <id> <dlc><time>发送29bit ID的远程帧
O<cmd>打开can
C<cmd>关闭can
V<cmd>显示版本号
N<cmd>显示串口号
F<cmd>读取can状态
s<cmd><value>设置can波特率 0 - 8
Z<cmd><value>设置ascii数据是否带时间

<cmd> 命令, 1个字节

<id> can的id,标准帧3个字节,扩展帧8个字节,hex表示

<dlc> can的dlc数据长度,1个字节,hex表示

<data>数据,根据dlc长度从0字节到16字节变化,hex表示

<time>时间,4个字节,hex表示

常见slcan命令示例:

ascii命令描述
t123166标准canid 0x123, 长度1, 数据 0x66
T123456783112233扩展canid 0x12345678, 长度3, 数据 0x11 0x22 0x33
r1260标准canid 0x126, 长度 0, 远程请求帧
T12345679扩展canid 0x12345679, 长度0, 远程请求帧

如果是来自can设备端的数据,就直接打包成ascii通过vcom发送出去就可以了。

软硬件架构图

rtt-n32-slcan.jpg

slcan逻辑图

rt-n32-slcan-loop.jpg

演示图片

使用串口工具直接打开串口,就可以看到can总线发送的数据,并且已经十六进制ascii格式,很方便阅读。发送数据到can总线也只需要按格式发送即可,每个命令结尾必须是0x0d。
QQ20220317224933.jpg

python程序采集can数据。

通过python-can库可以很方便打开slcan协议的设备获取数据,还可以将采集到的数据保存到日志文件中。脚本放在git仓库的test目录,安装号库就可以使用了。

import can
import threading
import time
import random

def print_message(msg):
    print(msg)

if __name__ == "__main__":
    # RX part
    #bus_rx = can.interface.Bus('virtual_ch', bustype='virtual')
    canbus = can.interface.Bus('COM32', bustype='slcan')
    
    logger = can.Logger("logfile.asc")  # save log to asc file
    listeners = [
        print_message,  # Callback function, print the received messages
        logger,  # save received messages to asc file
    ]
    notifier = can.Notifier(canbus, listeners)

    running = True
    while running:
        input()
        running = False

    # It's important to stop the notifier in order to finish the writting of asc file
    notifier.stop()
    # stops the bus
    canbus.shutdown()

QQ20220317225728.jpg

演示视频

https://www.bilibili.com/vide...

代码地址

gitee仓库地址 https://gitee.com/cazure/n32g...

推荐阅读
关注数
8074
内容数
181
小而美的物联网操作系统,经过14年的累积发展,RT-Thread 已经拥有一个国内最大的嵌入式开源社区,同时被广泛应用于能源、车载、医疗、消费电子等多个行业,累积装机量超过4亿台,成为国人自主开发、国内最成熟稳定和装机量最大的开源 RTOS。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息