5.2 bxCAN Guide
This chapter describes the file composition and the 33 public functions of the bxCAN driver in the N32G41x standard peripheral library: CAN reset and initialization, filter configuration, operating mode control, message transmit and receive, error management and status query, and interrupt and flag management. Two examples, CAN_LoopBack and CAN_Tx_Rx, demonstrate message transfer in loopback mode and normal mode. Read the register bit definitions, operating modes, filter mechanism and bit timing together with the “Controller area network (CAN)” chapter of the user manual, and take the errata sheet as the authority on known chip issues.
5.2.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32g41x_std_periph_driver/inc/n32g41x_can.h |
Defines the CAN_InitType, CAN_FilterInitType, CanTxMessage and CanRxMessage structures and the operating-mode, bit-timing, filter, mailbox and flag macros, and declares 33 public functions in the eight sections reset and initialization, configuration, operating mode control, transmit, receive, error management, status query, and interrupt and flag management |
firmware/n32g41x_std_periph_driver/src/n32g41x_can.c |
Implements those 33 functions: register reset and bit timing, filter and operating-mode configuration, mailbox message transmit and receive, error counters and status query, and interrupt and flag access |
projects/n32g41x_EVAL/examples/bxCAN/ |
bxCAN example root directory, containing 2 examples: CAN_LoopBack and CAN_Tx_Rx |
projects/n32g41x_EVAL/examples/bxCAN/CAN_LoopBack/ |
Composition of this example project: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32g41x_EVAL/bsp/ |
Board support directory referenced by both example projects: evaluation-board resource definitions and common millisecond delay and log-printing implementations |
5.2.2 API reference
The following 33 public functions are listed in the declaration order of n32g41x_can.h in 8 groups; each entry gives a summary and the original comment above the function in n32g41x_can.c.
Reset and initialization
CAN_DeInit, CAN_Init, CAN_InitStruct, CAN_InitFilter, CAN_SoftwareReset
Configuration
CAN_DebugFreeze, CAN_EnTTComMode
Operating mode control
CAN_OperatingModeReq, CAN_EnterSleep, CAN_WakeUp
Transmit
CAN_TransmitMessage, CAN_TransmitSTS, CAN_CancelTransmitMessage
Receive
CAN_ReceiveMessage, CAN_ReleaseFIFO, CAN_PendingMessage
Error management
CAN_GetLastErrCode, CAN_GetReceiveErrCounter, CAN_GetLSBTransmitErrCounter
Status query
CAN_GetTransmitFailStatus, CAN_GetArbitrationLostStatus, CAN_GetFlagLowestPriority, CAN_GetTransmitMailboxEmptyFlag, CAN_GetReceiveSignal, CAN_GetLastSamplePoint, CAN_GetReceiveMode, CAN_GetTransmitMode, CAN_GetMailboxCode
Interrupt and flag management
CAN_INTConfig, CAN_GetFlagSTS, CAN_ClearFlag, CAN_GetIntStatus, CAN_ClearINTPendingBit
void CAN_DeInit(const CAN_Module *CANx)Deinitializes the CAN peripheral registers to their default reset values.
name CAN_DeInit
fun Deinitializes the CAN peripheral registers to their default reset values.
param CANx:
- CAN
return none
uint8_t CAN_Init(CAN_Module *CANx, const CAN_InitType *CAN_InitParam)Initializes the CAN peripheral according to the specified parameters in the CAN_InitType structure.
name CAN_Init
fun Initializes the CAN peripheral according to the specified
parameters in the CAN_InitType structure.
param CANx:
- CAN
param CAN_InitParam (The input parameters must be the following values) :
- BaudRatePrescaler
- It ranges from 1 to 1024.
- OperatingMode
- CAN_Normal_Mode
- CAN_LoopBack_Mode
- CAN_Silent_Mode
- CAN_Silent_LoopBack_Mode
- RSJW
- CAN_RSJW_1tq
- CAN_RSJW_2tq
- CAN_RSJW_3tq
- CAN_RSJW_4tq
- TBS1
- CAN_TBS1_1tq
- CAN_TBS1_2tq
- CAN_TBS1_3tq
- CAN_TBS1_4tq
- CAN_TBS1_5tq
- CAN_TBS1_6tq
- CAN_TBS1_7tq
- CAN_TBS1_8tq
- CAN_TBS1_9tq
- CAN_TBS1_10tq
- CAN_TBS1_11tq
- CAN_TBS1_12tq
- CAN_TBS1_13tq
- CAN_TBS1_14tq
- CAN_TBS1_15tq
- CAN_TBS1_16tq
- TBS2
- CAN_TBS2_1tq
- CAN_TBS2_2tq
- CAN_TBS2_3tq
- CAN_TBS2_4tq
- CAN_TBS2_5tq
- CAN_TBS2_6tq
- CAN_TBS2_7tq
- CAN_TBS2_8tq
- TTCM
- DISABLE
- ENABLE
- ABOM
- DISABLE
- ENABLE
- AWKUM
- DISABLE
- ENABLE
- NART
- DISABLE
- ENABLE
- RFLM
- DISABLE
- ENABLE
- TXFP
- DISABLE
- ENABLE
return InitStatus :
- CAN_InitSTS_Failed
- CAN_InitSTS_Success
void CAN_InitStruct(CAN_InitType *CAN_InitParam)Fills each CAN_InitType member with its default value.
name CAN_InitStruct
fun Fills each CAN_InitType member with its default value.
param CAN_InitParam (The input parameters must be the following values) :
- BaudRatePrescaler
- It ranges from 1 to 1024.
- OperatingMode
- CAN_Normal_Mode
- CAN_LoopBack_Mode
- CAN_Silent_Mode
- CAN_Silent_LoopBack_Mode
- RSJW
- CAN_RSJW_1tq
- CAN_RSJW_2tq
- CAN_RSJW_3tq
- CAN_RSJW_4tq
- TBS1
- CAN_TBS1_1tq
- CAN_TBS1_2tq
- CAN_TBS1_3tq
- CAN_TBS1_4tq
- CAN_TBS1_5tq
- CAN_TBS1_6tq
- CAN_TBS1_7tq
- CAN_TBS1_8tq
- CAN_TBS1_9tq
- CAN_TBS1_10tq
- CAN_TBS1_11tq
- CAN_TBS1_12tq
- CAN_TBS1_13tq
- CAN_TBS1_14tq
- CAN_TBS1_15tq
- CAN_TBS1_16tq
- TBS2
- CAN_TBS2_1tq
- CAN_TBS2_2tq
- CAN_TBS2_3tq
- CAN_TBS2_4tq
- CAN_TBS2_5tq
- CAN_TBS2_6tq
- CAN_TBS2_7tq
- CAN_TBS2_8tq
- TTCM
- DISABLE
- ENABLE
- ABOM
- DISABLE
- ENABLE
- AWKUM
- DISABLE
- ENABLE
- NART
- DISABLE
- ENABLE
- RFLM
- DISABLE
- ENABLE
- TXFP
- DISABLE
- ENABLE
return none
void CAN_InitFilter(const CAN_FilterInitType *CAN_InitFilterStruct)Initializes the CAN peripheral according to the specified parameters in the CAN_FilterInitType structure.
name CAN_InitFilter
fun Initializes the CAN peripheral according to the specified
parameters in the CAN_FilterInitType structure.
param CAN_InitFilterStruct (The input parameters must be the following values) :
- Filter_HighId
- It ranges from 0x0000 to 0xFFFF
- Filter_LowId
- It ranges from 0x0000 to 0xFFFF
- FilterMask_HighId
- It ranges from 0x0000 to 0xFFFF
- FilterMask_LowId
- It ranges from 0x0000 to 0xFFFF
- Filter_FIFOAssignment
- CAN_Filter_FIFO0
- CAN_Filter_FIFO1
- Filter_Num
- It ranges from 0 to 13
- Filter_Mode
- CAN_Filter_IdMaskMode
- CAN_Filter_IdListMode
- Filter_Scale
- CAN_Filter_16bitScale
- CAN_Filter_32bitScale
- Filter_Act
- ENABLE
- DISABLE
return none
void CAN_SoftwareReset(CAN_Module *CANx)Enable software reset.
name CAN_SoftwareReset
fun Enable software reset.
param CANx:
- CAN
return none
void CAN_DebugFreeze(CAN_Module *CANx, FunctionalState Cmd)Enables the DBG Freeze for CAN.
name CAN_DebugFreeze
fun Enables the DBG Freeze for CAN.
param CANx:
- CAN
param Cmd (The input parameters must be the following values):
- DISABLE
- ENABLE
return none
void CAN_EnTTComMode(CAN_Module *CANx, FunctionalState Cmd)Enables the CAN Time stamp sent.
name CAN_EnTTComMode
fun Enables the CAN Time stamp sent.
param CANx:
- CAN
param Cmd (The input parameters must be the following values):
- DISABLE
- ENABLE
note when enabled, Time stamp (MTIM[15:0]) value is sent in the last
two data bytes of the 8-byte message: MTIM[7:0] in data byte 6
and MTIM[15:8] in data byte 7
note DLC must be programmed as 8 in order Time Stamp (2 bytes) to be
sent over the CAN bus.
return none
uint8_t CAN_OperatingModeReq(CAN_Module *CANx, uint8_t CAN_OperatingMode)Select the CAN Operation mode.
name CAN_OperatingModeReq
fun Select the CAN Operation mode.
param CANx:
- CAN
param CAN_OperatingMode (The input parameters must be the following values) :
- CAN_Operating_InitMode
- CAN_Operating_NormalMode
- CAN_Operating_SleepMode
return status :
- CAN_ModeSTS_Failed CAN failed entering the specific mode
- CAN_ModeSTS_Success CAN Succeed entering the specific mode
uint8_t CAN_EnterSleep(CAN_Module *CANx)Enters sleep mode.
name CAN_EnterSleep
fun Enters sleep mode.
param CANx:
- CAN
return sleepstatus:
- CAN_SLEEP_Ok
- CAN_SLEEP_Failed
uint8_t CAN_WakeUp(CAN_Module *CANx)Wakes the CAN up.
name CAN_WakeUp
fun Wakes the CAN up.
param CANx:
- CAN
return CAN_Status:
- CAN_WKU_Ok
- CAN_WKU_Failed
uint8_t CAN_TransmitMessage(CAN_Module *CANx, CanTxMessage *TxMessage)initialize the transmission of a message.
name CAN_TransmitMessage
fun initialize the transmission of a message.
param CANx:
- CAN
param TxMessage (The input parameters must be the following values):
- StdId
- It ranges from 0 to 0x7FF
- ExtId
- It ranges from 0 to 0x1FFFFFFF
- IDE
- CAN_Standard_Id
- CAN_Extended_Id
- RTR
- CAN_RTRQ_Data
- CAN_RTRQ_Remote
- DLC
- It ranges from 0 to 8
- Data[0-7]
- It ranges from 0 to 0xFF
return transmit_mailbox (The input parameters must be the following values) :
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
- CAN_TxSTS_NoMailBox
uint8_t CAN_TransmitSTS(const CAN_Module *CANx, uint8_t TransmitMailbox)Checks the transmission of a message.
name CAN_TransmitSTS
fun Checks the transmission of a message.
param CANx:
- CAN
param TransmitMailbox (The input parameters must be the following values) :
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return state :
- CAN_TxSTS_Failed
- CAN_TxSTS_Ok
- CAN_TxSTS_Pending
void CAN_CancelTransmitMessage(CAN_Module *CANx, uint8_t Mailbox)Cancels a transmit request.
name CAN_CancelTransmitMessage
brief Cancels a transmit request.
param CANx:
- CAN
param Mailbox (The input parameters must be the following values) :
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return none
Use note: The source comment provides a brief field but no fun field, so this summary is taken from brief; the implementation writes CAN_TSTS_ABRQM0, CAN_TSTS_ABRQM1 or CAN_TSTS_ABRQM2 to CANx->TSTS according to Mailbox, that is, it sets the abort request bit of the selected transmit mailbox, and does nothing for any other value of Mailbox.
void CAN_ReceiveMessage(CAN_Module *CANx, uint8_t FIFONum, CanRxMessage *RxMessage)Receives a message.
name CAN_ReceiveMessage
fun Receives a message.
param CANx:
- CAN
param FIFONum (The input parameters must be the following values) :
- CAN_FIFO0
- CAN_FIFO1
param RxMessage (The input parameters must be the following values) :
- StdId
- It ranges from 0 to 0x7FF
- ExtId
- It ranges from 0 to 0x1FFFFFFF
- IDE
- CAN_Standard_Id
- CAN_Extended_Id
- RTR
- CAN_RTRQ_Data
- CAN_RTRQ_Remote
- DLC
- It ranges from 0 to 8
- Data[0-7]
- It ranges from 0 to 0xFF
- FMI
- It ranges from 0 to 0xFF
return none
void CAN_ReleaseFIFO(CAN_Module *CANx, uint8_t FIFONum)Releases the specified DATAFIFO.
name CAN_ReleaseFIFO
fun Releases the specified DATAFIFO.
param CANx:
- CAN
param FIFONum (The input parameters must be the following values) :
- CAN_FIFO0
- CAN_FIFO1
return none
uint8_t CAN_PendingMessage(const CAN_Module *CANx, uint8_t FIFONum)Returns the number of pending messages.
name CAN_PendingMessage
fun Returns the number of pending messages.
param CANx :
- CAN
param FIFONum (The input parameters must be the following values) :
- CAN_FIFO0
- CAN_FIFO1
return message_pending :
- CAN_FIFOX_PENDING_0
- CAN_FIFOX_PENDING_1
- CAN_FIFOX_PENDING_2
- CAN_FIFOX_PENDING_3
uint8_t CAN_GetLastErrCode(const CAN_Module *CANx)Returns the CANx’s last error code (LEC).
name CAN_GetLastErrCode
fun Returns the CANx's last error code (LEC).
param CANx:
- CAN
return errorcode :
- CAN_ERRORCODE_NoErr No Error
- CAN_ERRORCODE_StuffErr Stuff Error
- CAN_ERRORCODE_FormErr Form Error
- CAN_ERRORCODE_ACKErr Acknowledgment Error
- CAN_ERRORCODE_BitRecessiveErr Bit Recessive Error
- CAN_ERRORCODE_BitDominantErr Bit Dominant Error
- CAN_ERRORCODE_CRCErr CRC Error
- CAN_ERRORCODE_SoftwareSetErr Software Set Error
uint8_t CAN_GetReceiveErrCounter(const CAN_Module *CANx)Returns the CANx Receive Error Counter (REC).
name CAN_GetReceiveErrCounter
fun Returns the CANx Receive Error Counter (REC).
param CANx:
- CAN
return counter_value:
- It ranges from 0 to 255
note In case of an error during reception, this counter is incremented
by 1 or by 8 depending on the error condition as defined by the CAN
standard. After every successful reception, the counter is
decremented by 1 or reset to 120 if its value was higher than 127.
When the counter value exceeds 127, the CAN controller enters the
error passive state.
uint8_t CAN_GetLSBTransmitErrCounter(const CAN_Module *CANx)Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC).
name CAN_GetLSBTransmitErrCounter
fun Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC).
param CANx:
- CAN
return counter_value:
- It ranges from 0 to 255
FlagStatus CAN_GetTransmitFailStatus(const CAN_Module *CANx, uint8_t mailbox_queue)Get the transmit failure status of the given transmit mailbox.
name CAN_GetTransmitFailStatus
fun Get the transmit failure status of the given transmit mailbox.
param CANx:
- CAN
param mailbox_queue:
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetArbitrationLostStatus(const CAN_Module *CANx, uint8_t mailbox_queue)Get the status of arbitration lost.
name CAN_GetArbitrationLostStatus
fun Get the status of arbitration lost.
param CANx:
- CAN
param mailbox_queue:
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetFlagLowestPriority(const CAN_Module *CANx, uint8_t mailbox_queue)Get the flag of lowest priority.
name CAN_GetFlagLowestPriority
fun Get the flag of lowest priority.
param CANx:
- CAN
param mailbox_queue:
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetTransmitMailboxEmptyFlag(const CAN_Module *CANx, uint8_t mailbox_queue)Get the flag of Transmit mailbox empty.
name CAN_GetTransmitMailboxEmptyFlag
fun Get the flag of Transmit mailbox empty.
param CANx:
- CAN
param mailbox_queue:
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetReceiveSignal(const CAN_Module *CANx)Returns the CANx’s receive signal value (RXS).
name CAN_GetReceiveSignal
fun Returns the CANx's receive signal value (RXS).
param CANx:
- CAN
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetLastSamplePoint(const CAN_Module *CANx)Returns the CANx’s Last sample point (LSMP).
name CAN_GetLastSamplePoint
fun Returns the CANx's Last sample point (LSMP).
param CANx:
- CAN
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetReceiveMode(const CAN_Module *CANx)Returns the CANx’s receive mode (RXMD).
name CAN_GetReceiveMode
fun Returns the CANx's receive mode (RXMD).
param CANx:
- CAN
return FlagStatus:
- SET
- RESET
FlagStatus CAN_GetTransmitMode(const CAN_Module *CANx)Returns the CANx’s transmit mode (TXMD).
name CAN_GetTransmitMode
fun Returns the CANx's transmit mode (TXMD).
param CANx:
- CAN
return FlagStatus:
- SET
- RESET
uint8_t CAN_GetMailboxCode(const CAN_Module *CANx)Returns the CANx’s mailbox code (CODE[1:0]).
name CAN_GetMailboxCode
fun Returns the CANx's mailbox code (CODE[1:0]).
param CANx:
- CAN
return mailbox_queue :
- CAN_TXMAILBOX_0
- CAN_TXMAILBOX_1
- CAN_TXMAILBOX_2
- CAN_TxSTS_NoMailBox
void CAN_INTConfig(CAN_Module *CANx, uint32_t CAN_INT, FunctionalState Cmd)Enables or disables the specified CANx interrupts according to Cmd.
name CAN_INTConfig
fun Enables or disables the specified CANx interrupts according
to Cmd.
param CANx:
- CAN
param CAN_INT (The input parameters must be the following values) :
- CAN_INT_TME,
- CAN_INT_FMP0,
- CAN_INT_FF0,
- CAN_INT_FOV0,
- CAN_INT_FMP1,
- CAN_INT_FF1,
- CAN_INT_FOV1,
- CAN_INT_EWG,
- CAN_INT_EPV,
- CAN_INT_BOF,
- CAN_INT_LEC,
- CAN_INT_ERR,
- CAN_INT_WKU,
- CAN_INT_SLK.
param Cmd :
- DISABLE
- ENABLE
return none
FlagStatus CAN_GetFlagSTS(const CAN_Module *CANx, uint32_t CAN_FLAG)Checks whether the specified CAN flag is set or not.
name CAN_GetFlagSTS
fun Checks whether the specified CAN flag is set or not.
param CANx:
- CAN
param CAN_FLAG (The input parameters must be the following values) :
- CAN_FLAG_EWGFL
- CAN_FLAG_EPVFL
- CAN_FLAG_BOFFL
- CAN_FLAG_LEC
- CAN_FLAG_RQCPM0
- CAN_FLAG_RQCPM1
- CAN_FLAG_RQCPM2
- CAN_FLAG_FFMP1
- CAN_FLAG_FFULL1
- CAN_FLAG_FFOVR1
- CAN_FLAG_FFMP0
- CAN_FLAG_FFULL0
- CAN_FLAG_FFOVR0
- CAN_FLAG_WKU
- CAN_FLAG_SLAK
return FlagStatus:
- SET
- RESET
void CAN_ClearFlag(CAN_Module *CANx, uint32_t CAN_FLAG)Clears the CAN’s flag status.
name CAN_ClearFlag
fun Clears the CAN's flag status.
param CANx:
- CAN
param CAN_FLAG (The input parameters must be the following values) :
- CAN_FLAG_RQCPM0
- CAN_FLAG_RQCPM1
- CAN_FLAG_RQCPM2
- CAN_FLAG_FFULL1
- CAN_FLAG_FFOVR1
- CAN_FLAG_FFULL0
- CAN_FLAG_FFOVR0
- CAN_FLAG_WKU
- CAN_FLAG_SLAK
- CAN_FLAG_LEC
return none
INTStatus CAN_GetIntStatus(const CAN_Module *CANx, uint32_t CAN_INT)Checks whether the specified CANx interrupt has occurred or not.
name CAN_GetIntStatus
fun Checks whether the specified CANx interrupt has occurred or not.
param CANx:
- CAN
param CAN_INT (The input parameters must be the following values) :
- CAN_INT_TME
- CAN_INT_FMP0
- CAN_INT_FF0
- CAN_INT_FOV0
- CAN_INT_FMP1
- CAN_INT_FF1
- CAN_INT_FOV1
- CAN_INT_WKU
- CAN_INT_SLK
- CAN_INT_EWG
- CAN_INT_EPV
- CAN_INT_BOF
- CAN_INT_LEC
- CAN_INT_ERR
return INTStatus :
- SET
- RESET
void CAN_ClearINTPendingBit(CAN_Module *CANx, uint32_t CAN_INT)Clears the CANx’s interrupt status.
name CAN_ClearINTPendingBit
fun Clears the CANx's interrupt status.
param CANx:
- CAN
param CAN_INT (The input parameters must be the following values) :
- CAN_INT_TME
- CAN_INT_FF0
- CAN_INT_FOV0
- CAN_INT_FF1
- CAN_INT_FOV1
- CAN_INT_WKU
- CAN_INT_SLK
- CAN_INT_EWG
- CAN_INT_EPV
- CAN_INT_BOF
- CAN_INT_LEC
- CAN_INT_ERR
return none
5.2.3 Demo descriptions
This section describes the 2 bxCAN examples: CAN_LoopBack loops each transmitted message back for internal reception in loopback mode, and CAN_Tx_Rx sends and receives messages through an external transceiver and bus in normal mode.
5.2.3.1 CAN_LoopBack Loopback transfer
Example directory: projects/n32g41x_EVAL/examples/bxCAN/CAN_LoopBack/
Enable the CAN and GPIO clocks→configure PA11 and PA12 for CAN alternate function→initialize CAN and the receive filter in loopback mode→transmit one message and wait for the looped-back reception→verify the received message, delay, and transmit again
| Item | Source analysis |
|---|---|
| Function | In loopback test mode, transmits one standard data frame; the message loops back internally to the receive FIFO, and after the identifier and the 8 data bytes are compared successfully the next frame is transmitted, repeating indefinitely. |
| Source files | src/main.c: main and the message field assignments;src/can_config.c: CAN_CONFIG, CAN_NVIC_Configuration, CAN_GPIO_Configuration and Check_CanRecData;inc/can_config.h: pin and filter macros, the Check_CanRecData declaration and the extern variables;inc/main.h: includes the driver and configuration headers;src/n32g41x_it.c, inc/n32g41x_it.h: interrupt service functions such as CAN_IRQHandler;readme.txt: function, environment and usage notes;MDK-ARM/, EWARM/: Keil and IAR projects. |
| Key configuration | Pins: RX is PA11 and TX is PA12, both on GPIO_AF1, switched by the N32G412 and N32G415 macros;RX is GPIO_MODE_INPUT, GPIO_PULL_UP and GPIO_DS_HIGH, TX is GPIO_MODE_AF_PP and GPIO_DS_HIGH;Mode: OperatingMode is CAN_LoopBack_Mode and TXFP is ENABLE, while TTCM, ABOM, AWKUM, NART and RFLM are DISABLE;Baud rate: 500 Kbps, APB1 48 MHz with prescaler 6 under N32G415 and 40 MHz with prescaler 5 otherwise;Filter: bank 0 in 32-bit mask mode assigned to CAN_FIFO0, admitting only identifier 0x400;Interrupt: FIFO0 pending, preemption and subpriority 0x0; Clock: HSI+PLL, 80 MHz for N32G412 and 96 MHz for N32G415. |
| Program and data path | main first calls CAN_CONFIG to initialize the clock, GPIO, NVIC, CAN and the filter, then fills CAN_TxMessage;in the while loop it first calls CAN_TransmitMessage to request transmission, then repeatedly calls Check_CanRecData in the Rx_Flag is DISABLE loop to compare the message;the FIFO0 pending interrupt triggers CAN_IRQHandler, where CAN_ReceiveMessage reads the message;after a successful check the loop delays and clears Rx_Flag for the next round. |
| Main APIs | CAN_InitStruct, CAN_Init, CAN_InitFilter, CAN_TransmitMessage, CAN_ReceiveMessage, CAN_INTConfig |
| Verification | After download and reset, a CAN analyser shows a message with identifier 0x400 and data 0x00 to 0x07 being transmitted repeatedly; in loopback mode no external transceiver is needed, and the return value of Check_CanRecData can also be observed for a non-zero result. |
| Use note | In loopback mode TX is fed back internally to RX, so no external CAN transceiver or bus is needed; the development environment is KEIL MDK-ARM 5.34 or IAR EWARM 8.50.1, on the N32G41x_STB V1.0 evaluation board. |
Core-code walkthrough and porting
The example first completes clock, pin and CAN initialization, then the main loop transmits a message and verifies the looped-back message with the help of an interrupt.
Data path: main -> CAN_CONFIG enables the clocks and configures GPIO, NVIC, CAN and the filter -> CAN_TransmitMessage requests transmission -> the looped-back reception triggers CAN_IRQHandler -> CAN_ReceiveMessage reads FIFO0 -> Check_CanRecData compares -> after a delay Rx_Flag is cleared
1. Start from default values and reset CAN. CAN_CONFIG first enables the CAN clock, then configures the interrupt and the pins, and then CAN_DeInit resets the registers and CAN_InitStruct fills them with default values.
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN, ENABLE);
CAN_NVIC_Configuration();
CAN_GPIO_Configuration();
CAN_DeInit(CAN);
CAN_InitStruct(&CAN_InitStructure);
When porting to another board, only CAN_GPIO_Configuration and the pin macros in can_config.h need to change.
2. Bit timing gives 500 Kbps per model. N32G415 uses APB1 at 48 MHz with a prescaler of 6, and the other models use APB1 at 40 MHz with a prescaler of 5, with the same segment parameters.
#ifdef N32G415
/* Baud rate = APB1CLK / (BaudRatePrescaler * (TBS1 + TBS2 + 1))
APB1CLK = 48MHz, 48000000 / (6 * (11 + 4 + 1)) = 500000 = 500Kbps */
CAN_InitStructure.RSJW = CAN_RSJW_4tq;
CAN_InitStructure.TBS1 = CAN_TBS1_11tq;
CAN_InitStructure.TBS2 = CAN_TBS2_4tq;
CAN_InitStructure.BaudRatePrescaler = 6;
#else
/* Baud rate = APB1CLK / (BaudRatePrescaler * (TBS1 + TBS2 + 1))
APB1CLK = 40MHz, 40000000 / (5 * (11 + 4 + 1)) = 500000 = 500Kbps */
CAN_InitStructure.RSJW = CAN_RSJW_4tq;
CAN_InitStructure.TBS1 = CAN_TBS1_11tq;
CAN_InitStructure.TBS2 = CAN_TBS2_4tq;
CAN_InitStructure.BaudRatePrescaler = 5;
#endif
When switching model or converting another baud rate, change BaudRatePrescaler, TBS1, TBS2 and RSJW together.
3. Filter 0 admits only identifier 0x400. The filter is configured as 32-bit mask mode and assigned to FIFO0, and both the match values and the masks come from macros in inc/can_config.h, comparing only the bits that must match.
CAN_FilterInitStructure.Filter_Num = 0;
CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode;
CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale;
CAN_FilterInitStructure.Filter_HighId = CAN_STD_ID_LIST_32BIT_H(0x00000400);
CAN_FilterInitStructure.Filter_LowId = CAN_STD_ID_LIST_32BIT_L(0x00000400);
CAN_FilterInitStructure.FilterMask_HighId = CAN_STD_ID_LIST_32BIT_H(0x00000200);
CAN_FilterInitStructure.FilterMask_LowId = CAN_STD_ID_LIST_32BIT_L(0x00000200);
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN_InitFilter(&CAN_FilterInitStructure);
To receive other identifiers, change Filter_HighId, Filter_LowId and the matching mask values together.
4. The interrupt fetches the message and the main loop verifies before retransmitting. The FIFO0 pending interrupt reads the message into CAN_RxMessage, and the main loop waits on the flag after transmitting and compares the message with Check_CanRecData.
void CAN_IRQHandler(void)
{
/* Receives a message */
CAN_ReceiveMessage(CAN, CAN_FIFO0, &CAN_RxMessage);
}
while(1)
{
/* Transmit */
CAN_TransmitMessage(CAN, &CAN_TxMessage);
while(Rx_Flag == DISABLE)
{
Rx_Flag = Check_CanRecData(&CAN_RxMessage, 0x0400, 0x00, CAN_Standard_Id, CAN_RTRQ_Data, 8,
0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0);
}
/* Delay */
wait_slak = 0xFFFF;
while(wait_slak > 0)
{
wait_slak--;
}
Rx_Flag = DISABLE;
}
When the expected message changes, change the Check_CanRecData arguments and the CAN_TxMessage field assignments in main together.
Corresponding source files: src/main.c, src/can_config.c, src/n32g41x_it.c, inc/can_config.h
5.2.3.2 CAN_Tx_Rx Normal-mode transfer
Example directory: projects/n32g41x_EVAL/examples/bxCAN/CAN_Tx_Rx/
Enable the CAN and GPIO clocks→configure PA11 and PA12 for CAN alternate function→initialize CAN and the receive filter in normal mode→transmit one message after start-up→after a message from the bus an interrupt sets the flag and one more message is transmitted
| Item | Source analysis |
|---|---|
| Function | In normal mode, transmits one standard data frame after start-up and then waits for messages on the bus; after one message is received an interrupt sets a flag and the main loop transmits one more frame, repeating indefinitely. |
| Source files | src/main.c: main and the message field assignments;src/can_config.c: CAN_CONFIG, CAN_NVIC_Configuration, CAN_GPIO_Configuration and Check_CanRecData;inc/can_config.h: pin and filter macros, the Check_CanRecData declaration and the extern variables;inc/main.h: includes the driver and configuration headers;src/n32g41x_it.c, inc/n32g41x_it.h: interrupt service functions such as CAN_IRQHandler;readme.txt: function, environment and usage notes;MDK-ARM/, EWARM/: Keil and IAR projects. |
| Key configuration | Pins: RX is PA11 and TX is PA12, both on GPIO_AF1, switched by the N32G412 and N32G415 macros;RX is GPIO_MODE_INPUT, GPIO_PULL_UP and GPIO_DS_HIGH, TX is GPIO_MODE_AF_PP and GPIO_DS_HIGH;Mode: OperatingMode is CAN_Normal_Mode and TXFP is ENABLE, while TTCM, ABOM, AWKUM, NART and RFLM are DISABLE;Baud rate: 500 Kbps, APB1 48 MHz with prescaler 6 under N32G415 and 40 MHz with prescaler 5 otherwise;Filter: bank 0 in 32-bit mask mode assigned to CAN_FIFO0, admitting only identifier 0x400;Interrupt: FIFO0 pending, preemption and subpriority 0x0; Clock: HSI+PLL, 80 MHz for N32G412 and 96 MHz for N32G415. |
| Program and data path | main first calls CAN_CONFIG to initialize the peripheral, then fills CAN_TxMessage;in the while loop it first calls CAN_TransmitMessage to request transmission, then polls Rx_Flag;the FIFO0 pending interrupt triggers CAN_IRQHandler, where CAN_ReceiveMessage reads the message and sets Rx_Flag to ENABLE;the main loop clears Rx_Flag and transmits again. |
| Main APIs | CAN_InitStruct, CAN_Init, CAN_InitFilter, CAN_TransmitMessage, CAN_ReceiveMessage, CAN_INTConfig |
| Verification | An external CAN transceiver and CAN bus are required; other nodes on the bus see a message with identifier 0x400 and data 0x00 to 0x07, and this node transmits one more frame after each received message. |
| Use note | Normal mode needs an external CAN transceiver and a connection to the CAN bus; the development environment is KEIL MDK-ARM 5.34 or IAR EWARM 8.50.1, on the N32G41x_STB V1.0 evaluation board. |
Core-code walkthrough and porting
The example first completes clock, pin and CAN initialization, then the main loop triggers the next transmission from each received message.
Data path: main -> CAN_CONFIG enables the clocks and configures GPIO, NVIC, CAN and the filter -> CAN_TransmitMessage transmits the first frame -> a reception from the bus triggers CAN_IRQHandler -> CAN_ReceiveMessage reads FIFO0 and sets Rx_Flag -> the main loop clears the flag and transmits again
1. Start from default values and reset CAN. CAN_CONFIG first enables the CAN clock, then configures the interrupt and the pins, and then CAN_DeInit resets the registers and CAN_InitStruct fills them with default values.
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_CAN, ENABLE);
CAN_NVIC_Configuration();
CAN_GPIO_Configuration();
CAN_DeInit(CAN);
CAN_InitStruct(&CAN_InitStructure);
When porting to another board, only CAN_GPIO_Configuration and the pin macros in can_config.h need to change.
2. Operating mode is normal transfer with 500 Kbps. OperatingMode is CAN_Normal_Mode and the bit timing is still split per model.
/* CAN cell init */
CAN_InitStructure.TTCM = DISABLE;
CAN_InitStructure.ABOM = DISABLE;
CAN_InitStructure.AWKUM = DISABLE;
CAN_InitStructure.NART = DISABLE;
CAN_InitStructure.RFLM = DISABLE;
CAN_InitStructure.TXFP = ENABLE;
CAN_InitStructure.OperatingMode = CAN_Normal_Mode;
#ifdef N32G415
/* Baud rate = APB1CLK / (BaudRatePrescaler * (TBS1 + TBS2 + 1))
APB1CLK = 48MHz, 48000000 / (6 * (11 + 4 + 1)) = 500000 = 500Kbps */
CAN_InitStructure.RSJW = CAN_RSJW_4tq;
CAN_InitStructure.TBS1 = CAN_TBS1_11tq;
CAN_InitStructure.TBS2 = CAN_TBS2_4tq;
CAN_InitStructure.BaudRatePrescaler = 6;
#else
/* Baud rate = APB1CLK / (BaudRatePrescaler * (TBS1 + TBS2 + 1))
APB1CLK = 40MHz, 40000000 / (5 * (11 + 4 + 1)) = 500000 = 500Kbps */
CAN_InitStructure.RSJW = CAN_RSJW_4tq;
CAN_InitStructure.TBS1 = CAN_TBS1_11tq;
CAN_InitStructure.TBS2 = CAN_TBS2_4tq;
CAN_InitStructure.BaudRatePrescaler = 5;
#endif
To use another mode change OperatingMode, and to convert the baud rate change BaudRatePrescaler, TBS1, TBS2 and RSJW together.
3. The main loop transmits and then waits on the flag. Each round transmits one frame and then blocks in the empty Rx_Flag is DISABLE loop until the interrupt sets the flag, after which the flag is cleared and the next round begins.
while(1)
{
CAN_TransmitMessage(CAN, &CAN_TxMessage);
while(Rx_Flag == DISABLE)
{
}
Rx_Flag = DISABLE;
}
To replace the polling with an event-driven design, organise the next transmission directly inside CAN_IRQHandler.
4. The interrupt sets a software flag after receiving a message. CAN_IRQHandler reads the message from FIFO0 and sets Rx_Flag to ENABLE, which is what makes the main loop continue transmitting.
void CAN_IRQHandler(void)
{
/* Receives a message */
CAN_ReceiveMessage(CAN, CAN_FIFO0, &CAN_RxMessage);
/* flag set */
Rx_Flag = ENABLE;
}
Corresponding source files: src/main.c, src/can_config.c, src/n32g41x_it.c, inc/can_config.h
5.2.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Width of one access to a CAN register | The CAN peripheral registers must be accessed as words (32 bits), never as half-words or bytes; when driving the registers directly, read and write them at their word width. |
User manual |
| Changing bit timing outside initialization mode | CAN_BTIM can only be modified while the CAN cell is in initialization mode, and the bit timing cannot be changed after leaving that mode;set the baud rate and sampling point once during initialization. |
User manual |
| Configuring or modifying a receive filter | Before changing the filter values and settings, clear the corresponding CAN_FMC.FAC bit or set CAN_FMC.FINITM to 1;CAN_FMC.FINITM set to 1 disables reception, and unused filter banks should stay deactivated. |
User manual |
| Writing transmit mailbox data | Software may modify the transmit mailbox registers only while CAN_TSTS.TMEM is 1 (mailbox empty);after the mailbox TXRQ is set the mailbox enters the pending state and its registers are write-protected. |
User manual |
| Aborting a transmit request | Setting CAN_TSTS.ABRQM can abort a transmit request: when the mailbox is in the ready or pending state it aborts immediately;when the mailbox is transmitting, a failed transmission is aborted after it becomes ready and the transmit-OK flag is cleared, while a successful transmission empties the mailbox and the hardware sets the transmit-OK flag. |
User manual |
| Entering initialization mode or starting from reset | After reset CAN is in sleep mode; to enter initialization mode from sleep, set CAN_MCTRL.INIRQ and clear CAN_MCTRL.SLPRQ at the same time, then wait for CAN_MSTS.INIAK to be set. |
User manual |
| Recovery after bus-off | When the transmit error counter exceeds 255 the bus-off flag is set; recovery requires 128 contiguous 11-bit recessive sequences on the CANRX pin, and initialization mode does not monitor CANRX, so recovery cannot complete there and the cell must leave initialization mode first. |
User manual |
The N32G412 and N32G415 series errata sheet V1.0.0 (2026.6.30) lists a single row for revision A chips with an empty errata link column, and gives no CAN-related entries. All the conclusions above are taken from the “Controller area network (CAN)” chapter of the user manual.