CAN application programming

In this chapter, we learn CAN application programming. CAN is one of the most widely used field buses. It is mainly used in automotive electronics and industrial fields, especially in the automotive field. A large number of sensors and modules on cars are connected through the CAN bus. CAN bus is currently one of the hot technologies in the field of automation. Due to its high reliability, CAN bus is currently widely used in industrial automation, ships, automobiles, medical and industrial equipment, etc.
Our I.MX6U ALPHA/Mini development board provides a CAN interface, which can be used for CAN bus communication. In this chapter, we will learn how to write a simple application to test the CAN interface on the development board. It should be noted that this chapter will not give you an in-depth explanation of CAN application programming. Similarly, CAN bus technology is also a very professional technical direction. The author is not engaged in this field and has very little understanding of the use and understanding of CAN. Therefore, this chapter also aims to guide everyone to get started!

Basics of CAN

Before learning CAN application programming, this section briefly introduces the basic knowledge of CAN.
The content of this section refers to the "CAN Getting Started Tutorial" written by Renesas Electronics. This manual has been provided to everyone in the development board information package. The path is: 4. Reference Materials->CAN Getting Started Tutorial.pdf.

What is CAN?

CAN is the abbreviation of Controller Area Network (hereinafter referred to as CAN), which is the controller area network and is an ISO internationally standardized serial communication protocol.
The CAN bus was originally developed by the German electrical company Bosch. Its initial motivation was to solve the communication between the huge electronic control systems in modern automobiles and reduce the ever-increasing number of signal lines. So, they designed a single network bus on which all peripheral devices could be connected.
In the current automobile industry, due to the requirements for safety, comfort, convenience, low pollution, and low cost, various electronic control systems have been developed, and there are more and more electronic control systems on vehicles. , such as engine management control, transmission control, car instrumentation, air conditioning, door control, lighting control, air bag control, steering control, tire pressure monitoring, braking system, radar, adaptive cruise, electronic anti-theft system, etc. Due to the different data types and reliability requirements used for communication between these systems, there are many cases where they are composed of multiple buses, and the number of wire harnesses also increases. In order to meet the needs of "reducing the number of wire harnesses" and "carrying out high-speed communication of large amounts of data through multiple LANs", the
German electrical manufacturer Bosch developed the CAN communication protocol for automobiles in 1986. Since then, CAN has been standardized through ISO11898 and ISO11519. It is now the standard protocol for automotive networks in Europe and is currently one of the most widely used fieldbuses.
CAN is a multi-master serial communication bus. The basic design specifications require a high bit rate, high immunity to electromagnetic interference, and the ability to detect any errors that occur. After decades of development, CAN's high performance, high reliability and high real-time performance have been recognized and widely used in industrial automation, ships, medical equipment, industrial equipment, etc.
Take automotive electronics as an example. There are air conditioners, doors, engines, a large number of sensors, etc. on the car. These components and modules are all connected together through the CAN bus to form a network. The vehicle network concept diagram is as follows: Figure 31.1.1 Vehicle Network
Concept picture
Insert image description here

CAN Features

The CAN communication protocol has the following characteristics:
(1) Multi-master control
When the bus is idle, all units can start sending messages (multi-master control).
The unit that accesses the bus first gets the right to send (CSMA/CA method*1).
When multiple units start sending at the same time, the unit sending the high-priority ID message can obtain the right to send.
(2) Message sending
In the CAN protocol, all messages are sent in a fixed format. When the bus is free, all units connected to the bus can start sending new messages. When two or more units start sending messages at the same time, the priority is determined based on the identifier (hereinafter referred to as ID). The ID does not represent the destination address of the transmission, but rather represents the priority of the message accessing the bus. When two or more units start sending messages at the same time, each bit of each message ID is arbitrated and compared one by one. The unit that wins the arbitration (judged to have the highest priority) can continue to send messages, while the unit that loses the arbitration immediately stops sending and starts receiving.
(3) System flexibility.
Units connected to the bus do not have information similar to "address". Therefore, when adding units to the bus, the software, hardware and application layers of other units connected to the bus do not need to be changed.
(4) Communication speed
According to the scale of the entire network, the appropriate communication speed can be set.
In the same network, all units must be set to the same communication speed. Even if one unit communicates at a different speed than the others, this unit will output an error signal, hampering communication throughout the network. Different networks can have different communication speeds.
(5) Remote data request
You can request other units to send data by sending "remote control frames".
(6) It has error detection function, error notification function, and error recovery function.
All units can detect errors (error detection function).
The unit that detects an error immediately notifies all other units simultaneously (error notification function).
Once the unit that is sending a message detects an error, it will forcibly end the current sending. The unit that forces the end of sending will resend the message repeatedly until it is successfully sent (error recovery function).
(7) Fault closure
CAN can determine whether the type of error is a temporary data error on the bus (such as external noise, etc.) or a persistent data error (such as internal unit failure, driver failure, disconnection, etc.). With this feature, when a persistent data error occurs on the bus, the unit causing the fault can be isolated from the bus.
(8). Connection
CAN bus is a bus that can connect multiple units at the same time. The total number of connectable units is theoretically unlimited. However, the number of units that can actually be connected is limited by the time delay on the bus and the electrical load. Lowering the communication speed increases the number of connectable units; increasing the communication speed decreases the number of connectable units.

CAN electrical properties

The CAN bus uses two lines to connect each unit: CAN_H and CAN_L. The CAN controller obtains the bus level by judging the potential difference on these two lines. The CAN bus level is divided into dominant level and recessive level. The dominant level represents logic "0". At this time, the CAN_H level is higher than CAN_L, which are 3.5V and 1.5V respectively, and the potential difference is 2V. The invisible level represents logic "1". At this time, the voltages of CAN_H and CAN_L are both about 2.5V, and the potential difference is 0V. The CAN bus sends specific data through changes in dominant and invisible levels, as shown in the figure below:

Insert image description here
The CAN bus is always in a recessive state when there is no node transmitting data, which means that the bus is always in a recessive state when it is idle.

CAN network topology

CAN is a distributed control bus. As a controller local area network, the CAN bus, like ordinary Ethernet, consists of many CAN nodes. Its network topology is shown in the figure below:
Figure 31.1.3 CAN network topology diagram

Each node of the CAN network is very simple, consisting of an MCU (microcontroller), a CAN controller and a CAN transceiver, and then connected together through the two lines CAN_H and CAN_L to form a CAN local area network. CAN can use a variety of physical media, such as twisted pairs, fiber optics, etc. The most commonly used is twisted pair. The signal is transmitted using differential voltage. The two signal lines are called "CAN_H" and "CAN_L". On our development board, the CAN interface uses these two signal lines, and the CAN interface only has these two signal lines.
It can be seen that the CAN controller LAN is the same as the ordinary Ethernet, and each CAN node is equivalent to a host in the LAN.
All CAN node units on the way are connected together using CAN_H and CAN_L. CAN_H is connected to CAN_H, CAN_L is
connected to CAN_L. Both ends of the CAN bus must be connected with a 120Ω termination resistor to match the bus impedance and absorb signal reflection. and callback to improve the anti-interference ability and reliability of data communication.
The CAN bus transmission speed can reach 1Mbps/S, and the latest CAN-FD has a maximum speed of 5Mbps/S or even higher. CAN-FD is not within the scope of this chapter. Those who are interested can check the relevant information by themselves. CAN transmission speed is related to the bus distance. The shorter the bus distance, the faster the transmission speed.

CAN bus communication model

The CAN bus transmission protocol refers to the OSI open system interconnection model, which is the OSI seven-layer model introduced earlier (refer to
Section 29.2 for specific details). Although the CAN transmission protocol refers to the OSI seven-layer model, in fact the CAN protocol only defines the three layers of "transport layer", "data link layer" and "physical layer", and the application layer protocol can be defined by CAN users to suit Any solution for special industrial areas. A standard that has been widely used in industrial control and manufacturing is DeviceNet, which is designed for PLCs and smart sensors. In the automotive industry, many manufacturers have their own application layer protocol standards.
Figure 31.1.4 OSI seven-layer model and CAN protocol

The CAN protocol only refers to the "transport layer", "data link layer" and "physical layer" in the OSI model. Therefore, various application layer protocols have emerged, such as the fieldbus standard DeviceNet used in automation technology. CanOpen for industrial control, diagnostic protocols OBD and UDS (Unified Diagnostic Service, ISO14229) for passenger cars, and CAN bus protocol SAEJ1939 for commercial vehicles.
The data link layer is divided into MAC sublayer and LLC sublayer. The MAC sublayer is the core part of the CAN protocol. The function of the data link layer is to organize the signals received by the physical layer into meaningful messages and provide a process for transmission control such as transmission error control. Specifically, it is message framing, arbitration, response, error detection or reporting. The functions of the data link layer are usually performed in the hardware of the CAN controller.
The physical layer defines the actual signal transmission method, bit timing, bit encoding method and synchronization steps. But specifically, signal levels, communication speeds, sampling points, electrical characteristics of drivers and buses, connector morphology, etc. are all undefined. These must be determined by the user based on system requirements.

Types of CAN frames

The CAN communication protocol defines 5 types of message frames, namely: data frame, remote control frame, error frame, overload frame, and interval frame. Communication is carried out through these 5 types of frames. There are two types of data frames and remote control frames: standard format and extended format. The standard format has 11 identifiers
(ID), and the extended format has 29 identifiers (ID). These five types of frames are shown in the table below:
Insert image description here
Data frames are the most commonly used frame type. Here we focus on data frames. The data frame structure is shown in the figure below:
Figure 31.1.5 Composition of data frame

Figure 31.1.5 shows the two frame structures of data frame standard format and extended format. In the figure, D represents the dominant level 0, R represents the recessive level 1, and
D/R represents dominant or recessive, that is, 0 Or 1, let's briefly analyze these 7 segments of the data frame.
The data frame consists of 7 segments:
(1) Frame start
indicates the segment at the beginning of the data frame.
(2) Arbitration segment
represents the priority of the frame.
(3) Control segment
represents the number of bytes of data and reserved bits.
(4) Data segment:
The content of the data, which can send 0 to 8 bytes of data.
(5) CRC segment
is a segment that checks frame transmission errors.
(6), ACK segment
indicates the segment that confirms normal reception.
(7), End of frame
: The segment indicating the end of the data frame.
For more detailed content, please refer to the "CAN Getting Started Tutorial" written by Renesas Electronics. This section ends here! Next, I will introduce to you the application programming of CAN.

SocketCan application programming

Since the Linux system manages CAN devices as network devices, in terms of CAN bus application development, Linux provides the
SocketCAN application programming interface, which makes CAN bus communication similar to communication with Ethernet, and the application development interface is more versatile and flexible. .
Most of the data structures and functions in SocketCAN are defined in the header file linux/can.h, so the <linux/can.h> header file must be included in our application.

Create socket socket

The creation of the CAN bus socket is completed using standard network socket operations. The network socket is defined in the header file <sys/socket.h>. Here's how to create a CAN socket:

int sockfd = -1;
/* 创建套接字*/
sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (0 > sockfd)
{
    
    
    perror("socket error");
    exit(EXIT_FAILURE);
}

The socket function was introduced in detail in Section 30.2.1. The first parameter is used to specify the communication domain. In SocketCan, it is usually set to PF_CAN, which is designated as the CAN communication protocol; the second parameter is used to specify the socket. The type of word, usually set to SOCK_RAW; the third parameter is usually set to CAN_RAW.

Bind the socket to the CAN device

For example, to bind the created socket to can0, the sample code is as follows:

......
struct ifreq ifr = {
    
    0};
struct sockaddr_can can_addr = {
    
    0};
int ret;
......
strcpy(ifr.ifr_name, "can0"); // 指定名字
ioctl(sockfd, SIOCGIFINDEX, &ifr);
can_addr.can_family = AF_CAN; // 填充数据
can_addr.can_ifindex = ifr.ifr_ifindex;
/* 将套接字与can0 进行绑定*/
ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
if (0 > ret)
{
    
    
    perror("bind error");
    close(sockfd);
    exit(EXIT_FAILURE);
}

The bind() function was introduced in detail in Section 30.2.2 and will not be repeated here!
Two structures appear here: struct ifreq and struct sockaddr_can, struct ifreq is defined in the <net/if.h> header file, and struct sockaddr_can is defined in the <linux/can.h> header file. These structures are I won’t explain it to you. If you are interested, you can check it out yourself. I don’t really understand it either!

Set filter rules

In our application, if no filtering rules are set, the application will receive messages with all IDs by default; if our application only needs to receive messages with certain IDs (or does not accept all messages, only send message), you can set filtering rules through the setsockopt function. For example, if an application only receives message frames with IDs 0x60A and 0x60B, it can filter out all other frames that do not comply with the rules. The sample code is as follows:

struct can_filter rfilter[2]; //定义一个can_filter 结构体对象
// 填充过滤规则,只接收ID 为(can_id & can_mask)的报文
rfilter[0].can_id = 0x60A;
rfilter[0].can_mask = 0x7FF;
rfilter[1].can_id = 0x60B;
rfilter[1].can_mask = 0x7FF;
// 调用setsockopt 设置过滤规则
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

There are only two members in the struct can_filter structure, can_id and can_mask.
If the application does not receive all messages, in this application that only sends data, the receive queue can be omitted in the kernel to reduce the
consumption of CPU resources. At this time, you can set the 4th parameter of the setsockopt() function to NULL and the 5th parameter to 0, as shown below:

setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

Data sending/receiving

In terms of the content of data transmission and reception, the CAN bus is slightly different from standard socket communication. Each communication uses the struct can_frame structure to encapsulate the data into a frame. The structure is defined as follows

struct can_frame {
    
    
	canid_t can_id; /* CAN 标识符*/
	__u8 can_dlc; /* 数据长度(最长为8 个字节)*/
	__u8 __pad; /* padding */
	__u8 __res0; /* reserved / padding */
	__u8 __res1; /* reserved / padding */
	__u8 data[8]; /* 数据*/
};

can_id is the frame identifier, if it is a standard frame, use the lower 11 bits of can_id; if it is an extended frame, use 0~28 bits.
The 29th, 30th, and 31st bits of can_id are the flag bits of the frame, which are used to define the type of the frame. The definition is as follows:

/* special address description flags for the CAN_ID */
#define CAN_EFF_FLAG 0x80000000U /* 扩展帧的标识*/
#define CAN_RTR_FLAG 0x40000000U /* 远程帧的标识*/
#define CAN_ERR_FLAG 0x20000000U /* 错误帧的标识,用于错误检查*/
/* mask */
#define CAN_SFF_MASK 0x000007FFU /* <can_id & CAN_SFF_MASK>获取标准帧ID */
#define CAN_EFF_MASK 0x1FFFFFFFU /* <can_id & CAN_EFF_MASK>获取标准帧ID */
#define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */

(1) Data transmission
For data transmission, use the write() function. For example, the data frame to be sent contains three bytes of data 0xA0, 0xB0 and
0xC0, and the frame ID is 123. It can be sent using the following method:

struct can_frame frame; //定义一个can_frame 变量
int ret;
frame.can_id = 123;//如果为扩展帧,那么frame.can_id = CAN_EFF_FLAG | 123;
frame.can_dlc = 3; //数据长度为3
frame.data[0] = 0xA0; //数据内容为0xA0
frame.data[1] = 0xB0; //数据内容为0xB0
frame.data[2] = 0xC0; //数据内容为0xC0
ret = write(sockfd, &frame, sizeof(frame)); //发送数据
if(sizeof(frame) != ret) //如果ret 不等于帧长度,就说明发送失败
perror("write error");

If you want to send a remote frame (frame ID is 123), you can use the following method to send it:

struct can_frame frame;
frame.can_id = CAN_RTR_FLAG | 123;
write(sockfd, &frame, sizeof(frame));

(2) Data reception
Data reception is realized using the read() function, as shown below:

struct can_frame frame;
int ret = read(sockfd, &frame, sizeof(frame));

(3) Error handling
When the application receives a frame of data, it can determine whether the received frame is an error frame by judging the CAN_ERR_FLAG bit in can_id. If it is an error frame, the specific cause of the error can be judged through other sign bits of can_id. The sign bit of the error frame is defined in the header file <linux/can/error.h>.

/* error class (mask) in can_id */
#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
......
......

Loopback function settings

By default, the local loopback function of CAN is enabled, you can use the following methods to disable or enable the local loopback function:

int loopback = 0; //0 表示关闭,1 表示开启(默认)
setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

When the local loopback function is enabled, all sent frames will be looped back to the socket corresponding to the CAN bus interface.

CAN application programming practice

In this section we will write a simple CAN application program. In the Linux system, CAN bus devices are uniformly managed by the system as network devices. Under the console, the same commands are used for CAN bus configuration and Ethernet configuration.
Use the ifconfig command to view the CAN device, as shown below:
Insert image description here
Our development board has only one CAN interface, can0, as shown in the following figure:
Insert image description here
Figure 31.3.2 The can interface on the ALPHA board

Insert image description here
Figure 31.3.3 The can interface on the Mini board
In the factory system of the development board, some tools are provided for testing the can. We can use these tools for testing. Since there is only one CAN interface on our board, if you want to test, you can use two development boards to connect their CAN interfaces and perform transceiver testing. If you only have one development board in hand, this method will naturally not work. In addition, we can also use some
CAN testing equipment for testing, such as CAN analyzer. Here I use the CAN analyzer for testing.
If you have purchased CAN test equipment such as a CAN analyzer, you can just use it for testing! Regarding the use of the CAN analyzer and supporting host computer, please refer to the instruction manual provided by them. If you do not know how to use it, please consult the manufacturer's technical support!
Before testing, use a CAN analyzer or other CAN test equipment to connect to the CAN interface on the backplane of the ALPHA|Mini development board. CANH is connected to the CANH of the instrument, and CANL is connected to the CANL of the CAN instrument. And open the PC software supporting the CAN analyzer. The author is using a CAN analyzer launched by Chuangxin Technology. The supporting PC software interface is as follows:
Figure 31.3.4 CAN host computer

After the device is connected, start the CAN analyzer through the host computer software, and then we will test.
Before testing, you need to configure the can device on the development board, execute the following command:

ifconfig can0 down #先关闭can0 设备
ip link set can0 up type can bitrate 1000000 triple-sampling on #设置波特率为1000000

Note that the baud rate set by the CAN analyzer must be consistent with the baud rate of the CAN device on the development board!
After the configuration is complete, you can then use the cansend command to send data,

cansend can0 123#01.02.03.04.05.06.07.08

Figure 31.3.5 Use the cansend command to send data

Insert image description here
The 123 in front of the "#" sign represents the frame ID, and the following number represents the data to be sent. At this time, the host computer will receive the data sent by the development board, as shown below:
Figure 31.3.6 The host computer software receives data

Then test the development board to receive CAN data, first execute the candump command on the development board:

candump -ta can0

Then send data to the development board through the CAN analyzer host computer software, as shown below:
Insert image description here
At this time, the development board can receive the data sent by the host computer, as shown below:
Insert image description here
After the test is completed, press Ctrl + C to exit the candump program. That’s it for the CAN test.

CAN data sending example

Through the previous learning, in this section we will write a very simple sample code for CAN data transmission. The author has already written the code, as shown below.
The paths corresponding to the source code of this routine are: development board CD->11, Linux C application programming routine source code->31_can->can_write.c.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
int main(void)
{
    
    
    struct ifreq ifr = {
    
    0};
    struct sockaddr_can can_addr = {
    
    0};
    struct can_frame frame = {
    
    0};
    int sockfd = -1;
    int ret;
    /* 打开套接字*/
    sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (0 > sockfd)
    {
    
    
        perror("socket error");
        exit(EXIT_FAILURE);
    }
    /* 指定can0 设备*/
    strcpy(ifr.ifr_name, "can0");
    ioctl(sockfd, SIOCGIFINDEX, &ifr);
    can_addr.can_family = AF_CAN;
    can_addr.can_ifindex = ifr.ifr_ifindex;
    /* 将can0 与套接字进行绑定*/
    ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
    if (0 > ret)
    {
    
    
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    /* 设置过滤规则:不接受任何报文、仅发送数据*/
    setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
    /* 发送数据*/
    frame.data[0] = 0xA0;
    frame.data[1] = 0xB0;
    frame.data[2] = 0xC0;
    frame.data[3] = 0xD0;
    frame.data[4] = 0xE0;
    frame.data[5] = 0xF0;
    frame.can_dlc = 6;    // 一次发送6 个字节数据
    frame.can_id = 0x123; // 帧ID 为0x123,标准帧
    for (;;)
    {
    
    
        ret = write(sockfd, &frame, sizeof(frame)); // 发送数据
        if (sizeof(frame) != ret)
        {
    
     // 如果ret 不等于帧长度,就说明发送失败
            perror("write error");
            goto out;
        }
        sleep(1); // 一秒钟发送一次
    }
out:
    /* 关闭套接字*/
    close(sockfd);
    exit(EXIT_SUCCESS);
}

The code is relatively simple, so I won’t explain too much here. Just compile it directly:
Figure 31.3.9 Compile sample code

Copy the compiled executable file can_write to the /home/root directory of the development board Linux system, and then run the program. After the program is run, a frame of data will be sent through can0 every 1 second, and 6 bytes of data will be sent at a time. , the frame ID is 0x123. At this time, the CAN host computer will receive the data sent by the development board, as shown below:
Insert image description here

Example of CAN data reception

In this section, we will write a very simple sample code for CAN data reception. The author has already written the code, as shown below.
The path corresponding to the source code of this routine is: development board CD->11, Linux C application programming routine source code->31_can->can_read.c.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
int main(void)
{
    
    
    struct ifreq ifr = {
    
    0};
    struct sockaddr_can can_addr = {
    
    0};
    struct can_frame frame = {
    
    0};
    int sockfd = -1;
    int i;
    int ret;
    /* 打开套接字*/
    sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (0 > sockfd)
    {
    
    
        perror("socket error");
        exit(EXIT_FAILURE);
    }
    /* 指定can0 设备*/
    strcpy(ifr.ifr_name, "can0");
    ioctl(sockfd, SIOCGIFINDEX, &ifr);
    can_addr.can_family = AF_CAN;
    can_addr.can_ifindex = ifr.ifr_ifindex;
    /* 将can0 与套接字进行绑定*/
    ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));
    if (0 > ret)
    {
    
    
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }
    /* 设置过滤规则*/
    // setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
    /* 接收数据*/
    for (;;)
    {
    
    
        if (0 > read(sockfd, &frame, sizeof(struct can_frame)))
        {
    
    
            perror("read error");
            break;
        }
        /* 校验是否接收到错误帧*/
        if (frame.can_id & CAN_ERR_FLAG)
        {
    
    
            printf("Error frame!\n");
            break;
        }
        /* 校验帧格式*/
        if (frame.can_id & CAN_EFF_FLAG) // 扩展帧
            printf("扩展帧<0x%08x> ", frame.can_id & CAN_EFF_MASK);
        else // 标准帧
            printf("标准帧<0x%03x> ", frame.can_id & CAN_SFF_MASK);
        /* 校验帧类型:数据帧还是远程帧*/
        if (frame.can_id & CAN_RTR_FLAG)
        {
    
    
            printf("remote request\n");
            continue;
        }
        /* 打印数据长度*/
        printf("[%d] ", frame.can_dlc);
        /* 打印数据*/
        for (i = 0; i < frame.can_dlc; i++)
            printf("%02x ", frame.data[i]);
        printf("\n");
    }
    /* 关闭套接字*/
    close(sockfd);
    exit(EXIT_SUCCESS);
}

Compile the sample code:
Insert image description here
Copy the compiled executable file can_read to the /home/root directory of the development board Linux system, then execute the program, and then send data to the development board through the CAN host computer. At this time, the development board will receive the host computer The data sent is as follows:
Insert image description here

Guess you like

Origin blog.csdn.net/zhuguanlin121/article/details/132594924