cancel
Showing results for 
Search instead for 
Did you mean: 

CAN Bus strange signal (solved)

Tom Schrauf
Associate II

edit: the problem was due to a CAN-master switching baudrates on the fly.

the wrong (slower) timing was detected by the CAN controller causing the interruption of the ongoing transmission.

Hello Community !

I am implementing CAN communication with an inverter and sometimes experience communication failures. The inverter is the only one sharing the bus.

The interface is setup @500kBaud, STM32F407 (revision 2) 100pins, CAN1 (A11,A12) and works fine except getting this strange behavior sometimes, which I can't understand.

I use interrupt driven Receive and cmsis CanTransmit fct.

SCE ISR just clears errors:

   CAN1->ESR = (uint32_t)RESET;

   CAN1->MSR = CAN_MSR_ERRI;

From that point on the inverter transmits corrupted frames for about 10s until it sort of recovers.

My CAN-Init:

   CAN_InitStructure.CAN_TTCM = DISABLE;

   CAN_InitStructure.CAN_ABOM = DISABLE;

   CAN_InitStructure.CAN_AWUM = DISABLE;

   CAN_InitStructure.CAN_NART = ENABLE;

   CAN_InitStructure.CAN_RFLM = ENABLE;

   CAN_InitStructure.CAN_TXFP = ENABLE;

   CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;

   CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;

I am a bit new to CAN-Bus so the solution might be very trivial.

I do not understand why the TX-Line is being activated interfering the ongoing transmission with a well shaped pattern.

What did I do wrong and how can the CAN TX line be activated without sending or receiving ? Is this part of the BUS arbitration and what is the condition that forces the CAN controller to behave like that (all queues empty).

Thank you for reading all this !

Tom

0693W00000HpeihQAB.png

22 REPLIES 22

static pinConfiguration pinsUsed[] = {

   { GPIOA, { GPIO_Pin_11, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL } } // CAN1 RX

   ,{ GPIOA, { GPIO_Pin_12, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } }  // CAN1 TX

//   ,{ GPIOB, { GPIO_Pin_5, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL } } // CAN2 RX

//   ,{ GPIOB, { GPIO_Pin_6, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } }  // CAN2 TX

   ,{ GPIOB, { GPIO_Pin_5, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } } // CAN2 RX

   ,{ GPIOB, { GPIO_Pin_6, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } }  // CAN2 TX

};

using B5 and B6 as debug pins (see the diagrams)

static pinAFConfig pinsAF[] = {

   { GPIOA, GPIO_PinSource11, GPIO_AF_CAN1 }

   ,{ GPIOA, GPIO_PinSource12, GPIO_AF_CAN1 }

//   ,{ GPIOB, GPIO_PinSource5, GPIO_AF_CAN2 }

//   ,{ GPIOB, GPIO_PinSource6, GPIO_AF_CAN2 }

};

unsigned char init_can( CAN_TypeDef* CANx, CAN_BAUDRATE speed )

{

int i;

   CAN_InitTypeDef       CAN_InitStructure;

   CAN_FilterInitTypeDef CAN_FilterInitStructure;

   if (CANx == CAN1) {

      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

      RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

   }

   else {

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);

   }

   for(i=0;i<sizeof pinsUsed / sizeof pinsUsed[0];++i) {

    GPIO_Init( pinsUsed[i].GPIOx, &pinsUsed[i].p );

   }

   for(i=0;i<sizeof pinsAF / sizeof pinsAF[0];++i) {

    GPIO_PinAFConfig( pinsAF[i].GPIOx, pinsAF[i].GPIO_PinSource, pinsAF[i].GPIO_AF );

   }

   /* CAN register init */

   CAN_DeInit(CANx);

   /* CAN cell init */

   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 = ENABLE; // non-automatic retransmission mode = DISABLED

   CAN_InitStructure.CAN_RFLM = ENABLE; // receive FIFO locked mode = DISABLED

   CAN_InitStructure.CAN_TXFP = ENABLE; // transmit FIFO priority = DISABLED

   CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; // CAN_Mode_LoopBack;

   CAN_InitStructure.CAN_SJW = CAN_SJW_1tq; // synchronization jump width = 1

   /* CAN clocked at 42MHz */

   // see RM0090 note

   // 336 clk = CAN_Prescaler * (1 + CAN_BS1 + CAN_BS2)

   // PCLK = 42MHz

   // http://www.bittiming.can-wiki.info/

   switch( speed ) {

   case CAN_BAUDRATE_125K:

      CAN_InitStructure.CAN_Prescaler = 21;

      CAN_InitStructure.CAN_BS1 = CAN_BS1_13tq;

      CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;

      break;

   case CAN_BAUDRATE_250K:

      CAN_InitStructure.CAN_Prescaler = 12;

      CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;

      CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;

      break;

   case CAN_BAUDRATE_500K:

      CAN_InitStructure.CAN_Prescaler = 6;

      CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;

      CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;

      break;

   case CAN_BAUDRATE_1M:

      CAN_InitStructure.CAN_Prescaler = 3;

      CAN_InitStructure.CAN_BS1 = CAN_BS1_11tq;

      CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;

      break;

   }

   // full speed

   if (RCC_Clocks.PCLK1_Frequency == 42000000) ;

   // 1/2 speed

   if (RCC_Clocks.PCLK1_Frequency == 21000000)

      CAN_InitStructure.CAN_Prescaler *= 2;

   // 1/4 speed

   if (RCC_Clocks.PCLK1_Frequency == 10500000)

      CAN_InitStructure.CAN_Prescaler *= 4;

   CAN_Init(CANx, &CAN_InitStructure);

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

   CAN_ITConfig( CANx, CAN_IT_FMP0 | CAN_IT_FMP1 | CAN_IT_FOV0 | CAN_IT_FOV1 | CAN_IT_EWG | CAN_IT_ERR, ENABLE );

   if (CANx == CAN1) {

      NVIC_EnableIRQ( CAN1_RX0_IRQn );

      NVIC_SetPriority( CAN1_RX0_IRQn, 0 );

      NVIC_SetPriority( CAN1_TX_IRQn, 0 );

//      NVIC_EnableIRQ( CAN1_RX1_IRQn );

      NVIC_EnableIRQ( CAN1_SCE_IRQn );

   }

   else {

      NVIC_EnableIRQ( CAN2_RX0_IRQn );

      NVIC_SetPriority( CAN2_RX0_IRQn, 0 );

      NVIC_SetPriority( CAN2_TX_IRQn, 0 );

//      NVIC_EnableIRQ( CAN2_RX1_IRQn );

      NVIC_EnableIRQ( CAN2_SCE_IRQn );

   }

   CAN_WakeUp( CANx );

   return 1;

}

As you can see i am using cmsis functions only. I set INT priority to highest by purpose not have delays caused by TIM5 or systic interrupts.

This problematic sequence only occurs once and can be reproduced. The ONLY time (even for hours) the SCE interrupt occurs is at this event.

My oscilloscope is a 40 years old analog 35mHz type without memory function - this won't help i guess.

But you see in the detailed diagram that the boinks are well aligned before the "problematic sequence" and communication resumes after the re-transmission stopped.

I will have a try with CAN2 as this can be done easily

Thank you for trying to help !!!!!!!!

But the frame has just begun when the "boinks" are interfering transmission. An ACK signal is 2uS long but these 8 boinks are 12uS and ALWAYS 8 successive ! And how can the CAN controller detect a frame error when it does not even allow transmission of the frame and interferes 12 uSecs after dominate signal ?

0693W00000HpkK2QAJ.jpg

Could you please tell us why you're configuring CAN1_Rx pin (PA11) in Open drain?

 { GPIOA, { GPIO_Pin_11, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL } } // CAN1 RX

Please replace GPIO_OType_OD by GPIO_OType_PP.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Hmm, this worked well with USART and SPI if i remember correctly.

I changed to CAN2 and the picture is the same but I will immediately check with PP if that makes sense.

0693W00000HpkR8QAJ.png

Changed to CAN2 (filter 14), PP with both Pull up and not.

Exactly the same waveform just on other pins.

static pinConfiguration pinsUsed[] = {

   { GPIOA, { GPIO_Pin_11, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } } // debug line

   ,{ GPIOA, { GPIO_Pin_12, GPIO_Mode_OUT, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_NOPULL } } // debug line

   ,{ GPIOB, { GPIO_Pin_5, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP } } // CAN2 RX

   ,{ GPIOB, { GPIO_Pin_6, GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP } }  // CAN2 TX

};

maybe should i try to switch on silent mode once a frame error was detected. But when to leave silent mode again ?

Maybe this helps the controller resync again ?

btw: this is when the situation recovers after hundreds of ignored frames the other side changes the frame and this is then accepted.

0693W00000HpkYxQAJ.jpgThe "big picture" so when the problem starts (see waveforms) anf how it recovers after ~15seconds.

0693W00000Hpka5QAB.jpg 

Tom Schrauf
Associate II

AND THANK YOU ALL FOR HELPING EVEN ON CHRISTMAS DAY.

NO MATTER I CAN SOLVE THE PROBLEM OR NOT I WISH YOU ALL A MERRY CHRISTMAS !!!!

Setting the SILM bit in the SCE ISR does not prevent the additional 2 boinks after the six before.

Seems I have to live with this and accept it as part of the startup sequence. I hope the CAN bus in vehicles uses different baudrates/frames and boinks :)

Kind of miraculous to me.

I think the open drain does not make a difference as the CAN chip uses Push pull output circuitry:

0693W00000Hpki4QAB.jpg