AnsweredAssumed Answered

STM32F407VG Can Bus Communiation without a transceiver

Question asked by fonteles_albuquerque on Dec 3, 2015
Latest reply on Dec 3, 2015 by Clive One
Hello there,

I'm trying to implement a simple chat application between two Discovery Board STM32F407VG, communicating through Can Bus. 

Firstly, I'm trying to do it without a transceiver,  only using the Can Controller and diodes as I saw at this link:

http://www.christoph-lauer.de/archives/11833

I built this circuit and tried to send one character through CAN1 to CAN2 at the same Discovery Board, but it does not work. It seems that the transmission is not working properly and I have no idea what to do. 

I already used the oscilloscope to check the signal at the TX and RX port of Can controller, and I can see some pulses, it seems to be a CAN frame, even though it looks a bit shorter than I thought it should be.

The code I'm running is bellow:

#include "stm32f4xx_can.h"
#include "stm32f4xx_usart.h"
#include "misc.h"


#include "stm32f4xx_conf.h"
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_exti.h"
#include "usbd_cdc_core.h"
#include "usbd_usr.h"
#include "usbd_desc.h"
#include "usbd_cdc_vcp.h"
#include "usb_dcd_int.h"




/* Private variables ---------------------------------------------------------*/
CAN_InitTypeDef        CAN_InitStructure;
CAN_FilterInitTypeDef  CAN_FilterInitStructure;
CanTxMsg TxMessage;
CanRxMsg RxMessage;




uint32_t i = 0;
uint8_t TransmitMailbox = 0;




/* Private function prototypes -----------------------------------------------*/
void NVIC_Config(void);
void CAN_Config(void);
void Init_RxMes(CanRxMsg *RxMessage);
void USART2_Config(void);
void USART2_SendData_s(const unsigned char *pucBuffer);
void NVIC_Config_USART2(void);




volatile uint32_t ticker, downTicker;


/*
 * The USB data must be 4 byte aligned if DMA is enabled. This macro handles
 * the alignment, if necessary (it's actually magic, but don't tell anyone).
 */
__ALIGN_BEGIN USB_OTG_CORE_HANDLE  USB_OTG_dev __ALIGN_END;




void init();

/*
 * Define prototypes for interrupt handlers here. The conditional "extern"
 * ensures the weak declarations from startup_stm32f4xx.c are overridden.
 */
#ifdef __cplusplus
 extern "C" {
#endif


void SysTick_Handler(void);
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void OTG_FS_IRQHandler(void);
void OTG_FS_WKUP_IRQHandler(void);


int main(void)
{
     //USART2_Config();
     //USART2_SendData_s("Program Begins\n\r");




     /* NVIC configuration */


     SystemInit();
     NVIC_Config();




     //NVIC_Config_USART2();


     /* Initialize USB, IO, SysTick, and all those other things you do in the morning */
     init();




     /* CANs configuration */
     CAN_Config();




     /* IT Configuration for CAN1 */
     CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);




     /* IT Configuration for CAN2 */
     CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);


    /* Transmit Structure preparation */
    TxMessage.StdId = 0x321;
    TxMessage.ExtId = 0x01;
    TxMessage.RTR = CAN_RTR_DATA;
    TxMessage.IDE = CAN_ID_STD;
    TxMessage.DLC = 1;


     while (1)
     {
          /* If there's data on the virtual serial port:
           *  - Echo it back
           *  - Turn the green LED on for 10ms
           */
          uint8_t theByte;
          if (VCP_get_char(&theByte))
          {
               VCP_put_char(theByte);


               TxMessage.Data[0] = 0x55;
               if(CAN_Transmit(CAN1, &TxMessage)){
               }
               else{
                    VCP_send_str("TX FAILED");
               }


               CAN_TransmitStatus(CAN1,TransmitMailbox);
               i = 0;


               while((CAN_TransmitStatus(CAN1, TransmitMailbox)  !=  CANTXOK) && (i  !=  0xFFFF))
               {
                    i++;
               }


               if (CAN_MessagePending(CAN2, CAN_FIFO0))
               {
                    CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);
                    VCP_send_str("Receive");
               }




          }


     }
}




void init()
{
     /* STM32F4 discovery LEDs */
     GPIO_InitTypeDef LED_Config;


     /* Always remember to turn on the peripheral clock...  If not, you may be up till 3am debugging... */
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
     LED_Config.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
     LED_Config.GPIO_Mode = GPIO_Mode_OUT;
     LED_Config.GPIO_OType = GPIO_OType_PP;
     LED_Config.GPIO_Speed = GPIO_Speed_25MHz;
     LED_Config.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_Init(GPIOD, &LED_Config);


     /* Setup SysTick or CROD! */
     if (SysTick_Config(SystemCoreClock / 1000))
     {
          ColorfulRingOfDeath();
     }


     /* Setup USB */
     USBD_Init(&USB_OTG_dev,
                 USB_OTG_FS_CORE_ID,
                 &USR_desc,
                 &USBD_CDC_cb,
                 &USR_cb);


     return;
}


/*
 * Call this to indicate a failure.  Blinks the STM32F4 discovery LEDs
 * in sequence.  At 168Mhz, the blinking will be very fast - about 5 Hz.
 * Keep that in mind when debugging, knowing the clock speed might help
 * with debugging.
 */


void ColorfulRingOfDeath(void)
{
     uint16_t ring = 1;
     while (1)
     {
          uint32_t count = 0;
          while (count++ < 500000);


          GPIOD->BSRRH = (ring << 12);
          ring = ring << 1;
          if (ring >= 1<<4)
          {
               ring = 1;
          }
          GPIOD->BSRRL = (ring << 12);
     }
}


/*
 * Interrupt Handlers
 */


void SysTick_Handler(void)
{
     ticker++;
     if (downTicker > 0)
     {
          downTicker--;
     }
}




void NMI_Handler(void)       {}
void HardFault_Handler(void) { ColorfulRingOfDeath(); }
void MemManage_Handler(void) { ColorfulRingOfDeath(); }
void BusFault_Handler(void)  { ColorfulRingOfDeath(); }
void UsageFault_Handler(void){ ColorfulRingOfDeath(); }
void SVC_Handler(void)       {}
void DebugMon_Handler(void)  {}
void PendSV_Handler(void)    {}


void OTG_FS_IRQHandler(void)
{
  USBD_OTG_ISR_Handler (&USB_OTG_dev);
}


void OTG_FS_WKUP_IRQHandler(void)
{
  if(USB_OTG_dev.cfg.low_power)
  {
    *(uint32_t *)(0xE000ED10) &= 0xFFFFFFF9 ;
    SystemInit();
    USB_OTG_UngateClock(&USB_OTG_dev);
  }
  EXTI_ClearITPendingBit(EXTI_Line18);
}


/**
  * @brief  Configures CAN1 and CAN2.
  * @param  None
  * @retval None
  */
void CAN_Config(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;




  /* Configure CAN1 and CAN2 IOs **********************************************/
  /* GPIOB clock enable */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  /* GPIOD clock enable */
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


  /* Configure CAN1 RX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);




  /* Configure CAN2 RX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOB, &GPIO_InitStructure);




  /* Configure CAN1 TX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;




  GPIO_Init(GPIOD, &GPIO_InitStructure);




  /* Configure CAN2 TX pin */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOB, &GPIO_InitStructure);




  /* Connect CAN_RX & CAN_TX to AF9 */
       GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1); //CAN1_RX = PD0
       GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); //CAN1_TX = PD1




      /* Connect CAN_RX & CAN_TX to AF9 */
       GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2); //CAN2_RX = PB5
       GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_CAN2); //CAN2_TX = PB6




  /* Configure CAN1 and CAN2 **************************************************/
       /* CAN1 & 2  Periph clock enable */
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);




   /* CAN1 and CAN2 register init */
  CAN_DeInit(CAN1);
  CAN_DeInit(CAN2);




  /* Struct init*/
  CAN_StructInit(&CAN_InitStructure);




  /* CAN1 and CAN2  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 = ENABLE;
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
  CAN_InitStructure.CAN_BS1 = CAN_BS1_6tq;
  CAN_InitStructure.CAN_BS2 = CAN_BS2_7tq;
  CAN_InitStructure.CAN_Prescaler = 3;




  /*Initializes the CAN1  and CAN2 */
 CAN_Init(CAN1, &CAN_InitStructure);
 CAN_Init(CAN2, &CAN_InitStructure);




  /* CAN1 filter init */
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_16bit;
  CAN_FilterInitStructure.CAN_FilterIdHigh =((0x123)<<5);           // 0x123
  CAN_FilterInitStructure.CAN_FilterIdLow = ((0x124)<<5);           // 0x124
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = ((0x7)<<5);        // 0x125
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((0x7)<<5);         // 0x126
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
  CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;


  CAN_FilterInit(&CAN_FilterInitStructure);




  /* CAN2 filter init */
  CAN_FilterInitStructure.CAN_FilterIdHigh = ((0x125)<<5);      // 0x125
  CAN_FilterInitStructure.CAN_FilterIdLow = ((0x126)<<5);       // 0x126
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh =((0x3)<<5);
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((0x3)<<5);
  CAN_FilterInitStructure.CAN_FilterNumber = 14;
  CAN_FilterInit(&CAN_FilterInitStructure);




  /* Transmit */
  TxMessage.StdId = 0x007;
  TxMessage.ExtId = 0x01;
  TxMessage.RTR = CAN_RTR_DATA;
  TxMessage.IDE = CAN_ID_STD;
  TxMessage.DLC = 1;
}


/**
  * @brief  Initializes a Rx Message.
  * @param  CanRxMsg *RxMessage.
  * @retval None
  */
void Init_RxMes(CanRxMsg *RxMessage)
{
  uint8_t i = 0;




  RxMessage->StdId = 0;
  RxMessage->ExtId = 0;
  RxMessage->IDE = CAN_ID_STD;
  RxMessage->DLC = 0;
  RxMessage->FMI = 0;
  for (i = 0; i < 8; i++)
  {
    RxMessage->Data[i] = 0;
  }
}




/**
  * @brief  Configures the NVIC for CAN.
  * @param  None
  * @retval None
  */
void NVIC_Config(void)
{
  NVIC_InitTypeDef  NVIC_InitStructure;




  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);




  NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);




  NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x1;
  NVIC_Init(&NVIC_InitStructure);
}




/**
  * @brief  This function handles CAN1 RX0 Handler.
  * @param  None
  * @retval None
  */
void CAN1_RX0_IRQHandler(void)
{
  VCP_send_str("CAN1 RX0 IRQ!");


  CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);




  if ((RxMessage.StdId == 0x321)&&(RxMessage.IDE == CAN_ID_STD)&&(RxMessage.DLC == 1)&&(RxMessage.Data[0] == 0xAA))
  {
       //USART2_SendData_s("CAN 1 IRQ OK\n\r");/* OK */
       VCP_send_str("CAN 1 IRQ OK\n\r");
  }
  else
  {
       //USART2_SendData_s("CAN 1 IRQ Error\n\r");/* Error */
       VCP_send_str("CAN 1 IRQ Error\n\r");
  }
}




/**
  * @brief  This function handles CAN2 RX0 Handler.
  * @param  None
  * @retval None
  */




void CAN2_RX0_IRQHandler(void)
{
  VCP_send_str("CAN2 RX0 IRQ!");


  CAN_Receive(CAN2, CAN_FIFO0, &RxMessage);




  if ((RxMessage.StdId == 0x321)&&(RxMessage.IDE == CAN_ID_STD)&&(RxMessage.DLC == 1)&&(RxMessage.Data[0] == 0x55))
  {
       //USART2_SendData_s("CAN 2 IRQ OK\n\r");/* OK */
       VCP_send_str("CAN 2 IRQ OK\n\r");
  }
  else
  {
       //USART2_SendData_s("CAN 2 IRQ Error\n\r");/* Error */
       VCP_send_str("CAN 2 IRQ Error\n\r");
  }
}




//////////////////////////////////////




//void USART2_Config(void)
//{
//
//
//     GPIO_InitTypeDef GPIO_InitStructure;
//     USART_InitTypeDef USART_InitStructure;
//
//
//     /* enable peripheral clock for USART2 */
//     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
//
//
//     /* GPIOA clock enable */
//     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//
//
//     /* GPIOA Configuration:  USART2 TX on PA2 */
//     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
//     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(GPIOA, &GPIO_InitStructure);
//
//
//     /* Configure USART Rx as alternate function  */
//       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
//       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
//       GPIO_Init(GPIOA, &GPIO_InitStructure);
//
//
//     /* Connect USART2 pins to AF2 */
//     // TX = PA2
//     GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
//     // RX = PA3
//     GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2);
//
//
//     USART_InitStructure.USART_BaudRate = 9600;
//     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(USART2, &USART_InitStructure);
//
//
//      /* Enable USART2 Receive interrupts */
//     USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
//
//
//      USART_Cmd(USART2, ENABLE); // enable USART2
//
//
//}
//////////////////////////////////////////
//void USART2_SendData_s(const unsigned char *pucBuffer)
//{
//    // Loop while there are more characters to send.
//    while(*pucBuffer)
//    {
//        USART_SendData(USART2, (uint16_t) *pucBuffer++);
//        /* Loop until the end of transmission */
//        while(USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)
//        {
//        }
//    }
//}
///////////////////////////////////////////////////////////////////////
/*
 * NVIC initialization function
 */
void NVIC_Config_USART2(void)
 {
     NVIC_InitTypeDef NVIC_InitStructure;
  /* Enable the USARTx Interrupt */
   NVIC_InitStructure.NVIC_IRQChannel =USART2_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
 }


I would appreciate any help :)
Thank you.





Outcomes