cancel
Showing results for 
Search instead for 
Did you mean: 

CAN Configuration for STM32

matthiasdoerr9
Associate II
Posted on September 14, 2010 at 21:57

CAN Configuration for STM32

5 REPLIES 5
ashley23
Associate II
Posted on May 17, 2011 at 14:06

I use this code and it works ine or receive and transmit...

uint8_t CAN1_Init(void)

{

    uint8_t retVal = CANINITFAILED;

   

    // Enable GPIOD and AFIO clock

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);

    // Enable CAN 1 Clock

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    CAN_DeInit(CAN1);

    

    GPIO_InitTypeDef GPIO_InitStructure;

    // Configure CAN Tx as push-pull

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOD, &GPIO_InitStructure); 

    // Configure CAN Rx as input floating

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

    GPIO_Init(GPIOD, &GPIO_InitStructure);

    // Remap CAN1 to PD0 and PD1

    AFIO->MAPR &= ~(AFIO_MAPR_CAN_REMAP);    

    AFIO->MAPR |= AFIO_MAPR_CAN_REMAP_REMAP3;

     

    // Configure for 1MBit

    CAN_InitTypeDef ci;

    CAN_StructInit(&ci);

    ci.CAN_Prescaler = 4;

    ci.CAN_SJW = CAN_SJW_1tq;

    ci.CAN_BS1 = CAN_BS1_6tq;

    ci.CAN_BS2 = CAN_BS2_2tq;     

    ci.CAN_TXFP = ENABLE;

    

    retVal = CAN_Init(CAN1, &ci);

    

    // Enable filters as required:

    CAN_FilterInitTypeDef filterInit;

    filterInit.CAN_FilterNumber = 0;

    filterInit.CAN_FilterActivation = ENABLE;

    filterInit.CAN_FilterMode = CAN_FilterMode_IdMask;

    filterInit.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;

    filterInit.CAN_FilterIdHigh = 0;

    filterInit.CAN_FilterIdLow = 0;

    filterInit.CAN_FilterMaskIdHigh = 0;

    filterInit.CAN_FilterMaskIdLow = 0;

    filterInit.CAN_FilterScale = CAN_FilterScale_16bit;    

    CAN_FilterInit(&filterInit);

    

    if(retVal != CANINITFAILED)

    {

        // Peripheral interrupt enable

        CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);   

        CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); 

        CAN_ITConfig(CAN1, CAN_IT_FF0, ENABLE); 

        CAN_ITConfig(CAN1, CAN_IT_FOV0, ENABLE); 

        

        // Interrupt Controller config

        NVIC_InitTypeDef NVIC_InitStructure;   

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

        // Tx Interrupt channel

        NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure);

        // Rx0 Interrupt channel

        NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure);

    }

    

    return retVal;

}

matthiasdoerr9
Associate II
Posted on May 17, 2011 at 14:06

Thank you very much for your answer, but my application is still not working right. I think I have a problem with the Interrupts.

Can you please send me your whole application.

Best Regards

Matthias

ashley23
Associate II
Posted on May 17, 2011 at 14:06

My whole application is very complex.  Also it is company property so I can not send it.  I will add some examples for interrupt code too. Are you sure that your CAN bus is physically working.  I can tell you for certain that you can not use just one device and scope the pins.  You need another working CAN device on the bus.  Or, put your device in loopback mode.  My app was configured for 1MBit bus, is that the speed you are using?

1MBit CAN Init (comment in the loopback line if required):

uint8_t CAN1_Init(void)

{

    uint8_t retVal = CANINITFAILED;

   

    // Enable GPIOD and AFIO clock

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);

    // Enable CAN 1 Clock

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

    CAN_DeInit(CAN1);

    

    GPIO_InitTypeDef GPIO_InitStructure;

    // Configure CAN Tx as push-pull

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;

    GPIO_Init(GPIOD, &GPIO_InitStructure); 

    // Configure CAN Rx as input floating

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;

    GPIO_Init(GPIOD, &GPIO_InitStructure);

    // Remap CAN1 to PD0 and PD1

    AFIO->MAPR &= ~(AFIO_MAPR_CAN_REMAP);    

    AFIO->MAPR |= AFIO_MAPR_CAN_REMAP_REMAP3;

     

    // Configure for 1MBit

    CAN_InitTypeDef ci;

    CAN_StructInit(&ci);

    //ci.CAN_Mode = CAN_Mode_LoopBack;

    ci.CAN_Prescaler = 4;

    ci.CAN_SJW = CAN_SJW_1tq;

    ci.CAN_BS1 = CAN_BS1_6tq;

    ci.CAN_BS2 = CAN_BS2_2tq;     

    ci.CAN_TXFP = ENABLE;

    

    retVal = CAN_Init(CAN1, &ci);

    

    // Enable filters as required:

    CAN_FilterInitTypeDef filterInit;

    filterInit.CAN_FilterNumber = 0;

    filterInit.CAN_FilterActivation = ENABLE;

    filterInit.CAN_FilterMode = CAN_FilterMode_IdMask;

    filterInit.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;

    filterInit.CAN_FilterIdHigh = 0;

    filterInit.CAN_FilterIdLow = 0;

    filterInit.CAN_FilterMaskIdHigh = 0;

    filterInit.CAN_FilterMaskIdLow = 0;

    filterInit.CAN_FilterScale = CAN_FilterScale_16bit;    

    CAN_FilterInit(&filterInit);

    

    if(retVal != CANINITFAILED)

    {

        // Peripheral interrupt enable

        //HW_SetCAN1RxInterrupts(ENABLE);           // Enable these later

        CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE);   // CAN1_TX - Transmit mailbox empty

        

        NVIC_InitTypeDef NVIC_InitStructure;   

        // Tx Interrupt channel

        NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = INT_CAN_TX_INT_GROUP;

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = INT_CAN_TX_SUB_PRI;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure);

        // Rx0 Interrupt channel

        NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;

        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = INT_CAN_RX0_INT_GROUP;

        NVIC_InitStructure.NVIC_IRQChannelSubPriority = INT_CAN_RX0_SUB_PRI;

        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

        NVIC_Init(&NVIC_InitStructure);

    }

    

    return retVal;

}

void HW_SetCAN1RxInterrupts(FunctionalState state)

{

    CAN_ITConfig(CAN1, CAN_IT_FMP0, state);  // CAN1_RX0 - Fifo 0 message pending

    CAN_ITConfig(CAN1, CAN_IT_FF0, state);   // CAN1_RX0 - Fifo 0 full

    CAN_ITConfig(CAN1, CAN_IT_FOV0, state);  // CAN1_RX0 - Fifo 0 overrun

}

Receive interrupt:

void USBTOCAN_CanRxISRHandler(void)

{

    if(CAN_MessagePending(CAN1, CAN_FIFO0) > 0)

    {

        // There is one or more messages in FIFO 0 

        

        CanRxMsg rxMessage;

        while(CAN_MessagePending(CAN1, CAN_FIFO0) > 0)

        {

            CAN_Receive(CAN1, CAN_FIFO0, &rxMessage);

            ... Do your stuff with the message here

            }

        }

    }

    else if(CAN_GetITStatus(CAN1, CAN_IT_FOV0))

    {

        // There has been a buffer overflow

        CAN_ClearITPendingBit(CAN1, CAN_IT_FOV0);

    }

    else if(CAN_GetITStatus(CAN1, CAN_IT_FF0))

    {

        // Buffers are all full

        CAN_ClearITPendingBit(CAN1, CAN_IT_FF0);

    } 

}

Transmit interrupt.  This is not used in my code, but I enabled it for some debugging I did.

void USBTOCAN_CanTxISRHandler(void)

{

    // Check if is a real interrupt.  Sometimes an interrupt occurs when the NVIC CAN1 interrupt is enabled even though all RQCPx bits are 0.  This happens after a debugger reset but not on first power up.

    if(CAN1->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2))

    {

        uint16_t sentID;

        if(CAN_GetITStatus(CAN1, CAN_IT_RQCP0))

        {

            CAN_ClearITPendingBit(CAN1, CAN_IT_RQCP0);

            sentID = CAN1->sTxMailBox[0].TIR >> 21;

        }

        else if(CAN_GetITStatus(CAN1, CAN_IT_RQCP1))

        {

            CAN_ClearITPendingBit(CAN1, CAN_IT_RQCP1);

            sentID = CAN1->sTxMailBox[1].TIR >> 21;

        }

        else if(CAN_GetITStatus(CAN1, CAN_IT_RQCP2))

        {

            CAN_ClearITPendingBit(CAN1, CAN_IT_RQCP2);

            sentID = CAN1->sTxMailBox[2].TIR >> 21;

        }

    }

}

matthiasdoerr9
Associate II
Posted on May 17, 2011 at 14:07

Thank you very much for your help. But my application is still not working right. The CAN-Controller is configured in Loopback-Mode, but there is no signal on the output pin. There is only one thing which I don't understand in your code. What are you doing with the sentID?

The speed is not really an issue at time.

aljaz
Associate II
Posted on May 17, 2011 at 14:07

The CAN-Controller is configured in Loopback-Mode, but there is no signal on the output pin.

Are you sure that Loopback mode toggles the hardware pins??

Double-check the Reference manual of this microcontroller. There are all modes listed together with effect on the pins.