CAN (Controller Area Network) is a serial communication protocol bus for real-time applications, which can use twisted pair wires to transmit signals and is one of the most widely used fieldbuses in the world. It was developed by Bosch in Germany in the 1980s specifically for the automotive industry. Multiple nodes can be supported on one CAN group.
In Linux systems, CAN is a network device that sends and receives by means of socket communication.
The development board has one CAN channel and the corresponding network card device is CAN0. The board already comes with a CAN transceiver, which leads to a direct H and L differential interface. The CANH and CANL on the board can be connected to the CANH and CANL of the CAN analyzer for transceiver testing. The wiring is as follows
The operation can be performed using canutil under Linux.
Set the baud rate to 250k. canfd is not currently available on the board, but the RK3568 itself supports canfd, so a canfd baud rate must be set here as well
root@linaro-alip:~# ip link set can0 type can bitrate 250000 dbitrate 3000000 fd on
Start CAN0
root@linaro-alip:~# ip link set can0 up
Send standard frame id 0x123 data 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
root@linaro-alip:~# cansend can0 123#1122334455667788
Send extended frame id 0x12345678 data 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
root@linaro-alip:~# cansend can0 12345678#1122334455667788
After sending the CAN analyzer displays the following
Receiving data
root@linaro-alip:~# candump can0
Send standard frame id 0x234 data 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 using CAN analyzer
By linking to the libperipheral_api.a static library, the following interfaces can be called in C to operate CAN
/**
* @name: user_can_init
* @description: Initialize CAN
* @param can_name: can network card device name e.g. can0
* @param can_baud: baud rate e.g. 250000
* @param canfd_baud: canfd baud rate e.g. 3000000
* @return greater than or equal to 0 - Success; less than 0 - Failure
*/
int user_can_init(char *can_name, int can_baud, int canfd_baud);
/**
* @name: user_can_deinit
* @description: De-initialize CAN
* @param can_name: can network card device name e.g. can0
* @return greater than or equal to 0 - Success; less than 0 - Failure
*/
int user_can_deinit(char *can_name);
/**
* @name: user_can_send
* @description: Send a frame of CAN data
* @param can_name: can network card device name e.g. can0
* @param frame: CAN Structs in Linux
* @return Greater than 0 - Success; Less than 0 - Failure; Equal to 0 - Temporarily unable to send, buffer may be full
*/
int user_can_send(char *can_name, struct can_frame frame);
/**
* @name: user_can_recv
* @description: Recv a frame of CAN data
* @param can_name: can network card device name e.g. can0
* @param frame: CAN Structs in Linux
* @return Greater than 0 - Success; Less than 0 - Failure; Equal to 0 - No data received, receive buffer empty
*/
int user_can_recv(char *can_name, struct can_frame *frame);
The test demo is as follows, taking the operation of CAN0 as an example, with an external CAN analyzer
void can_api_test(void)
{
struct can_frame frame_tx = {0};
struct can_frame frame_rx = {0};
int nbytes = 0;
user_can_init("can0",250000,3000000);
frame_tx.can_id = 0x123;
frame_tx.can_dlc = 8;
frame_tx.data[0] = 0x11;
frame_tx.data[1] = 0x22;
frame_tx.data[2] = 0x33;
frame_tx.data[3] = 0x44;
frame_tx.data[4] = 0x55;
frame_tx.data[5] = 0x66;
frame_tx.data[6] = 0x77;
frame_tx.data[7] = 0x88;
nbytes = user_can_send("can0",frame_tx);
frame_tx.can_id = 0x12345678 | CAN_EFF_FLAG;
frame_tx.can_dlc = 8;
frame_tx.data[0] = 0x11;
frame_tx.data[1] = 0x22;
frame_tx.data[2] = 0x33;
frame_tx.data[3] = 0x44;
frame_tx.data[4] = 0x55;
frame_tx.data[5] = 0x66;
frame_tx.data[6] = 0x77;
frame_tx.data[7] = 0x88;
nbytes = user_can_send("can0",frame_tx);
nbytes = user_can_recv("can0",&frame_rx);
/* printf the received frame */
if (nbytes > 0) {
printf("%#x [%d] ", frame_rx.can_id, frame_rx.can_dlc);
for (unsigned char i = 0; i < frame_rx.can_dlc; i++)
printf("%#x ", frame_rx.data[i]);
printf("\n");
}
user_can_deinit("can0");
return;
}
int main()
{
can_api_test();
return 0;
}
The results of the run are as follows