cancel
Showing results for 
Search instead for 
Did you mean: 

How do I implement a CAN Bus on my STM32F042k6 without using Std Lib or Cube MX?

I am trying since a couple of days to implement a CAN Bus communication for my above mentioned board without success. I wish to do this using the Registers only. Can someone give some hints on how I should proceed? or a link?. Thanks in advance.

1 ACCEPTED SOLUTION

Accepted Solutions

I have had the solution to my problem. The issue was in the Bit Timing Register. The values were not corresponding to my CAN Adapter

View solution in original post

6 REPLIES 6
AvaTar
Lead

I would get the SPL for the F0xx, and take a CAN example as starting point.

https://www.st.com/content/st_com/en/products/embedded-software/mcu-mpu-embedded-software/stm32-embedded-software/stm32-standard-peripheral-libraries/stsw-stm32048.html

Take the relevant register settings and initialization sequence, and re-code it your way.

No need to make things too difficult.

> I wish to do this using the Registers only.

I would still go with the CMSIS header files and naming conventions.

This is zero extra effort, and makes your code more readable & portable.

I followed the CAN example in the SPL and now I have a problem. The CAN Intterupt doesnot fire. Can someone give me some help?

>>Can someone give me some help?

You make it very hard to help you. That something "doesn't work" imparts very little information, there are a million ways to fail. So rather that take the Thomas Edison approach, define clearly what you're doing so other can inspect. Determine what pieces actually work as expected so you can focus on the parts/point where failure occurs. If you want to do register level programming the onus is on you to assimilate the Reference Manual. Perhaps use the SPL/HAL to prove if your hardware is viable, and then recode at a register level that suits you.

Do you have the vectors set up? Do you enable the interrupt in the NVIC? Do you enable the interrupt in the peripheral? Do you actually get any events causing interrupts?

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

Hi @Community member​  thanks for your reply.

void CAN_Setup(void)
{
	uint32_t TSEG1 = 12, TSEG2 = 5, SJW = 1;
	uint32_t BRP = 0;
	/*Enable Clock on CAN Bus*/
	SET_BIT(RCC->APB1ENR, RCC_APB1ENR_CANEN);
	CAN_GPIO_Setup();
	/* Request initialisation */
	SET_BIT(CAN->MCR, CAN_MCR_INRQ);
	while ((CAN->MSR & CAN_MSR_INAK) == 0);
	CAN->MCR |= CAN_MCR_NART;
	/* Exit from sleep mode */
	CLEAR_BIT(CAN->MCR,CAN_MCR_SLEEP);
	BRP = (36000000 / (uint32_t)(8 * (500000))) - 1;
	CAN->BTR &= ~(((        0x03) << 24) | ((        0x07) << 20) | ((         0x0F) << 16) | (         0x1FF));
	CAN->BTR |=  ((((SJW-1) & 0x03) << 24) | (((TSEG2-1) & 0x07) << 20) | (((TSEG1-1) & 0x0F) << 16) | ((BRP-1) & 0x3FF));
	/*Enable Interrupts for FIFO0 anm message pending*/
	CAN->IER = CAN_IER_FMPIE0;
	/*Activate Interrupt for CAN Bus*/
	NVIC_EnableIRQ(CEC_CAN_IRQn);
	NVIC_SetPriority(CEC_CAN_IRQn,0);
	/*Request the CAN Hardware to enter Normal mode */
	CLEAR_BIT(CAN->MCR, CAN_MCR_INRQ);
	while((CAN->MSR & CAN_MSR_INAK) != 0);
}
void CAN_Filter_Init(void)
{
		/*Deactivate filter 0 */
		CAN->FA1R &= ~(CAN_FA1R_FACT0);
	  /* Initialisation mode for the filter */
	  /* Select the start slave bank */
		MODIFY_REG (CAN->FMR ,
			CAN_FMR_CAN2SB   ,
			CAN_FMR_FINIT    |
			(uint32_t) 14 << 8U );
		/*Filter Mode Mask */
		CAN->FM1R &= ~ CAN_FM1R_FBM0;
		/*Set CAN Filter Scale Register*/
		CAN->FS1R |= CAN_FS1R_FSC0;
		/*Filter 0 Assigment to FIFO0*/
		CAN->FFA1R &= ~ CAN_FFA1R_FFA0;
		/*32Bit Identifier*/
		CAN->sFilterRegister[0].FR1 = 0x0000; /*Accepts all Ids*/
		/*Activate filter 0 */
		CAN->FA1R |= CAN_FA1R_FACT0;
		/* Leave the initialisation mode for the filter */
		CLEAR_BIT(CAN->FMR, ((uint32_t)CAN_FMR_FINIT));
 
}

Above are some snippets of my setup. Here is my main

#include "stm32f0xx.h"
#include "can.h"
 
void Delay(void);
 
CAN_MSG CanTx;
CAN_MSG CanRx;
 
int main(void)
{
 
	CAN_Init();
	CanTx.ID = 0x2;
	CanTx.Format = STANDARD_FORMAT;
	CanTx.Type = DATA_FRAME;
	CanTx.DLC = 8;
	CanTx.Data[0] = 0;
	CanTx.Data[1] = 0x1;
	CanTx.Data[2] = 0x2;
	CanTx.Data[3] = 0x3;
	CanTx.Data[4] = 0x4;
	CanTx.Data[5] = 0x5;
	CanTx.Data[6] = 0x6;
	CanTx.Data[7] = 0x7;
 
 
  while (1)
  {
	CAN_Transmit(&CanTx);
  }
}
 
 
void Delay(void)
{
	for(int i=0;i<0x60000;i++){}
}
 
 
 
void CEC_CAN_IRQHandler(void)
{
	  if (CAN->RF0R & CAN_RF0R_FMP0) {			      // message pending ?
			CAN_Receive(&CanRx);                       // read the message
	  }
}
 

This is the summary of my code. Im working with 36MHz Clock Frequncy and I am Using FIFO0. The function CEC_CAN_IRQHandler doesnot fire.

I have had the solution to my problem. The issue was in the Bit Timing Register. The values were not corresponding to my CAN Adapter

can u give complete CAN communication code my mail is madayaswanth9@gmail.com