CAN (Controller Area Network) is a serial communication protocol bus for real-time applications. It can use twisted pair cables to transmit signals and is one of the most widely used field buses in the world. It was developed by Bosch in Germany in the 1980s specifically for the automotive industry. A group of CANs can support multiple nodes.
Under Linux, CAN is a network device that transmits and receives data through socket communication.
There is one CAN on the development board, and the corresponding pin positions are as follows
The corresponding network card device is CAN0. There is no CAN transceiver on the board, and the interfaces are CAN TX and CAN RX. A CAN transceiver module with a voltage level of 3.3V is also required. TI's SN65HVD230 can be selected. Connect the CAN TX and CAN RX on the board to the CAN TX and CAN RX of the SN65HVD230 module, and connect the CANH and CANL of the SN65HVD230 to the CANH and CANL of the CAN analyzer to perform the transceiver test. The wiring is as follows
Can be used in Linux to perform related operations using canutil.
Set the baud rate to 250k.
ip link set can0 type can bitrate 250000
Start CAN0
ifconfig can0 up
Send standard frame id 0x123 data 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
cansend can0 123#1122334455667788
Send extended frame id 0x12345678 data 0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
cansend can0 12345678#1122334455667788
After sending CAN analyzer displays as follows
Receive data
candump can0
Use CAN analyzer to send standard frame id 0x123 data 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07
By connecting to the libperipheral_api.a static library, you can use C language to call the following interface to operate CAN
/**
* @name: user_can_init
* @description: Initialize CAN
* @param can_name: can network card device name such as can0
* @param can_baud: baud rate Such as 250000
* @param canfd_baud: canfd baud rate such as 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: Deinitialize CAN
* @param can_name: can network card device name such as 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 such as can0
* @param frame: CAN structure under Linux
* @return greater than 0 - success less than 0 - failure equal to 0 - Temporarily unable to send, the buffer may be full
*/
int user_can_send(char *can_name, struct can_frame frame);
/**
* @name: user_can_recv
* @description: Receive a frame of CAN data
* @param can_name: can network card device name such as can0
* @param frame: CAN structure under 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, external CAN analyzer
#include "peripheral_api.h"
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);
//Standard frame
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);
//Extended frame
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);
sleep(1);
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;
}
Put the peripheral_api.a static library, peripheral_api.h and test demo source code test.c in the same path, and the compilation command is as follows
aarch64-none-linux-gnu-gcc test.c peripheral_api.a -I. -o cantest
The results are as follows