2013-04-10 06:17 AM
Hello!
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 inred
:(
GPIO_InitTypeDef GPIO_InitStructure;
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN GPIOs configuration ***********************************/
/* Enable GPIOD clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Connect PD1 to CAN1_Tx pin */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1);
/* Connect PD0 to CAN1_Rx pin */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1);
/* Configure CAN1_Rx(PD0) and CAN1_Tx(PD1) pins */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
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(GPIOD, &GPIO_InitStructure);
/* CAN configuration *****************************************/
Controller area network (CAN) UM1061
122/634 DocID 18540 Rev 1
/* Enable CAN1 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
/* 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 = 1MBps (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(CAN1, &CAN_InitStructure);
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber = 0;
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
CAN_FilterInit(&CAN_FilterInitStructure);
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 usingRCC_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 getting1.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 theRCC_GetClocksFreq
function? Thanks, Dave #can #stm32f2072013-04-10 06:41 AM
GetClockFreq uses a computation based on HSE_VALUE (or HSI_VALUE), and is not a measurement of speed.
Check what you have HSE_VALUE set to in your project. Check what you have the HSE running at externally. Export clocks via an MCOx pin, measure. If serial port baud clocks are correct, HSE_VALUE probably is too. Check what is being set up in system_stm32fxx.c, and SystemInit()2013-04-11 05:23 AM
Thanks for the input... Turns out the
SetSysClock
function was turning on the HSE oscillator, while I thought I was running from the HSI. Since the crystal on our board is 20MHz instead of the 25MHz part expected bySetSysClock
, resulting in the incorrect APB1 frequency and CAN baud rate. A quick adjustment to PLL_M is all that was necessary.Thanks again for pointing me in the right direction!Dave2013-04-11 06:59 AM
Awesome, thanks for the update.