2024-05-22 12:00 AM
Hello dear friends,
It's been a week since I worked on the CAN transceiver and couldn't make it work. I have set up the chip rcc, bit rate, and receive interrupt of CAN, set the receive filter, and the receiver id in transmission, with no success. I have used only a single board and connected Tx to Rx (PD0 PD9) through a jumper. I have checked that there no frame on the CAN Analyzer.
The code is attached. Help me what had make it not
#include "Mcu.h"
#include "stm32f4xx.h"
void CAN1_Init(void);
void CAN1_Tx(uint8_t tr);
uint8_t CAN1_Rx(void);
void TIM4_ms_Delay(uint32_t delay);
uint8_t k = 0;
uint8_t rec = 0;
void GPIO_Init(){
// Enable GPIOB clock signal
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
// Configuring PD0 and PD1 in alternate function mode
GPIOD->MODER |= GPIO_MODER_MODE1_1 | GPIO_MODER_MODE0_1 ;
// Selecting AF9 for PD0 and PD1 (See Page 272 of dm00031020)
GPIOD->AFR[1] |= (GPIO_AFRL_AFSEL0_3 | GPIO_AFRL_AFSEL0_1 | GPIO_AFRL_AFSEL1_0 | GPIO_AFRL_AFSEL1_3);
}
void CAN1_Init(){
/* 1. Setting Up the Baud Rate and Configuring CAN1 in
* Loop Back Mode -------------------------------------------------------*/
// Enable clock for CAN1
RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
// Entering CAN Initialization Mode and wait for acknowledgment
CAN1->MCR |= CAN_MCR_INRQ;
while (!(CAN1->MSR & CAN_MSR_INAK)){}
//Set Loop back mode for CAN1
CAN1->BTR &= ~CAN_BTR_LBKM;
//Setting the Re synchronization jump width to 1
CAN1->BTR &= ~CAN_BTR_SJW;
//Setting the no. of time quanta for Time segment 2
// TS2 = 4-1;
CAN1->BTR &= ~(CAN_BTR_TS2);
CAN1->BTR |= (CAN_BTR_TS2_1 | CAN_BTR_TS2_0);
//Setting the no. of time quanta for Time segment 1
// TS1 = 3-1;
CAN1->BTR &= ~(CAN_BTR_TS1);
CAN1->BTR |= (CAN_BTR_TS1_1);
//Setting the Baud rate Pre-scalar for CAN1
// BRP[9:0] = 16-1
CAN1->BTR |= ((16-1)<<0);
// Exit the Initialization mode for CAN1
// Wait until the INAK bit is cleared by hardware
CAN1->MCR &= ~CAN_MCR_INRQ;
while (CAN1->MSR & CAN_MSR_INAK){}
//Exit Sleep Mode
CAN1->MCR &= ~ CAN_MCR_SLEEP;
while (CAN1->MSR & CAN_MSR_SLAK);
/* 2. Setting up the Transmission----------------------------------------*/
CAN1->sTxMailBox[0].TIR = 0;
//Setting up the Std. ID
CAN1->sTxMailBox[0].TIR = (0x01 << 21);
CAN1->sTxMailBox[1].TIR = (0x02 << 21);
CAN1->sTxMailBox[2].TIR = (0x03 << 21);
CAN1->sTxMailBox[3].TIR = (0x04 << 21);
CAN1->sTxMailBox[0].TDHR = 0;
// Setting Data Length to 1 Byte.
CAN1->sTxMailBox[0].TDTR = 1;
/* 3. Configuring the Filters--------------------------------------------*/
//Enter Filter Initialization mode to configure the filters
CAN1->FMR |= CAN_FMR_FINIT;
// Configuring the Number of Filters Reserved for CAN1
// and also the start bank for CAN2
CAN1->FMR |= 14<<8;
// Select the single 32-bit scale configuration
CAN1->FS1R |= CAN_FS1R_FSC13;
// Set the receive ID
//CAN1->sFilterRegister[13].FR1 = 0x0; // Accept any message ID
CAN1->sFilterRegister[0].FR1 = (0x01 << 21);
CAN1->sFilterRegister[1].FR1 = (0x02 << 21);
CAN1->sFilterRegister[2].FR1 = (0x03 << 21);
CAN1->sFilterRegister[3].FR1 = (0x04 << 21);
// Select Identifier List mode
CAN1->FM1R &= ~CAN_FM1R_FBM13; // Use mask mode
//Activating filter 13
//CAN1->FA1R |= CAN_FA1R_FACT13;
CAN1->FA1R |= (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
//Exit filter Initialization Mode
CAN1->FMR &= ~CAN_FMR_FINIT;
}
void CAN1_Tx(uint8_t tr){
// Put the Data to be transmitted into Mailbox Data Low Register
CAN1->sTxMailBox[0].TDLR = tr;
// Request for Transmission
CAN1->sTxMailBox[0].TIR |= 1;
}
uint8_t CAN1_Rx(){
// Monitoring FIFO 0 message pending bits FMP0[1:0]
while(!(CAN1->RF0R & 3)){}
// Read the message ID from the FIFO 0 mailbox
uint32_t RIR = CAN1->sFIFOMailBox[0].RIR;
uint8_t RxD = (CAN1->sFIFOMailBox[0].RDLR) & 0xFF;
// Extract message ID from RIR
uint32_t msgID = RIR >> 21;
// Releasing FIFO 0 output mailbox
CAN1->RF0R |= 1 << 5;
return msgID;
}
int main()
{
GPIO_Init();
CAN1_Init();
while (1)
{
// Main program loop, no need for delay here
// Main program loop, no need for delay here
CAN1_Tx(k);
rec = CAN1_Rx();
k += 1;
if (k > 25)
k = 0;
}
}
2024-05-22 12:11 AM
Preferable to continue prior thread. https://community.st.com/t5/stm32-mcus-boards-and-hardware/implement-can-communication-on-stm32f407-discovery-board/td-p/676445
Not sure there's significant interest in register based code. If not in Loopback you need a receiving node to accept / acknowledge data.
I think the EVAL boards had some CAN to CAN examples
2024-05-22 02:24 AM
I agree with @Tesla DeLorean , we don't think there is an interest for CAN coding at register level! Unless you explain the purpose.
Also be sure you configure correctly the Rx GPIO pin: in loopback mode you need to set the internal pull-up for the Rx pin. See that thread: https://community.st.com/t5/stm32-mcus-products/stm32f042g6ux-can-issue/m-p/675133#M245238.
That's why I suggested you in the other thread to first run a HAL example then inspire from the HAL driver implementation and if there will be some issues with your code do the comparison register values between what you get with HAL and with your code.