2012-02-19 07:11 PM
Im trying to use the CAN interface on the STM32F4 discovery board. I am using the STM code sample which says it configures it to 1Mbit baud rate but this doesnt seem to be the case, with an oscilloscope hooked I am getting a baud rate of 2kBit and a 5us sync pulse (it should be about 250ns for 1Mbit from what I have read.
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK, ENABLE);
/* Connect CAN pins to AF9 */
GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
GPIO_PinAFConfig(CAN_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT);
/* Configure CAN RX and TX pins */
GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN | CAN_TX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(CAN_GPIO_PORT, &GPIO_InitStructure);
/* CAN configuration ********************************************************/
/* Enable CAN clock */
RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
/* CAN register init */
CAN_DeInit(CANx);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM = DISABLE;
CAN_InitStructure.CAN_ABOM = DISABLE;
CAN_InitStructure.CAN_AWUM = DISABLE;
CAN_InitStructure.CAN_NART = DISABLE;
CAN_InitStructure.CAN_RFLM = DISABLE;
CAN_InitStructure.CAN_TXFP = DISABLE;
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
/* CAN Baudrate = 1 MBps (CAN clocked at 30 MHz) */
CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
CAN_InitStructure.CAN_Prescaler = 2;
CAN_Init(CANx, &CAN_InitStructure);
This is all the standard code with a comment towards the end that it sets it up for 1Mbit with a 30MHz clock, the only thing I can think of is that the 30MHz clock asumption is wrong, I cant see where this would be coming from. From what I can find the APB1 clock should just be running off the HSI clock but this doesnt seem to be the case.
Can anyone point me in the right direction for fixing this? (I am using IAR for my IDE if that makes any difference)
2012-02-22 05:06 AM
Hi i.philip,
I also try to set up the can interface. Here my code, which is unfortunatly also not working: CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); //for CAN1 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); //for CAN2 /* GPIOD Periph clock enable */ //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIO B Takt RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); /* Configure PD0 in R */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOD, &GPIO_InitStructure); /* Configure PD1 out T */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOD, &GPIO_InitStructure); CAN_DeInit(CAN1); CAN_StructInit(&CAN_InitStructure); // CAN cell init CAN_InitStructure.CAN_TTCM=DISABLE; CAN_InitStructure.CAN_ABOM=DISABLE; CAN_InitStructure.CAN_AWUM=ENABLE; CAN_InitStructure.CAN_NART=DISABLE; CAN_InitStructure.CAN_RFLM=DISABLE; CAN_InitStructure.CAN_TXFP=DISABLE; //CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; CAN_InitStructure.CAN_Mode = CAN_Mode_Silent; // CAN Bitrate CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; // SJW (1 bis 4 möglich) CAN_InitStructure.CAN_BS1=CAN_BS1_13tq; // Samplepoint 72% CAN_InitStructure.CAN_BS2=CAN_BS2_2tq; // Samplepoint 72% //CAN_InitStructure.CAN_Prescaler=1; // 2000 kbit/s //CAN_InitStructure.CAN_Prescaler=2; // 1000 kbit/s //CAN_InitStructure.CAN_Prescaler=4; // 500 kbit/s //CAN_InitStructure.CAN_Prescaler=5; // 400 kbit/s //CAN_InitStructure.CAN_Prescaler=8; // 250 kbit/s //CAN_InitStructure.CAN_Prescaler=10; // 200 kbit/s CAN_InitStructure.CAN_Prescaler=16; // 125 kbit/s //CAN_InitStructure.CAN_Prescaler=20; // 100 kbit/s //CAN_InitStructure.CAN_Prescaler=40; // 50 kbit/s //CAN_InitStructure.CAN_Prescaler=80; // 40 kbit/s //CAN_InitStructure.CAN_Prescaler=200; // 10 kbit/s //CAN_InitStructure.CAN_Prescaler=1023; // ganz langsam CAN_Init(CAN1, &CAN_InitStructure); // CAN filter init CAN_FilterInitStructure.CAN_FilterNumber=1; CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit; CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; CAN_FilterInit(&CAN_FilterInitStructure); // CAN FIFO0 message pending interrupt enable CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE); //Nachrichten im FIFO ''1'' CAN_ITConfig(CAN1, CAN_IT_SLK, ENABLE); //gesetzt wenn CAN im sleep mode Maybe this helps you or you got an idea from what is wrong in my code.2012-02-22 07:23 AM
2012-02-22 11:22 PM
Hi all,
just something I was thinking about, since my last post. I connected a can bus to my ports PD0 and PD1. I have a tool called PCANopen Magic pro which tells, that there is traffic on the can bus, I see the IDs and the data. But my receive fifo doesn´t receive anything. I tried to monitor this with: CanRxMsg* RxMessage; CanRxMsg Rx; FlagStatus flagfifo0 = RESET; RxMessage = &Rx; /* Clear R_xMessage */ RxMessage->StdId=0x01; RxMessage->ExtId=0x02; RxMessage->IDE=4; RxMessage->DLC=0; RxMessage->FMI=0; for(uint8_t i=0; i<8; i++) { RxMessage->Data[i]=0x00; } flagfifo0 = CAN_GetFlagStatus(CAN1,CAN_FLAG_FMP0); flagfifo0 = CAN_GetFlagStatus(CAN1,CAN_FLAG_FMP0); if(flagfifo0 == SET) CAN_Rec(CAN1,CAN_FIFO0,&Rx); Greetings Bjoern2012-02-23 06:36 AM
Hello all,
after checking today I found out that the can initialsation (CAN_init) is returning CAN_InitStatus_Failed. After that I think the CAN controller is not working normally. In the Reference Manual is written that about the INAK bit 0 in the CAN->MSR register, which goes to 0 by hardware after init, if CAN->MCR INRQ gets 0 and 11 consecutive recessive bits are on CAN RX signal. As I have a CAN bus running on the input, what does this mean?? Thanks in advance Bjoern2012-02-29 12:09 AM
Hello again,
I finaly solved the problem. The main thing is that my adjusting to the Baudrate was wrong. The AHB1 Bus (Can is conected to) is running with 42MHz compared to 36 MHz on the old STMF103 controllers. Therefore I had to calculate the numbers new. In the RM0090 side 783 is written how you have to calculate the numbers. Mainly it is easier to understand if you think of 42MHz divided by my Baudrate of 125KHz is 336 clock cycles . 336 clk = CAN_Prescaler * (1 + CAN_BS1 + CAN_BS2) So if you set the CAN_Prescaler to 16 : 21 = (1 + CAN_BS1 + CAN_BS2) And to get a sample point of 72 % you can either use CAN_BS1 = 14 and CAN_BS2 = 6 or CAN_BS1 = 15 and CAN_BS2 = 5 Both are working. // CAN Bitrate CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; // SJW (1 bis 4 möglich)CAN_InitStructure.CAN_BS1=CAN_BS1_14tq; // Samplepoint 72%
CAN_InitStructure.CAN_BS2=CAN_BS2_6tq; // Samplepoint 72% //CAN_InitStructure.CAN_Prescaler=1; // 2000 kbit/s //CAN_InitStructure.CAN_Prescaler=2; // 1000 kbit/s //CAN_InitStructure.CAN_Prescaler=4; // 500 kbit/s //CAN_InitStructure.CAN_Prescaler=5; // 400 kbit/s //CAN_InitStructure.CAN_Prescaler=8; // 250 kbit/s //CAN_InitStructure.CAN_Prescaler=10; // 200 kbit/s CAN_InitStructure.CAN_Prescaler=16; // 125 kbit/s //CAN_InitStructure.CAN_Prescaler=20; // 100 kbit/s //CAN_InitStructure.CAN_Prescaler=40; // 50 kbit/s //CAN_InitStructure.CAN_Prescaler=80; // 40 kbit/s //CAN_InitStructure.CAN_Prescaler=200; // 10 kbit/s //CAN_InitStructure.CAN_Prescaler=1023; // ganz langsam I haven´t tried this for other baudrates, let me know if it works with other numbers. Greetings Bjoern
2013-12-13 06:15 AM
Hi Buddy,
I am still confused about this calculation. From where you found this equation ? clk = CAN_Prescaler * (1 + CAN_BS1 + CAN_BS2) And how you calculated this 72% accuracy? As said above how 42Mhz clock is come for CAN module?2013-12-13 06:35 AM
CAN_BitRate = CAN_CLK / (CAN_Prescaler * (CAN_SJW + CAN_BS1 + CAN_BS2))
Where CAN_CLK is the source APB/AHB clock, nominally 36 or 42 MHz, or WHATEVER you have the buses running at, which at the end of the day you control. You are looking at the cycles that account for a BIT (aka TQ, Time Quantum), and dividing it into the clocking source used to generate the timing. The calculation seems self evident, you could work the numbers on examples. Not sure where the 72% comes from, or what it is referring too.2013-12-13 10:33 PM
I was searching in example code for this frequency.
in example Systemcoreclock is set to 168Mhz. External crystal is 8Mhz. But I was not able to get the calculation for this APB clock how they set it to 36 or 42Mhz. What I understand from clock study is that all peripheral is running on this APB clock. Please correct me if I am wrong.2013-12-13 10:49 PM
The ratio of the APB1 and APB2 (peripheral) clocks with respect to the AHB (HCLK hardware) is defined in system_stm32f4xx.c
APB1 is nominally div 4 (168/4 = 42) APB2 is nominally div 2 (168/2 = 84) You can use RCC_GetClocksFreq() function to retrieve the frequencies of these clocks. The CAN peripherals are on APB1 /* CANx Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); Pretty sure the Reference Manual RM0090 has a clock tree diagram, and what devices are attached to what buses.