AnsweredAssumed Answered

STM32 CAN: Having trouble with baud rate

Question asked by david.rea on Apr 10, 2013
Latest reply on Apr 11, 2013 by Clive One

I'm working on bringing up the CAN peripheral on a STM32F207VCT6 part. I followed the CAN Programming Example in the Peripheral Driver Library manual (pertinent lines highlighted in red):

01.GPIO_InitTypeDef GPIO_InitStructure;
02.CAN_InitTypeDef CAN_InitStructure;
03.CAN_FilterInitTypeDef CAN_FilterInitStructure;
04./* CAN GPIOs configuration ***********************************/
05./* Enable GPIOD clock */
06.RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
07./* Connect PD1 to CAN1_Tx pin */
08.GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
09./* Connect PD0 to CAN1_Rx pin */
10.GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
11./* Configure CAN1_Rx(PD0) and CAN1_Tx(PD1) pins */
12.GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
13.GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
14.GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
15.GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
16.GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
17.GPIO_Init(GPIOD, &GPIO_InitStructure);
18./* CAN configuration *****************************************/
19.Controller area network (CAN) UM1061
20.122/634 DocID 18540 Rev 1
21./* Enable CAN1 clock */
22.RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
23./* CAN cell init */
24.CAN_InitStructure.CAN_TTCM = DISABLE;
25.CAN_InitStructure.CAN_ABOM = DISABLE;
26.CAN_InitStructure.CAN_AWUM = DISABLE;
27.CAN_InitStructure.CAN_NART = DISABLE;
28.CAN_InitStructure.CAN_RFLM = DISABLE;
29.CAN_InitStructure.CAN_TXFP = DISABLE;
30.CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
31.CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
32./* CAN Baudrate = 1MBps (CAN clocked at 30 MHz) */
33.CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
34.CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq;
35.CAN_InitStructure.CAN_Prescaler = 2;
36.CAN_Init(CAN1, &CAN_InitStructure);
37./* CAN filter init */
38.CAN_FilterInitStructure.CAN_FilterNumber = 0;
39.CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
40.CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
41.CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
42.CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
43.CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
44.CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
45.CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
46.CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;

Calling the CAN_Transmit function successfully enqueues my test message for transmission, and the CAN peripheral begins trying to send it out on the bus. Looking at the traffic with a scope, however, the bit times appear to be about 1.25μsec long - not the 1.0μsec you'd expect running at 1Mbps.

From the chip reference manual (RM0033, page 775), setting the prescaler to 2 with an APB1 clock rate of 30MHz (checked using RCC_GetClocksFreq) would seem to result in a time quantum duration of:

(2 + 1) * (1 / 30e6) = 1e-7 = 0.1μsec

With BS1 and BS2 set to 6 and 8 time quanta (respectively) the nominal bit time would then be:

(1 * 0.1μsec) + [0.1μsec * 6] + [0.1μsec * 8] = 0.1μsec * (1+6+8) = 1.5μsec

But this results in a baud rate of about 666Kbps, not 1Mbps as indicated in the example comments. And after verifying the register contents on my running target, I'm still getting 1.25μsec bits, for a baud rate of 800Kbps.

So either something is wrong with my configuration (CAN_BTR = 0x00750001) or my APB1 clock is actually running slower than 30MHz. Is there any way to check the APB1 clock rate other than the RCC_GetClocksFreq function?