AnsweredAssumed Answered

STM32F04 CAN init

Question asked by blesener.daniel on Apr 9, 2015
Latest reply on Apr 11, 2015 by blesener.daniel
Below is my code. I've looked thru it many many time and it looks perfect for my initial testing. I had the code working for transmit (only in regards to seeing on a scope). Now it is not working and I have no clue why. Does anyone see any problems? I am just trying to transmit every 100ms and see on a scope. The code works in loop back mode. But not in normal. It sends something the first time thru the send sequence and then stops?

I am trying to get a send/receive working with a USBCAN COM module from gridconnect.

  CAN_DeInit(CAN);


  //Allow operation during debugging - pg 822 of ref manual. Not sure why we would ever want to freeze CAN in debug mode.
  CAN_DBGFreeze(CAN, DISABLE);


    /* CAN Periph clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN, ENABLE);   //12MHz to CAN clock


  //Enable GPIO clock 
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);


  //structues for initialization
  GPIO_InitTypeDef       GPIO_InitStructure;
  NVIC_InitTypeDef       NVIC_InitStructure;
  CAN_InitTypeDef        CAN_InitStructure;
  CAN_FilterInitTypeDef  CAN_FilterInitStructure;


  //Connect CAN pins to AF4 as shown by datasheet pg. 38
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_4);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_4); 
  
  //Configure CAN RX and TX pins 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
  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);


  //NVIC configuration 
  NVIC_InitStructure.NVIC_IRQChannel = CEC_CAN_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);


  //Enter CAN init mode. See ref manual page 972 & 818.
  CAN->MCR |= CAN_MCR_INRQ;
  
  //Wait for init. See ref manual page 972 & 818.
  while ((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) 
  {
  //TODO: ADD TIMEOUT
  }


  //CAN cell init 
  //Time triggered communication mode. 
  //In this mode, the internal counter of the CAN hardware is activated and used to generate the
  //Time Stamp value stored in the CAN_RDTxR/CAN_TDTxR registers, respectively (for Rx
  //and Tx mailboxes). The internal counter is incremented each CAN bit time
  //See pg. 824 of ref manual.
  CAN_InitStructure.CAN_TTCM = DISABLE;
  //Automatic bus-off management.
  //If ABOM is set, the bxCAN will start the recovering sequence automatically after it has
  //entered Bus-Off state.
  //If ABOM is cleared, the software must initiate the recovering sequence by requesting
  //bxCAN to enter and to leave initialization mode.
  //See pg. 831 of ref manual.
  CAN_InitStructure.CAN_ABOM = DISABLE;
  //Automatic Wake Up Mode. 
  //Automatically wake of from sleep mode - we don't use sleep mode so not needed.
  CAN_InitStructure.CAN_AWUM = DISABLE;
  //No Automatic ReTransmission. If enabled, transmission attempt will only occur once. If transmission fails, No Automatic ReTransmission will occur
  CAN_InitStructure.CAN_NART = DISABLE;
  //If disabled we will always see latest message. If enabled we miss messages to hold FIFO until a read occurs - pg 825 ref manual
  CAN_InitStructure.CAN_RFLM = DISABLE;
  //Receive FIFO locked mode. In this mode (if enabled) the priority order is given by the transmit request order - pg 823 ref manual
  CAN_InitStructure.CAN_TXFP = ENABLE;
  //Normal mode must be used unless testing. We will not use sleep mode for low power.
  CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;//CAN_Mode_LoopBack;//CAN_Mode_Normal;
  //The resynchronization Jump Width (SJW) defines an upper bound to the amount of
  //lengthening or shortening of the bit segments. It is programmable between 1 and 4 time
  //quanta. Must be <= BS2. See page 831 ref manual.
  CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;  
  //TODO: Change structure to match SFP network. Protocol below made for use with gridconnect CANUSB module.
  //See figure 317 in reference manual for baudrate calculations (baudrate = 1 PCLK clock cycle *(1 + BS1 + BS2))
  //tq = (BRP[9:0]+1) x tPCLK = (299 + 1) * 1/12MHz = 25us
  //Nominal bit time = tq * (1 + BS1 + BS2) = 25us
  //BS1 = (time)BS1 = tq * (TS1[3:0] + 1) ----> Note that TS1 is just register for BS1 - so use CAN_BS1 value. Same process for BS2 time. 
  //Baud rate = 1 / (nominal bit time) = 
  //CAN Baudrate = 10KHz 
  CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;      //Defines location of sample point 
  CAN_InitStructure.CAN_BS2 = CAN_BS2_1tq;      //Defines location of transmit point
  CAN_InitStructure.CAN_Prescaler = 299;        //This is BRP reg - can be between 1 and 1024...BRP = what is in reg + 1 (1 starts at 0)
  //Init CAN
  CAN_Init(CAN, &CAN_InitStructure);  


  //Leave CAN init mode. See ref manual page 972 & 818.
  CAN->MCR &=~ CAN_MCR_INRQ;
  
  //Wait until we have left init mode. See ref manual page 972 & 818.
  while ((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) 
  {
   //TODO: ADD TIMEOUT
  }


  //Enter filter init mode. See ref manual page 972 & 818.
  CAN->FMR |= CAN_FMR_FINIT;


  //Which filter will be initialized? Ranges from 0-13.
  CAN_FilterInitStructure.CAN_FilterNumber = 0;
  CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
  CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
  //TODO - MAKE FILTER ACTIVE???
  CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0;
  CAN_FilterInitStructure.CAN_FilterActivation = DISABLE;
  CAN_FilterInit(&CAN_FilterInitStructure);


  //Leave filter init. See ref manual page 972 & 818.
  CAN->FMR &=~ CAN_FMR_FINIT;
  
  //Transmit Structure preparation 
  TxMessage.StdId = 0x2;//0x321;
  TxMessage.ExtId = 0x2;//0x321;
  //Only two options, remote frame or data frame.
  //Data frame simply sends data. 
  //Any node may request data from one source node. A remote frame is consequently followed by a 
  //data frame containing the requested data
  TxMessage.RTR = CAN_RTR_DATA;//CAN_RTR_Remote;
  //STD or EXT option - just the length of the unique identifier to select node reception for tx (STD --> 11bits EXT --> 29 bits)
  TxMessage.IDE = CAN_ID_STD;
  TxMessage.DLC = 8;
  TxMessage.Data[0] = 0x81;
  TxMessage.Data[1] = 0x81;
  TxMessage.Data[2] = 0x81;
  TxMessage.Data[3] = 0x81;
  TxMessage.Data[4] = 0x81;
  TxMessage.Data[5] = 0x81;
  TxMessage.Data[6] = 0x81;
  TxMessage.Data[7] = 0x81;
  
  /* Enable FIFO 0 message pending Interrupt */
  CAN_ITConfig(CAN, CAN_IT_FMP0, ENABLE);
  
  /* Enable FIFO 0 full Interrupt */
  CAN_ITConfig(CAN, CAN_IT_FF0, ENABLE);
  
  /* Enable FIFO 1 full Interrupt */
  CAN_ITConfig(CAN, CAN_IT_FF1, ENABLE);


/////////////////////////////////////////////////////////////////////////////
In my main loop I have this in a 100ms poll
    if(CAN_test)
        {
        //CAN_test = !CAN_test;
        can_tx_retVal = CAN_Transmit(CAN,&TxMessage);
        if(can_tx_retVal == CAN_TxStatus_NoMailBox){
            CAN_CancelTransmit(CAN,0);
            CAN_CancelTransmit(CAN,1);
            CAN_CancelTransmit(CAN,2);
            }
        }

Outcomes