cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 DISCOVERY CAN bus controller problem

keyboqian
Associate
Posted on July 13, 2012 at 15:57

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!

Keybo
36 REPLIES 36
jurij
Associate II
Posted on July 23, 2012 at 20:55

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();

jurij
Associate II
Posted on July 23, 2012 at 21:02

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?

Posted on July 23, 2012 at 21:12

/* CAN1 clock enable */

 RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

 /* CAN2 clock enable */

 RCC_AHB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);

Surely APB1 not AHB1

 RCC_APB1PeriphClockCmd()
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jurij
Associate II
Posted on July 23, 2012 at 21:26

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. =)

jurij
Associate II
Posted on July 23, 2012 at 21:31

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 ...

Posted on July 23, 2012 at 21:41

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jurij
Associate II
Posted on July 23, 2012 at 21:59

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).

Posted on July 23, 2012 at 22:57

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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jiri239955
Associate
Posted on July 28, 2012 at 21:59

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