Transmit and Receive - AutoReply
This sample demonstrates the use of the auto-reply feature of the CAN peripheral for data transmission and reception.
A USB CAN analyzer is externally connected to the CAN, enabling communication between the PC and the CAN controller for sending and receiving data.
The CAN auto-reply feature is utilized to automatically receive or send data frames.
Requirements
For hardware requirements, please refer to the Requirements.
Wiring
The EVB is connected to a TJA1051 CAN Receiver module by connecting P4_0 to CTX, P4_1 to CRX. The EVB BAT/5V is connected to the module VCC and NC. The EVB GND is connected to the module GND and S.
The other end of the TJA1051 CAN Receiver module is connected to the PC via a USB CAN analyzer, by connecting module CANH to analyzer CANH and module CANL to analyzer CANL.

CAN TRX Demo Code Hardware Connection Diagram
The introduction of CAN transceiver can refer to CAN Transceiver Introduction .
Configurations
The following macros can be configured to modify CAN pin definitions.
#define CAN_TX_PIN P4_0 #define CAN_RX_PIN P4_1
The entry function is as follows, call this function in
main()
to run this sample code. For more details, please refer to the Initialization.can_trx_autoreply_demo();
Building and Downloading
For building and downloading, please refer to the Building and Downloading.
Experimental Verification
Press the Reset button on the EVB and the message will be displayed in the Debug Analyzer.
can_trx_autoreply_demo: start!
After the IC is reset, a remote frame sent by the IC is received on the tool.
Within the Debug Analyzer, IC prints out the remote frame IDs to be replied and those that can be autoreplied.
can_trx_autoreply_demo: start! can_driver_init: BUS state: 0, waiting... can_driver_init: BUS ON 1 can_receive_remote_auto_tx_reply: tx auto reply remote frame id: 0x00000001 can_send_remote_auto_receive_reply: rx auto receive data frame id: 0x00000010
Send a 0x010 data frame on the tool, the IC will receive and print the log and send the next remote frame to be replied.
can_trx_autoreply_handler: CAN RX INT can_send_remote_auto_receive_reply: rx auto receive data frame id: 0x00000001
The IC auto reply data frame is received on the tool.
Code Overview
This section introduces the code and process description for initialization and corresponding function implementation in the sample.
Source Code Directory
The directory for project file and source code are as follows:
For project directory, please refer to Source Code Directory.
Source code directory:
sdk\sample\io_demo\canbus\trx_autoreply\can_trx_autoreply.c
.
Initialization
The initialization flow for peripherals can refer to Initialization Flow.
CAN initialization flow is shown in the following figure.

CAN Init Flow
Call
Pad_Config()
andPinmux_Config()
to configure the corresponding pin’s PAD and PINMUX.static void can_board_init(void) { /* Config pinmux and pad for CAN. */ Pinmux_Config(CAN_TX_PIN, CAN_TX); Pinmux_Config(CAN_RX_PIN, CAN_RX); Pad_Config(CAN_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW); Pad_Config(CAN_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE, PAD_OUT_LOW); }
Call
RCC_PeriphClockCmd()
to enable the CAN clock.Initialize the CAN peripheral:
Define a
CAN_InitTypeDef
typeinit_struct
and callCAN_StructInit()
to pre-fillinit_struct
with default values.Modify the
init_struct
parameters as needed. The CAN initialization parameters are configured as shown in the table below.Call
CAN_Init()
to initialize the parameters and the CAN peripheral.
CAN Hardware Parameters |
Setting in the |
CAN |
---|---|---|
Auto Re-transmit Enable |
||
CAN Speed Parameter - BRP |
3 |
|
CAN Speed Parameter - SJW |
3 |
|
CAN Speed Parameter - TSEG1 |
13 |
|
CAN Speed Parameter - Tseg2 |
4 |
Call
CAN_Cmd()
to enable the corresponding CAN peripheral.Call
CAN_INTConfig()
to configure the CAN receive completeCAN_RX_INT
interrupt, transmit completeCAN_TX_INT
interrupt, error interruptCAN_ERROR_INT
, etc. Configure NVIC, and refer to Interrupt Configuration for NVIC-related configurations.Call
CAN_GetBusState()
to loop-check the CAN bus state and wait for the CAN bus to open.while (CAN_GetBusState() != CAN_BUS_STATE_ON) { __asm volatile ( "nop \n" ); }
Note
If the program is stuck at the point of waiting for the CAN bus to be on, please check if the CAN bus is connected correctly.
Functional Implementation
Call
can_receive_remote_auto_tx_reply
, enable TX autoreply function.Set the transmit frame type for the TX message buffer. Enable auto reply function. Configure frame id and frame data to auto reply.
Enable the message buffer TX done interrupt. Poll the RAM status to be idle.
void can_receive_remote_auto_tx_reply(void) { CANError_TypeDef tx_error; CANTxFrame_TypeDef tx_frame_type; ... tx_frame_type.msg_buf_id = 0; tx_frame_type.frame_type = CAN_STD_DATA_FRAME; tx_frame_type.standard_frame_id = 0x01; tx_frame_type.extend_frame_id = 0x01; tx_frame_type.auto_reply_bit = SET; CAN_MBTxINTConfig(CAN0, tx_frame_type.msg_buf_id, ENABLE); tx_error = CAN_SetMsgBufTxMode(CAN0, &tx_frame_type, tx_data, 8); ... }
Execute
can_send_remote_auto_receive_reply
, enable RX autoreply function.Enable auto reply. Unmask the rtr, ide, and id bit filters to receive specified frames.
Disable RX GDMA.
Enable the message buffer RX done interrupt. Poll the RAM status to be idle.
void can_send_remote_auto_receive_reply(void) { CANError_TypeDef rx_error; CANRxFrame_TypeDef rx_frame_type; rx_frame_type.msg_buf_id = 10; rx_frame_type.extend_frame_id = 0; rx_frame_type.standard_frame_id = 0x10; rx_frame_type.frame_ide_bit = CAN_IDE_STANDARD_FORMAT; rx_frame_type.frame_rtr_bit = CAN_RTR_DATA_FRAME; rx_frame_type.frame_rtr_mask = CAN_RX_FRAME_UNMASK_RTR; rx_frame_type.frame_ide_mask = CAN_RX_FRAME_UNMASK_IDE; rx_frame_type.frame_id_mask = 0; rx_frame_type.rx_dma_en = RESET; rx_frame_type.auto_reply_bit = SET; rx_error = CAN_SetMsgBufRxMode(CAN0, &rx_frame_type); CAN_MBRxINTConfig(CAN0, rx_frame_type.msg_buf_id, ENABLE); ... }
If remote frame with the same frame id as TX autoreply setting is received, the message buffer will automatically reply and trigger the TX interrupt. If data frame with the same frame id as RX autoreply setting is received, the message buffer will automatically receive the frame and trigger the RX interrupt. Check the interrupt source in the
can_trx_autoreply_handler
.If the interrupt source is the RX done interrupt, print the received frame data and call the
can_send_remote_auto_receive_reply
function, then wait for the next interrupt.If the interrupt source is the TX done interrupt, call the
can_receive_remote_auto_tx_reply
function, then wait for the next interrupt.
... if (SET == CAN_GetINTStatus(CAN0, CAN_RX_INT_FLAG)) { ... CAN_GetMBnRxDoneFlag(CAN0, index) ... CAN_GetRamData(CAN0, mb_info.data_length, rx_data); CANDataFrameSel_TypeDef frame_type = CAN_CheckFrameType(mb_info.rtr_bit, mb_info.ide_bit, mb_info.edl_bit); can_send_remote_auto_receive_reply(); } if (SET == CAN_GetINTStatus(CAN0, CAN_TX_INT_FLAG)) { CAN_ClearINTPendingBit(CAN0, CAN_TX_INT_FLAG); IO_PRINT_INFO0("can_trx_autoreply_handler: CAN TX INT"); /* Enable autoreply next time. */ can_receive_remote_auto_tx_reply(); /* Add user code. */ }