基于工控机的CAN协议控制设备的操作

CAN协议(Controller Area Network)则是一种用于汽车和工业应用的串行通信协议,具有高性能、低成本和灵活性等特点。

在Linux系统中设置CAN接口;

首先,使用ifconfig -a命令查看系统中所有的网络接口,包括CAN接口(如can0、can1等)。

ip link set can0 type can bitrate 500000网络接口,包括CAN接口(如can0、can1等)。

启动CAN接口:ifconfig can0 up

发送和接收CAN消息:使用candump、cansend;

举个例子:

向can0设备,id为0x604发送0x00,0x01;

下面用TCP链接服务器并通过服务器向can设备发送控制命令的一个代码示例:

tcp配合can,发送控制信息给设备,实现驱动;

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/can.h>
#include <linux/can/raw.h>

// 服务器地址信息
const char* serverIP = "192.168.1.2";
const int serverPort = 8080;
// 客户端地址信息
const char* clientIP = "192.168.1.1";
const int clientPort = 8085;

// 创建CAN套接字并向设备can0的0x0发送数据
void sendCANMessage1(uint16_t can_id,uint8_t data0,uint8_t data1)  {
 
 int soc;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;
//   struct can_frame frame0;


    if ((soc = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        std::cerr << "Failed to open CAN socket" << std::endl;
        return;
    }

    strcpy(ifr.ifr_name, "can0");
    ioctl(soc, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    if (bind(soc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        std::cerr << "Failed to bind CAN socket" << std::endl;
        close(soc);
        return;
    }

 frame.can_id = can_id;
    frame.can_dlc = 2;  // Data Length Code
    frame.data[0] = data0;
    frame.data[1] = data1;
 if (write(soc, &frame, sizeof(frame)) != sizeof(frame)) {
        std::cerr << "Failed to write to CAN socket" << std::endl;
    }

    close(soc);
}


// 创建CAN套接字并向设备can0的0x604发送数据
void sendCANMessage(uint16_t can_id,uint8_t data0,uint8_t data1,uint8_t data2,uint8_t data3,uint8_t data4,uint8_t data5,uint8_t data6,uint8_t data7) {
    int soc;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame;
//   struct can_frame frame0;


    if ((soc = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        std::cerr << "Failed to open CAN socket" << std::endl;
        return;
    }

    strcpy(ifr.ifr_name, "can0");
    ioctl(soc, SIOCGIFINDEX, &ifr);

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;

    if (bind(soc, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        std::cerr << "Failed to bind CAN socket" << std::endl;
        close(soc);
        return;
    }

    frame.can_id = can_id;
    frame.can_dlc = 8;  // Data Length Code
    frame.data[0] = data0;
    frame.data[1] = data1;
    frame.data[2] = data2;
    frame.data[3] = data3;
    frame.data[4] = data4;
    frame.data[5] = data5;
    frame.data[6] = data6;
    frame.data[7] = data7;

    if (write(soc, &frame, sizeof(frame)) != sizeof(frame)) {
        std::cerr << "Failed to write to CAN socket" << std::endl;
    }

    close(soc);
}

int main() {
    // 创建TCP套接字
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (clientSocket == -1) {
        std::cerr << "Failed to create TCP socket" << std::endl;
        return -1;
    }

    // 设置客户端地址
    struct sockaddr_in clientAddr;
    memset(&clientAddr, 0, sizeof(clientAddr));
    clientAddr.sin_family = AF_INET;
    clientAddr.sin_port = htons(clientPort);
    inet_pton(AF_INET, clientIP, &(clientAddr.sin_addr));

    // 绑定到客户端地址
    if (bind(clientSocket, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) == -1) {
        std::cerr << "Failed to bind TCP socket to client address" << std::endl;
        close(clientSocket);
        return -1;
    }

    // 设置服务器地址
    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(serverPort);
    inet_pton(AF_INET, serverIP, &(serverAddr.sin_addr));

    // 连接到服务器
    if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == -1) {
        std::cerr << "Failed to connect to server" << std::endl;
        close(clientSocket);
        return -1;
    }

    // 接收和处理消息
    char buffer[1024];
    while (true) {
        ssize_t recvSize = recv(clientSocket, buffer, sizeof(buffer), 0);
        if (recvSize <= 0) {
            std::cerr << "Failed to receive message from server" << std::endl;
            break;
        } else {
            buffer[recvSize] = '\0';
            if (strcmp(buffer, "start") == 0) {
               // 向设备can0的0x604发送0x11
               sendCANMessage1(0x0,0x1,0x2);
               sendCANMessage1(0x0,0x1,0x4);
               

		 sendCANMessage(0x604,0x2F,0x60,0x60,0x00,0x03,0x00,0x00,0x00);
                sendCANMessage(0x604,0x23,0xFF,0x60,0X00,0xE8,0x03,0x00,0x00);
                sendCANMessage(0x604,0x23,0x83,0x60,0X00,0x88,0x13,0x00,0x00);
                sendCANMessage(0x604,0x23,0x84,0x60,0X00,0x88,0x13,0x00,0x00);
                sendCANMessage(0x604,0x2B,0x40,0x60,0X00,0x06,0x00,0x00,0x00);
                sendCANMessage(0x604,0x2B,0x40,0x60,0X00,0x07,0x00,0x00,0x00);
                sendCANMessage(0x604,0x2B,0x40,0x60,0X00,0x0F,0x00,0x00,0x00);

               std::cout << "Sent open to CAN" << std::endl;
            } else if (strcmp(buffer, "stop") == 0) {
                // 向设备can0的0x604发送0x17
                sendCANMessage(0x604, 0x2B, 0x40,0x60,0X00,0x07,0x00,0x00,0x00);
                std::cout << "Sent stop to CAN" << std::endl;
            } else if (strcmp(buffer, "10") == 0) {
                sendCANMessage(0x604,0x23,0xFF,0x60,0X00,0xE8,0x10,0x00,0x00);
                sendCANMessage(0x604,0x2B,0x40,0x60,0X00,0x0F,0x00,0x00,0x00);

                std::cout << "Received message: " << buffer << std::endl;
            }else if (strcmp(buffer, "3") == 0) {
                sendCANMessage(0x604,0x23,0xFF,0x60,0X00,0xE8,0x03,0x00,0x00);
                sendCANMessage(0x604,0x2B,0x40,0x60,0X00,0x0F,0x00,0x00,0x00);

                std::cout << "Received message: " << buffer << std::endl;
            }else {
                std::cout << "Received message: " << buffer << std::endl;

	    }

        }
  

    close(clientSocket);
    return 0;
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值