html网站登录界面模板,免费的外链网站,在线图片编辑器下载,丹阳建设工程管理处网站文章目录 CAN总线回环测试第一种基于板载CAN测试第一步确认板载是否支持第二步关闭 CAN 接口将 CAN 接口置于非活动状态第三步 配置 CAN 接口第一步 设置 CAN 接口比特率第二步 设置 CAN 启用回环模式第三步 启用 CAN 接口 第四步 测试CAN总线回环捕获 CAN 消息发送 CAN 消息 第… 文章目录 CAN总线回环测试第一种基于板载CAN测试第一步确认板载是否支持第二步关闭 CAN 接口将 CAN 接口置于非活动状态第三步 配置 CAN 接口第一步 设置 CAN 接口比特率第二步 设置 CAN 启用回环模式第三步 启用 CAN 接口 第四步 测试CAN总线回环捕获 CAN 消息发送 CAN 消息 第二种基于Linux库的原生开发1. 确认硬件支持2. 配置 CAN 接口3. 使用 SocketCAN API 编写应用程序创建 CAN 套接字绑定 CAN 接口发送和接收 CAN 消息示例代码 4. 应用程序测试 CAN总线回环测试
第一种基于板载CAN测试
第一步确认板载是否支持
确保你的硬件支持 CAN并且已经正确安装了驱动程序。可以通过以下命令检查是否检测到了 CAN 设备
ip link show type can可以看到板载自带了can0和can1. can0 和 can1是接口的名称分别表示系统中的第一个和第二个 CAN 接口。
NOARP,ECHO NOARP表示该接口不使用 ARP地址解析协议。CAN 总线不需要 ARP 因为它不是基于 IP 的网络。 ECHO可能启用了回环模式发送的消息会被自己的 CAN 控制器重新接收。这里不确定是否启用了可以用指令ip -details link show 查看到 或者单看can0can1的状态以can0为例子
ip -details link show can0mtu 16最大传输单元Maximum Transmission Unit对于 CAN 接口来说MTU 通常是 16 字节这是因为 CAN 消息的最大有效载荷是 8 字节加上一些额外的头部信息。
qdisc noop队列调度算法Queueing Discipline这里使用的是 noop即空操作队列调度器。这意味着没有任何包调度策略被应用所有数据包将直接传递而不会排队。
state DOWN当前接口状态为关闭DOWN意味着接口未激活无法进行通信。要激活接口可以使用 ip link set can0 up 或 ip link set can1 up。
mode DEFAULT表示接口的工作模式默认情况下是标准模式。
group default指明这个接口属于哪个组default 是默认组。
qlen 10队列长度Queue Length表示可以排队等待处理的数据包数量在这里是 10。
链路类型 link/can表明这是一个 CAN 类型的接口。 第二步关闭 CAN 接口将 CAN 接口置于非活动状态
如果没有激活的情况直接跳过此步
ip link set can0 down第三步 配置 CAN 接口
第一步 设置 CAN 接口比特率
ip link set can0 type can bitrate 500000ip link set这是一个用来配置网络接口的命令。 can0指定要配置的网络接口名称这里是 can0。 type can指明该接口是 CAN 类型的。 bitrate 500000设置 CAN 总线的数据传输速率比特率为 500 kbps。这个值应该根据你的硬件支持和需求进行调整。
设置完可以借助指令查看
ip -details link show can0第二步 设置 CAN 启用回环模式
指令
ip link set can0 type can loopback onloopback on启用回环模式。在这种模式下所有从 CAN 控制器发出的消息都会被重新送回到同一个控制器而不会真正发送到物理总线上。这对于测试非常有用因为它允许你在不连接任何其他设备的情况下验证软件是否正常工作。 设置完同样可以借助指令查看
ip -details link show can0第三步 启用 CAN 接口
指令
ip link set can0 up启动成功后同样可以借助指令查看
ip -details link show can0第四步 测试CAN总线回环
捕获 CAN 消息
使用 nohup 和 candump 捕获消息并记录到文件
nohup candump can0 log.txt nohup使程序在用户退出终端后继续运行。这对于长时间运行的任务很有用。 candump这是 Linux 下的一个工具用于捕获并显示 CAN 消息。它会实时监听指定的 CAN 接口并输出接收到的消息。 can0指定要监听的 CAN 接口。 log.txt将 candump 的输出重定向到一个名为 log.txt 的文件中而不是打印到屏幕上。 将命令放入后台执行这样可以在同一终端窗口中继续输入其他命令。 发送 CAN 消息
标准数据帧发8位数据
cansend can0 0B000123#00.00.00.00.00.00.00.01#后面每一位数据不加.也行注意别发错了
cansend这是 Linux 下的一个工具用于向指定的 CAN 接口发送 CAN 消息。 can0指定要使用的 CAN 接口。
0B000123#00.00.00.00.00.00.00.01这是要发送的 CAN 消息格式。 具体来说0B000123是 CAN ID其中 0B 表示标准帧格式11位ID000123是具体的 ID 值。 #分隔符后面跟着的是数据字段。00.00.00.00.00.00.00.01 是数据字段的内容表示 8 字节的数据。每个字节用两位十六进制数表示。 其实都用默认就是标准数据帧
cansend can0 123#00.00.00.00.00.00.00.02数据也可以发0-8任意字节
cansend can0 234#88第二种基于Linux库的原生开发
在 Linux 下进行 CAN 总线应用开发时通常需要通过系统调用和特定的套接字 API 来与 CAN 接口交互。Linux 内核提供了一个叫做 SocketCAN 的子系统它使得 CAN 通信可以像普通的网络编程一样使用标准的 BSD 套接字接口来实现。下面是进行 CAN 应用开发的基本步骤
1. 确认硬件支持
ip link show type can加粗样式 可以看到板载自带了can0和can1. 2. 配置 CAN 接口
先关闭can接口
ip link set can0 down配置波特率
ip link set can0 type can bitrate 500000如果使用回环如下操作不使用或者使用正常模式就跳过此步我这里采用回环测试因此执行此步骤
ip link set can0 type can loopback on启动can接口
ip link set can0 up至此所有配置完成 3. 使用 SocketCAN API 编写应用程序
创建 CAN 套接字
在 C/C 中可以通过 socket() 函数创建一个 CAN 套接字。例如
#include sys/socket.h
#include linux/can.h
#include linux/can/raw.hint s;
if ((s socket(PF_CAN, SOCK_RAW, CAN_RAW)) 0) {perror(Socket creation failed);return -1;
}绑定 CAN 接口
接下来将套接字绑定到具体的 CAN 接口如 can0。这可以通过 bind() 函数完成
struct ifreq ifr;
struct sockaddr_can addr;addr.can_family AF_CAN;
strcpy(ifr.ifr_name, can0);if (ioctl(s, SIOCGIFINDEX, ifr) 0) {perror(Interface index get failed);close(s);return -1;
}addr.can_ifindex ifr.ifr_ifindex;if (bind(s, (struct sockaddr *)addr, sizeof(addr)) 0) {perror(Bind to CAN interface failed);close(s);return -1;
}发送和接收 CAN 消息
struct can_frame frame;// 构造要发送的 CAN 帧
frame.can_id 0x123; // CAN ID
frame.can_dlc 8; // 数据长度码DLC表示数据域的字节数
memset(frame.data, 0x01, frame.can_dlc); // 设置数据域内容// 发送 CAN 帧
if (write(s, frame, sizeof(struct can_frame)) ! sizeof(struct can_frame)) {perror(Write CAN frame failed);close(s);return -1;
}// 接收 CAN 帧
if (read(s, frame, sizeof(struct can_frame)) ! sizeof(struct can_frame)) {perror(Read CAN frame failed);close(s);return -1;
}printf(Received CAN ID%x, DLC%d\n, frame.can_id, frame.can_dlc);
for (int i 0; i frame.can_dlc; i)printf(Data[%d]: %02x\n, i, frame.data[i]);示例代码
下面是一段完整的示例代码展示了如何创建 CAN 套接字、绑定接口、发送和接收消息:
这里我开启了线程父线程用来写子线程用来读代码被屏蔽掉的那部分是禁止回环模式的为了防止配置的时候关闭回环失败因此软件上再关闭一次。
#include can_config.h#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include signal.h
#include libgen.h
#include getopt.h
#include limits.h#include sys/types.h
#include sys/socket.h
#include sys/uio.h
#include sys/ioctl.h
#include net/if.h#include linux/can.h
#include linux/can/raw.hint main()
{int s; // 就是fdint n_read 0; // 读取到的数据个数//创建 CAN 套接字if ((s socket(PF_CAN, SOCK_RAW, CAN_RAW)) 0) {perror(Socket creation failed);return -1;}printf(socket ok \n);/*// 禁用回环模式如果需要int loopback 0; // 0 表示关闭回环模式if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, loopback, sizeof(loopback)) 0) {perror(Failed to disable loopback mode);close(s);return -1;}// 禁用监听自己的消息可选int recv_own_msgs 0; // 0 表示关闭接收自己的消息if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, recv_own_msgs, sizeof(recv_own_msgs)) 0) {perror(Failed to disable receiving own messages);close(s);return -1;}*/// 绑定 CAN 接口struct ifreq ifr;struct sockaddr_can addr;addr.can_family AF_CAN;strcpy(ifr.ifr_name, can0);if (ioctl(s, SIOCGIFINDEX, ifr) 0) {perror(Interface index get failed);close(s);return -1;}addr.can_ifindex ifr.ifr_ifindex;if (bind(s, (struct sockaddr *)addr, sizeof(addr)) 0) {perror(Bind to CAN interface failed);close(s);return -1;}printf(bind ok \n);// 构造要发送的 CAN 帧struct can_frame wirte_frame;struct can_frame recive_frame;wirte_frame.can_id 0x123; // CAN IDwirte_frame.can_dlc 8; // 数据长度码DLC表示数据域的字节数memset(wirte_frame.data, 0x01, wirte_frame.can_dlc); // 设置数据域内容int data 0x01;//开启线程 一个接收一个发送;__pid_t pid;pid fork();//返回的pid号 父进程是正数id号码子进程是0// 父进程 write 子进程接收if(pid0){printf(in farther ok \n);while(1){// 发送 CAN 帧 间隔3秒写一次if (write(s, wirte_frame, sizeof(struct can_frame)) ! sizeof(struct can_frame)) {perror(Write CAN frame failed);close(s);return -1;}sleep(3);memset(wirte_frame.data,data, wirte_frame.can_dlc); // 设置数据域内容} }else if(pid0){printf(in son ok \n);while(1){// 接收 CAN 帧if ((n_read read(s, recive_frame, sizeof(struct can_frame)) )! sizeof(struct can_frame)) {perror(Read CAN frame failed);close(s);return -1;}if(n_read0){printf(Received CAN ID%x, DLC%d\n, recive_frame.can_id, recive_frame.can_dlc);for (int i 0; i recive_frame.can_dlc; i)printf(Data[%d]: %02x\n, i, recive_frame.data[i]);}}}else{perror(fork error\n);}close(s);return 0 ;
}
4. 应用程序测试
先用交叉编译工具编译
arm-linux-gnueabi-gcc mycan.c -o mycan远程发送到板子
scp ./mycan root192.168.1.101:/root/zhua执行 适当改一改代码 再测试 这里有个小问题就是write一直写FIFO文件队列会满然后就是溢出报错因此要学习错误处理等操作。
所以最后关于帧格式位同步仲裁错误处理等可以深入了解。推荐在学习stm32的时候学习寄存器配置开发可以深入的了解到。