2012-07-13 06:57 AM
Hi all,
I am trying to get the CAN interface working on the STM32F4DISCOVERY board.After calling the configuration functions from the peripheral library, when I tried to transmit message with just a oscilloscope connected to the TX and RX pins it does not work. I tried usng CAN_TransmitStatus() to see the status of the mailbox and it returned ''pending''. Then I tracked down the register in the CAN controller, the error flag is up and further more it says ''BIT DOMINANT error''... I don't know if I need to connect to a transceiver first and hook this board onto a CAN bus before I test it out? Or is it just something wrong with the configuration.Here is the code I had for the configuration part:---(I just used GPIOE pin0 to see if the program is running, nothing else) /* Enable GPIO clock */ RCC_AHB1PeriphClockCmd(CAN_GPIO_CLK|RCC_AHB1Periph_GPIOE, 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); //RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); //configure a pin for debug GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOE, &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); /* CAN filter init */#ifdef USE_CAN1 CAN_FilterInitStructure.CAN_FilterNumber = 0;#else /* USE_CAN2 */ CAN_FilterInitStructure.CAN_FilterNumber = 14;#endif /* USE_CAN1 */ 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); /* Transmit Structure preparation */ TxMessage.StdId = 0x321; TxMessage.ExtId = 0x01; TxMessage.RTR = CAN_RTR_DATA; TxMessage.IDE = CAN_ID_STD; TxMessage.DLC = 1; /* Enable FIFO 0 message pending Interrupt */ CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);Any help is very appreciated. Thanks!Keybo2012-07-23 11:55 AM
Hi!
I am also trying to set up CAN interface on STM32F4Discovery ... but I have trouble with CAN Initialization ... the CAN_Init() function always returns value CAN_InitStatus_Failed. What about your code ... does it work? Does the CAN_Init return value CAN_InitStatus_Success? Anyway, here is my code ... could you help me? Thanks!void RCC_Configuration(void) {
/* ENABLE CLOCKS */ /* GPIOB clock enable */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); /* USART3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); /* CAN1 clock enable */ RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* CAN2 clock enable */ RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); }void GPIO_Configuration(void) {
GPIO_InitTypeDef GPIO_InitStructureUSART; GPIO_InitTypeDef GPIO_InitStructureCAN_RX; GPIO_InitTypeDef GPIO_InitStructureCAN_TX;/* GPIO USART Configuration */
GPIO_InitStructureUSART.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; GPIO_InitStructureUSART.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructureUSART.GPIO_OType = GPIO_OType_PP; GPIO_InitStructureUSART.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructureUSART.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructureUSART);/* Connect USART to AF */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3); //USART_TX = PB10 GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3); //USART_RX = PB11/* GPIO CAN_RX Configuration */
GPIO_InitStructureCAN_RX.GPIO_Pin = GPIO_Pin_12; GPIO_InitStructureCAN_RX.GPIO_Mode = GPIO_Mode_AF; //GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP; //GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL; //GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructureCAN_RX);/* GPIO CAN_TX Configuration */
GPIO_InitStructureCAN_TX.GPIO_Pin = GPIO_Pin_13; GPIO_InitStructureCAN_TX.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructureCAN_TX.GPIO_OType = GPIO_OType_PP; GPIO_InitStructureCAN_TX.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructureCAN_TX);/* Connect CAN_RX & CAN_TX to AF9 */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); //CAN_RX = PB12 GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); //CAN_TX = PB13 }void USART_Configuration(void) {
USART_InitTypeDef USART_InitStructure;/* USART3 configuration */
/* 256000 baud, window 8bits, one stop bit, no parity, no hw control, rx/tx enabled */ USART_InitStructure.USART_BaudRate = 256000; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART3, &USART_InitStructure);USART_Cmd(USART3, ENABLE);
}void CAN_Configuration(void) {
CAN_InitTypeDef CAN_InitStructure;/* CAN2 reset */
CAN_DeInit(CAN2);/* CAN2 configuration */
CAN_InitStructure.CAN_TTCM = DISABLE; // time-triggered communication mode = DISABLED CAN_InitStructure.CAN_ABOM = DISABLE; // automatic bus-off management mode = DISABLED CAN_InitStructure.CAN_AWUM = DISABLE; // automatic wake-up mode = DISABLED CAN_InitStructure.CAN_NART = DISABLE; // non-automatic retransmission mode = DISABLED CAN_InitStructure.CAN_RFLM = DISABLE; // receive FIFO locked mode = DISABLED CAN_InitStructure.CAN_TXFP = DISABLE; // transmit FIFO priority = DISABLED CAN_InitStructure.CAN_Mode = CAN_Mode_Silent; // normal CAN mode CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // synchronization jump width = 1 CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq; //14 CAN_InitStructure.CAN_BS2 = CAN_BS2_8tq; //6 CAN_InitStructure.CAN_Prescaler = 2; // baudrate 125kbps //CAN_InitStructure.CAN_Prescaler = 4; // baudrate 500 kbps CAN_Init(CAN2, &CAN_InitStructure); }int main(void)
{ /* Initialize Clocks */ RCC_Configuration(); /* Initialize GPIO */ GPIO_Configuration(); /* Initialize USART */ USART_Configuration(); /* Initialize CAN */ CAN_Configuration();2012-07-23 12:02 PM
This is where I actually get stuck (on the very beginning of the initialization):
/* Exit from sleep mode */
CANx->MCR &= (~(uint32_t)CAN_MCR_SLEEP);/* Request initialisation */
CANx->MCR |= CAN_MCR_INRQ ;/* Wait the acknowledge */
while (((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT)) { wait_ack++; }/* Check acknowledge */
if ((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) { InitStatus = CAN_InitStatus_Failed; } I never get that acknowledge ... could you tell me what am I doing wrong?2012-07-23 12:12 PM
/* CAN1 clock enable */
RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); /* CAN2 clock enable */ RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE); Surely APB1 not AHB1 RCC_APB1PeriphClockCmd()2012-07-23 12:26 PM
Yeah, figured it out a minute after posting, but thanks anyway! :D
CAN does get initialized now, I am resuming my work to the next problem. =)2012-07-23 12:31 PM
To the original poster:
Your problem might be here: /* 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); The speed of APB1 is 42MHz, not 30MHz ...2012-07-23 12:41 PM
The speed of APB1 is 42MHz, not 30MHz ...
That would depend on how the clock tree has been set up previously. 42 MHz would be the usual setting for most F4 designs, 30 MHz for F2 designs.2012-07-23 12:59 PM
Could you explain the ''clock tree''? By reading reference manual of STM32F407VG, I can see that clock speed of APB1 is 42MHz. Do you mean F2 processors have APB1 with clock speed 30MHz?
To the original poster: Check what happens when your program gets at the end of the CAN initialization, here:/* Request leave initialisation */
CANx->MCR &= ~(uint32_t)CAN_MCR_INRQ;/* Wait the acknowledge */
wait_ack = 0;while (((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT))
{ wait_ack++; }/* ...and check acknowledged */
if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) { InitStatus = CAN_InitStatus_Failed; } else { InitStatus = CAN_InitStatus_Success ; } }/* At this step, return the status of initialization */
return InitStatus; If I unplug the CAN transciever from STM32F4Discovery board, I don't get the acknowledge and returned InitStatus is CAN_InitStatus_Failed ... on the other hand, if I connect the CAN transciever, I get the acknowledgement immediately (and later CAN_InitStatus_Success).2012-07-23 01:57 PM
Could you explain the ''clock tree''? By reading reference manual of STM32F407VG, I can see that clock speed of APB1 is 42MHz. Do you mean F2 processors have APB1 with clock speed 30MHz?
I get to pick the speed the processor runs, the PLL and clock divider registers for the APB and AHB buses. If I ran the F4 at 120, 60 or 30 MHz I could easily run the APB at 30 MHz. The 42 MHz you mention is the maximum rated speed, and not an absolute setting. The quoted maximum for the F2 is 30 MHz, assuming a Div4 setting, its practical limit is probably closer to the F4 on the same process, but you don't have a Div3 setting for the APB. For the F1 the slower APB was rated at 36 MHz. Why would I clock below 168 MHz? So that it consumes significantly less power. Clock Tree, Figure 9, RM0090, Page 85 Generally the safest method is to read the current settings RCC_ClocksTypeDef RCC_Clocks; RCC_GetClocksFreq(&RCC_Clocks); printf(''SYS:%d H:%d, P1:%d, P2:%d\r\n'', RCC_Clocks.SYSCLK_Frequency, RCC_Clocks.HCLK_Frequency, // AHB RCC_Clocks.PCLK1_Frequency, // APB1 RCC_Clocks.PCLK2_Frequency); // APB2
2012-07-28 12:59 PM
Hi,
I have similar problem with initialization, using basically the same code. What is different that my CAN_RX, CAN_TX pins are not connected to CAN transmitter, but I use silent&loopback mode instead. I mentioned that in your case CAN_Init works properly if your CAN_TX,CAN_RX are connected to transmitter and fails if they are disconnected. Have you tried silent&loopback mode and CAN_RX,TX disconnected? Jiri