USB-TO-CAN 读取数据【SocketCAN】

设备:

系统: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

运行效果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值