2010-09-14 12:57 PM
CAN Configuration for STM32
2011-05-17 05:06 AM
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;
}
2011-05-17 05:06 AM
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 Matthias2011-05-17 05:06 AM
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;
}
}
}
2011-05-17 05:07 AM
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.2011-05-17 05:07 AM
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.