设备:

系统:Ubuntu 18.04.6 LT
内核:5.4.0-150-generic
驱动:
tar -xzf peak-linux-driver-8.17.0.tar.gz
cd peak-linux-driver-8.17.0
编译:
make clean
make
sudo make install
加载:
sudo modprobe peak_usb
启用:
sudo ip link set can0 down
sudo ip link set can0 type can bitrate 500000
sudo ip link set can0 up
验证:
ip -details link show can0
查看:总线有节点发布数据:id=0x012,数据为0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
# 抓包
candump can0
# 如果想发送一帧数据
cansend can0 123#1122334455667788
通过 PCAN-VIEW 查看【这里我们看到0x123数据收到】

回到主题,代码应该怎么写呢?
这里给出一个测试文件socketcan_example.c 和 Makefile
1.socketcan_example.c
/*
# ******************************************************
# Author : Jetaime
# Last modified: 2025-07-07
# Email : stay2616@126.com
# Website : www.niyouduo.com
# Filename : socketcan_example.c
# Description : Minimal SocketCAN send/receive demo
# ******************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
int main() {
int s;
struct sockaddr_can addr;
struct ifreq ifr;
// 创建 CAN RAW socket
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Socket");
return 1;
}
// 使用 can0
strcpy(ifr.ifr_name, "can0");
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
// 绑定 socket
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("Bind");
return 1;
}
printf("SocketCAN (can0) initialized.\n");
// 发一帧
struct can_frame frame;
frame.can_id = 0x123;
frame.can_dlc = 4;
frame.data[0] = 0x11;
frame.data[1] = 0x22;
frame.data[2] = 0x33;
frame.data[3] = 0x44;
if (write(s, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame)) {
perror("Write");
return 1;
}
printf("Sent CAN frame: ID=0x123, Data={0x11, 0x22, 0x33, 0x44}\n");
printf("Waiting for CAN frames (Ctrl+C to stop)...\n");
while (1) {
struct can_frame recv_frame;
int nbytes = read(s, &recv_frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("Read");
break;
} else if (nbytes < sizeof(struct can_frame)) {
fprintf(stderr, "Incomplete CAN frame\n");
continue;
}
printf("Received CAN frame: ID=0x%X, DLC=%d, Data={", recv_frame.can_id, recv_frame.can_dlc);
for (int i = 0; i < recv_frame.can_dlc; i++) {
printf("0x%02X", recv_frame.data[i]);
if (i < recv_frame.can_dlc - 1) printf(", ");
}
printf("}\n");
usleep(100000);
}
close(s);
return 0;
}
2.Makefile
CC = gcc
CFLAGS = -Wall -O2
TARGET = socketcan_example
all: $(TARGET)
$(TARGET): socketcan_example.c
$(CC) $(CFLAGS) -o $(TARGET) socketcan_example.c
clean:
rm -f $(TARGET)
3.make & ./ socketcan_example

在这里补充一个:run_can.sh
#!/bin/bash
# ====================================
# 自动配置 SocketCAN can0 并运行程序
# ====================================
# 配置项
CAN_IF="can0"
BITRATE="500000"
EXEC="./socketcan_example" # 你的可执行文件名
# 检查是否有 can0
if ! ip link show "$CAN_IF" > /dev/null 2>&1; then
echo "❌ Error: Interface $CAN_IF not found. Is your PCAN-USB connected?"
exit 1
fi
echo "✅ Found interface: $CAN_IF"
# 如果没 UP,先 Down 再 Up
state=$(ip link show "$CAN_IF" | grep -o "state [A-Z]*" | awk '{print $2}')
if [ "$state" != "UP" ]; then
echo "⚙️ Configuring $CAN_IF with bitrate ${BITRATE}..."
sudo ip link set "$CAN_IF" down
sudo ip link set "$CAN_IF" type can bitrate "$BITRATE"
sudo ip link set "$CAN_IF" up
echo "✅ $CAN_IF is now UP!"
else
echo "✅ $CAN_IF already UP!"
fi
# 最终检查
echo "📡 Current $CAN_IF status:"
ip -details link show "$CAN_IF"
# 运行程序
echo "🚀 Running $EXEC ..."
$EXEC
运行效果:

2991

被折叠的 条评论
为什么被折叠?



