目錄
一、啟用本機(jī)的 VCAN? 編輯
1.1? 加載本機(jī)的 vcan
1.2? 添加本機(jī)的 vcan0
1.3? 查看添加的 vcan0
1.4? 開啟本機(jī)的 vcan0
1.5? 關(guān)閉本機(jī)的 vcan0
1.6? 刪除本機(jī)的 vcan0
二、測試本機(jī)的 VCAN
2.1? CAN 發(fā)送數(shù)據(jù) 代碼
2.2? CAN 接收數(shù)據(jù) 代碼
2.3? CMakeLists.txt 代碼
2.4? 虛擬 CAN 收發(fā)測試
三、VCAN 的其它操作
3.1? 啟用 VCAN
3.2? 關(guān)閉 VCAN
3.3? 重啟 VCAN
3.4? 停止 VCAN
3.5? 設(shè)備波特率
3.6? 顯示 VCAN 詳情
3.7? VCAN 回環(huán)測試
3.8? 發(fā)送 VCAN 數(shù)據(jù)
3.9? 接收 VCAN 數(shù)據(jù)
3.10? 查看 VCAN 狀態(tài)
3.11? VCAN 數(shù)據(jù)過濾文章來源:http://www.zghlxwxcb.cn/news/detail-774268.html
當(dāng)沒有CAN設(shè)備時(shí),可使用 Ubuntu 的虛擬 CAN 進(jìn)行通訊測試。文章來源地址http://www.zghlxwxcb.cn/news/detail-774268.html
一、啟用本機(jī)的 VCAN
? 1.1 加載本機(jī)的 vcan
# 加載虛擬 CAN:
sudo modprobe vcan
? 1.2 添加本機(jī)的 vcan0
# 添加 VCAN0 到操作系統(tǒng):
sudo ip link add dev can0 type vcan
? 1.3 查看添加的 vcan0
# 查看 CAN0 :
ifcon?g -a
? 1.4 開啟本機(jī)的 vcan0
# 開啟 CAN0 :
sudo ip lin
? 1.5 關(guān)閉本機(jī)的 vcan0
# 關(guān)閉 CAN0 :
sudo ip link set dev can0 down
? 1.6 刪除本機(jī)的 vcan0
# 刪除 CAN0 :
sudo ip link del dev can0
二、測試本機(jī)的 VCAN
? 2.1 CAN 發(fā)送數(shù)據(jù) 代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char* argv[]) {
int skt = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (0 > skt) {
perror("create socket error");
return -1;
}
// 指定 can0 設(shè)備
struct ifreq ifr = { 0 };
strcpy(ifr.ifr_name, "vcan0");
ioctl(skt, SIOCGIFINDEX, &ifr);
struct sockaddr_can addr = { 0 };
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
// 將 can0 與套接字進(jìn)行綁定
int rv = bind(skt, (struct sockaddr*)&addr, sizeof(addr));
if (rv < 0) {
perror("bind socket error");
close(skt);
return -2;
}
// 設(shè)置過濾規(guī)則:不接受任何報(bào)文、僅發(fā)送數(shù)據(jù)
setsockopt(skt, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
// 發(fā)送數(shù)據(jù)
struct can_frame frame = { 0 };
frame.can_id = 0x123;
frame.can_dlc = 6; {
frame.data[0] = 0xA0;
frame.data[1] = 0xB0;
frame.data[2] = 0xC0;
frame.data[3] = 0xD0;
frame.data[4] = 0xE0;
frame.data[5] = 0xF0;
}
unsigned short index = 0;
while (true) {
// 開始發(fā)送數(shù)據(jù)
rv = write(skt, &frame, sizeof(frame));
if (sizeof(frame) != rv) {
perror("write can frame failed");
break;
} else {
printf("send count : %d \n", ++index);
sleep(1); // 1 second
}
}
close(skt);
return 0;
}
? 2.2 CAN 接收數(shù)據(jù) 代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char* argv[]) {
int skt = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (0 > skt) {
perror("create socket error");
return -1;
}
// 指定 can0 設(shè)備
struct ifreq ifr = { 0 };
strcpy(ifr.ifr_name, "vcan0");
ioctl(skt, SIOCGIFINDEX, &ifr);
struct sockaddr_can addr = { 0 };
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
// 將 can0 與套接字進(jìn)行綁定
int rv = bind(skt, (struct sockaddr*)&addr, sizeof(addr));
if (0 > rv) {
perror("bind error");
close(skt);
return -2;
}
// 設(shè)置過濾規(guī)則
// setsockopt(skt, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
// 接收數(shù)據(jù)
struct can_frame frame = { 0 };
while (true) {
rv = read(skt, &frame, sizeof(struct can_frame));
if (rv < 0) {
perror("read can frame error");
break;
}
// 校驗(yàn)是否接收到錯(cuò)誤幀
if (frame.can_id & CAN_ERR_FLAG) {
printf("error can frame \n");
break;
}
// 校驗(yàn)幀格式
if (frame.can_id & CAN_EFF_FLAG) {
printf("擴(kuò)展幀 <0x%08x> ", frame.can_id & CAN_EFF_MASK);
} else {
printf("標(biāo)準(zhǔn)幀 <0x%03x> ", frame.can_id & CAN_SFF_MASK);
}
// 校驗(yàn)幀類型:數(shù)據(jù)幀還是遠(yuǎn)程幀
if (frame.can_id & CAN_RTR_FLAG) {
printf("remote request frame \n");
continue;
}
// 打印數(shù)據(jù)
printf("[%d] ", frame.can_dlc);
for (int idx = 0; idx < frame.can_dlc; idx++) {
printf("%02x ", frame.data[idx]);
} printf("\n");
}
close(skt);
return 0;
}
? 2.3 CMakeLists.txt 代碼
cmake_minimum_required(VERSION 3.0)
# 設(shè)置統(tǒng)一輸出目錄
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
# 設(shè)置統(tǒng)一鏈接目錄
link_directories(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY})
link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY})
# 主要工程項(xiàng)目
add_executable(vcan_recv vcan_recv.cpp)
add_executable(vcan_send vcan_send.cpp)
?? 2.4 虛擬 CAN 收發(fā)測試
?? 三、VCAN 的其它操作
# 安裝 can 工具包:
sudo apt install can-utils
? 3.1 啟用 VCAN
# 啟用 CAN
sudo ip link set vcan0 up
? 3.2 關(guān)閉 VCAN
# 關(guān)閉 CAN
sudo ip link set vcan0 down
? 3.3 重啟 VCAN
# 重啟CAN
sudo canconfig vcan0 restart
? 3.4 停止 VCAN
# 停止CAN
sudo canconfig vcan0 stop
? 3.5 設(shè)備波特率
# 設(shè)置波特率
sudo ip link set vcan0 up type can bitrate 250000
? 3.6 顯示 VCAN 詳細(xì)信息
# 顯示 CAN 詳細(xì)信息
sudo ip -details link show vcan0
?3.7 VCAN 回環(huán)測試
# 回環(huán)測試
sudo canconfig vcan0 ctrlmode loopback on
?3.8 發(fā)送 VCAN 數(shù)據(jù)
# 向 CAN 總線發(fā)送數(shù)據(jù)
sudo cansend vcan0 --identifier=ID+數(shù)據(jù)
? 3.9 接收 VCAN 數(shù)據(jù)
# 接收 CAN 總線數(shù)據(jù)
sudo candump vcan0
? 3.10 查看 VCAN 狀態(tài)
# 查看CAN總線狀態(tài)
sudo canecho vcan0
? 3.11 VCAN 數(shù)據(jù)過濾
# 使用濾波器接收 ID 匹配的數(shù)據(jù)
sudo candump vcan0 --filter=ID:mask
到了這里,關(guān)于Ubuntu20.04 上啟用 VCAN 用作本地調(diào)試的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!