cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407 can communication normal mode not working

rohitkumarkv07
Associate II

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;
	}
}

 

2 REPLIES 2

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
SofLit
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.