0
\$\begingroup\$

I am trying to communicate my STM32F746ZG microcontroller with a MCP2515 and am having a problem where I don't believe the MCP2515 is receiving anything I have sent via SPI.

The reason I have come to this conclusion is because I have checked that my SPI code from the STM sends correctly through an oscilloscope (which it does), then following that check, I have tried to see if what I have written into the CNF1 register can be read back, which it doesn't (for example, if I set the CNF1 register to 00000100 or 0x04, the value that is read back is 0x00).

I was wondering if anyone has worked on a project like this and if they had any ideas on how I could fix this. (p.s. I am using HAL-Library)

mcp2515.c

/*
 * STM32F7xx_MCP2515.c
 * Library for Microchip MCP2515 CAN Controller
 *
 *  Created on: Jun 28, 2016
 *      Author: Nicholas Lloyd
 */

#include "MCP2515.h"
#include "stm32f7xx_hal.h"
#include "stm32f7xx_hal_gpio.h"
#include "stm32f7xx_hal_spi.h"
#include "stm32f7xx_hal_rcc.h"
#include "stm32f7xx_hal_rcc_ex.h"
#include "stm32f7xx_hal_flash_ex.h"
#include "stm32f7xx_it.h"
#include <stddef.h>

/*Private Define */
SPI_HandleTypeDef SPI_Structure;

// Constructor defining which pins to use for CS and INT

/* Global variables */
uint8_t SPI_BUFFER_TX1;
uint8_t SPI_BUFFER_TX2[2];
uint8_t SPI_BUFFER_TX3[3];
uint8_t SPI_BUFFER_TX4[4];
uint8_t SPI_BUFFER_RX2[2];
uint8_t SPI_BUFFER_RX3[3];
uint8_t SPI_NULL = 0x00;
uint8_t SPI_BLANK_RECEIVE[4];

void MCP2515_GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* GPIO Clock Enables */
    __HAL_RCC_GPIOD_CLK_ENABLE();
    /* Configuring Chip Select Pin */
    GPIO_InitStructure.Mode         = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull         = GPIO_PULLDOWN;
    GPIO_InitStructure.Speed        = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Pin          = SPI1_CS_PIN;
    HAL_GPIO_Init(SPI1_CS_PORT, &GPIO_InitStructure);
    /* Setting the chip select to high so data can not be sent */
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);

    /* SPI Clock Enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
    /* GPIO Clock Enables */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /* GeneralSPI GPIO Configuration */
    GPIO_InitStructure.Mode         = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Pull         = GPIO_NOPULL;
    GPIO_InitStructure.Speed        = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Alternate    = SPI1_AF;
    /* SPI SCK Pin Configuration */
    GPIO_InitStructure.Pin          = SPI1_SCK_PIN;
    HAL_GPIO_Init(SPI1_GPIO_PORT, &GPIO_InitStructure);
    /* SPI MISO Pin Configuration */
    GPIO_InitStructure.Pin          = SPI1_MISO_PIN;
    HAL_GPIO_Init(SPI1_GPIO_PORT, &GPIO_InitStructure);
    /* SPI MOSI Pin Configuration */
    GPIO_InitStructure.Pin          =  SPI1_MOSI_PIN;
    HAL_GPIO_Init(SPI1_GPIO_PORT, &GPIO_InitStructure);

    /* GPIO Clock Enables */
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /* Configuring LED1, LED2, LED3 */
    GPIO_InitStructure.Pin          = USER_LED_BLUE;
    GPIO_InitStructure.Mode         = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull         = GPIO_NOPULL;
    GPIO_InitStructure.Speed        = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(USER_LED_PORT, &GPIO_InitStructure);
    /* Check to see if LEDs run and if board functions */
    HAL_GPIO_WritePin(USER_LED_PORT, USER_LED_BLUE, GPIO_PIN_RESET);
}

void MCP2515_SPI_Configuration(void)
{
    /* The SPI Handle for Channel 1 */
    SPI_Structure.Instance = SPI1;
    /* DeInitializes SPI1 */
    HAL_SPI_DeInit(&SPI_Structure);
    /* Prevent unused argument(s) compilation warning */
    HAL_SPI_MspInit (&SPI_Structure);
    /* SPI configuration */
    SPI_Structure.Init.Mode = SPI_MODE_MASTER;
    SPI_Structure.Init.Direction = SPI_DIRECTION_2LINES;
    SPI_Structure.Init.DataSize = SPI_DATASIZE_8BIT;
    SPI_Structure.Init.CLKPolarity = SPI_POLARITY_LOW;
    SPI_Structure.Init.CLKPhase = SPI_PHASE_1EDGE;
    SPI_Structure.Init.NSS = SPI_NSS_SOFT;
    SPI_Structure.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
    SPI_Structure.Init.FirstBit = SPI_FIRSTBIT_MSB;
    //SPI_Structure.Init.TIMode = SPI_TIMODE_DISABLE;
    //SPI_Structure.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    SPI_Structure.Init.CRCPolynomial = 7;
    /* Error Loop Init */
    HAL_SPI_Init(&SPI_Structure);
    __HAL_RCC_SYSCFG_CLK_ENABLE();
    __HAL_SPI_ENABLE(&SPI_Structure);
}
/*
  Initialize MCP2515

  int CAN_Bus_Speed = transfer speed in kbps
  int Freq = MCP2515 oscillator frequency in MHz
  int SJW = Synchronization Jump Width Length bits - 1 to 4 (see data sheet)

  returns baud rate set

  Sending a bus speed of 0 kbps initiates AutoBaud and returns zero if no
  baud rate could be determined.  There must be two other active nodes on the bus!
*/
int MCP2515_Initialise(int baud, uint8_t Freq, uint8_t SJW) {
  if(SJW < 1) SJW = 1;
  if(SJW > 4) SJW = 4;
  if(baud > 0) {
    if(MCP2515_SubInitialise(baud, Freq, SJW, 0)) {
        return baud;
    }
  } else {
      int i=0;
      char interruptFlags = 0;
      for(i=5; i<1000; i=i+5) {
        if(MCP2515_SubInitialise(i, Freq, SJW, 1)) {
            // check for bus activity
            MCP2515_Single_Write(CANINTF,0);
            HAL_Delay(5); // need the bus to be communicating within this time frame
            if(MCP2515_Interrupt()) {
              // determine which interrupt flags have been set
              interruptFlags = MCP2515_Read(CANINTF);
              if(!(interruptFlags & MERRF)) {
                // to get here we must have received something without errors
                  MCP2515_Mode(MODE_NORMAL);
                  return i;
              }
            }
        }
      }
  }
  return 0;
}

int MCP2515_SubInitialise(int baud, uint8_t Freq, uint8_t SJW, uint8_t autoBaud) {

  // Reset MCP2515 which puts it in configuration mode
  MCP2515_Reset();

  // Calculate bit timing registers
  uint8_t BRP;
  float TQ;
  uint8_t BT;
  float tempBT;

  float NBT = 1.0 / (float)baud * 1000.0; // Nominal Bit Time us
  for(BRP=0;BRP<8;BRP++) {
    TQ = 2.0 * (float)(BRP + 1) / (float)Freq;
    tempBT = NBT / TQ;
      if(tempBT<=25) {
        BT = (int)tempBT;
        if(tempBT-BT==0) break;
      }
  }

  int SPT = (0.7 * BT); // Sample point
  uint8_t PRSEG = (SPT - 1) / 2;
  uint8_t PHSEG1 = SPT - PRSEG - 1;
  uint8_t PHSEG2 = BT - PHSEG1 - PRSEG - 1;

  // Programming requirements
  if(PRSEG + PHSEG1 < PHSEG2) return 0;
  if(PHSEG2 <= SJW) return 0;

  uint8_t BTLMODE = 1;
  uint8_t SAM = 0;

  // Set registers
  SJW = SJW - 1;
  SJW = SJW << 6;
  uint8_t CNF1_data = SJW;
  CNF1_data = CNF1_data | BRP;
  BTLMODE = BTLMODE << 7;
  uint8_t CNF2_data = BTLMODE;
  SAM = SAM << 6;
  CNF2_data = CNF2_data | SAM;
  PHSEG1 = PHSEG1 - 1;
  PHSEG1 = PHSEG1 << 3;
  CNF2_data = CNF2_data | PHSEG1;
  PRSEG = PRSEG - 1;
  CNF2_data = CNF2_data | PRSEG;
  uint8_t CNF3_data = 0x80;
  PHSEG2 = PHSEG2 - 1;
  CNF3_data = CNF3_data | PHSEG2;

  // Write to registers
  uint8_t correct_mode;
  correct_mode = MCP2515_Mode(MODE_CONFIG);
  if (correct_mode == 0) {
      while (1) {
      }
  }
  MCP2515_Single_Write(CNF1, CNF1_data);
  MCP2515_Single_Write(CNF2, CNF2_data);
  MCP2515_Single_Write(CNF3, CNF3_data);
  MCP2515_Single_Write(TXRTSCTRL,0);

  if(!autoBaud) {
    // Return to Normal mode
      if(!MCP2515_Mode(MODE_NORMAL)) return 0;
  } else {
    // Set to Listen Only mode
      if(!MCP2515_Mode(MODE_LISTEN)) return 0;
  }
  // Enable all interupts
  MCP2515_Single_Write(CANINTE,255);

  // Test that we can read back from the MCP2515 what we wrote to it
  uint8_t rtn = MCP2515_Read(CNF1);
  if (rtn==CNF1_data) {
      return 1;
  }
  else {
      return 0;
  }
}

void MCP2515_Reset(void)
{
    uint8_t check_status;
    SPI_BUFFER_TX1 = CAN_RESET_BASE;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    check_status = HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX1, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    if (check_status != HAL_OK) {
        while (1) {
        }
    }
}

uint8_t MCP2515_Read(uint8_t address) {
    uint8_t data = 0x00;
    uint8_t check_status;
    SPI_BUFFER_TX3[0] = CAN_READ_BASE;
    SPI_BUFFER_TX3[1] = address;
    SPI_BUFFER_TX3[2] = SPI_NULL;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    check_status = HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX3, &SPI_BUFFER_RX3, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    if (check_status != HAL_OK) {
        while (1) {
        }
    }
    data = SPI_BUFFER_RX3[2];
    return data;
}

void MCP2515_Read_Multiple(uint8_t address, uint8_t data[], uint8_t bytes) {
  // allows for sequential reading of registers starting at address - see data sheet
  HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
  SPI_BUFFER_TX3[0] = CAN_READ_BASE;
  SPI_BUFFER_TX3[1] = address;
  SPI_BUFFER_TX3[2] = SPI_NULL;
  HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX3, &data, SPI_MESSAGE_SIZE3,  SPI_TIMEOUT);
  HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
}

uint8_t MCP2515_ReadBuffer(uint8_t buffer) {
  uint8_t data = 0x00;

  uint8_t address = CAN_READ_BUFFER_BASE | (buffer<<1);
  SPI_BUFFER_TX2[0] = address;
  SPI_BUFFER_TX2[1] = SPI_NULL;
  HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
  HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX2, &data, SPI_MESSAGE_SIZE2, SPI_TIMEOUT);
  HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
  return data;
}

void MCP2515_Single_Write(uint8_t address, uint8_t data) {
    uint8_t check_status1;
//  uint8_t check_status2;
//  uint8_t check_status3;
    SPI_BUFFER_TX3[0] = CAN_WRITE_BASE;
    SPI_BUFFER_TX3[1] = address;
    SPI_BUFFER_TX3[2] = data;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    check_status1 = HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX3, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE3, SPI_TIMEOUT);
//  check_status1 = HAL_SPI_TransmitReceive(&SPI_Structure, CAN_WRITE, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
//  check_status2 = HAL_SPI_TransmitReceive(&SPI_Structure, &address, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
//  check_status3 = HAL_SPI_TransmitReceive(&SPI_Structure, &data, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    if (check_status1 != HAL_OK) {
        while (1) {
        }
    }
//  if (check_status2 != HAL_OK) {
//      while (1) {
//      }
//  }
//  if (check_status3 != HAL_OK) {
//      while (1) {
//      }
//  }
}

void MCP2515_SendBuffer(uint8_t buffers) {
  // buffers should be any combination of TXB0, TXB1, TXB2 ORed together, or TXB_ALL
    uint8_t address = CAN_RTS_BASE | buffers;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    HAL_SPI_TransmitReceive(&SPI_Structure, &address, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
}

void MCP2515_LoadBuffer(uint8_t buffer, uint8_t data) {
    uint8_t address = CAN_LOAD_BUFFER_BASE | buffer;
    SPI_BUFFER_TX2[0] = address;
    SPI_BUFFER_TX2[1] = data;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX2, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE2, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
}

uint8_t MCP2515_Status() {
    uint8_t data = 0x00;
    SPI_BUFFER_TX3[0] = CAN_STATUS_BASE;
    SPI_BUFFER_TX3[1] = SPI_NULL;
    SPI_BUFFER_TX3[2] = SPI_NULL;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    HAL_SPI_TransmitReceive(&SPI_Structure, CAN_STATUS, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_NULL, &data, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_NULL, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    return data;
  /*
  bit 7 - CANINTF.TX2IF
  bit 6 - TXB2CNTRL.TXREQ
  bit 5 - CANINTF.TX1IF
  bit 4 - TXB1CNTRL.TXREQ
  bit 3 - CANINTF.TX0IF
  bit 2 - TXB0CNTRL.TXREQ
  bit 1 - CANINTFL.RX1IF
  bit 0 - CANINTF.RX0IF
  */
}

uint8_t MCP2515_RXStatus() {
    uint8_t data = 0x00;
    SPI_BUFFER_TX3[0] = CAN_RX_STATUS_BASE;
    SPI_BUFFER_TX3[1] = SPI_NULL;
    SPI_BUFFER_TX3[2] = SPI_NULL;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    HAL_SPI_TransmitReceive(&SPI_Structure, CAN_RX_STATUS, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_NULL, &data, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_NULL, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    return data;
  /*
  bit 7 - CANINTF.RX1IF
  bit 6 - CANINTF.RX0IF
  bit 5 -
  bit 4 - RXBnSIDL.EIDE
  bit 3 - RXBnDLC.RTR
  bit 2 | 1 | 0 | Filter Match
  ------|---|---|-------------
      0 | 0 | 0 | RXF0
        0 | 0 | 1 | RXF1
        0 | 1 | 0 | RXF2
        0 | 1 | 1 | RXF3
        1 | 0 | 0 | RXF4
        1 | 0 | 1 | RXF5
        1 | 1 | 0 | RXF0 (rollover to RXB1)
        1 | 1 | 1 | RXF1 (rollover to RXB1)
  */
}

void MCP2515_BitModify(uint8_t address, uint8_t mask, uint8_t data) {
  // see data sheet for explanation
    uint8_t check_status;
    SPI_BUFFER_TX4[0] = CAN_BIT_MODIFY_BASE;
    SPI_BUFFER_TX4[1] = address;
    SPI_BUFFER_TX4[2] = mask;
    SPI_BUFFER_TX4[3] = data;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    check_status = HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX4, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE4, SPI_TIMEOUT);
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    while (check_status != 0) {
        while (1) {
        }
    }
}

uint8_t MCP2515_Interrupt(void) {
  if (__HAL_RCC_GET_IT(RCC_IT_HSERDY) == 1) return 1;
  else if (__HAL_RCC_GET_IT(RCC_IT_PLLRDY) == 1) return 1;
  else if (__HAL_RCC_GET_IT(RCC_IT_PLLI2SRDY) == 1) return 1;
  else if (__HAL_RCC_GET_IT(RCC_IT_CSS) == 1) return 1;
  else if (__HAL_SPI_GET_IT_SOURCE(&SPI_Structure, SPI_IT_TXE) == 1) return 1;
  else if (__HAL_SPI_GET_IT_SOURCE(&SPI_Structure, SPI_IT_RXNE) == 1) return 1;
  else if (__HAL_SPI_GET_IT_SOURCE(&SPI_Structure, SPI_IT_ERR) == 1) return 1;
  else return 0;
}

uint8_t MCP2515_Mode(uint8_t mode) {
  /*
  mode can be one of the following:
  MODE_CONFIG
  MODE_LISTEN
  MODE_LOOPBACK
  MODE_SLEEP
  MODE_NORMAL
  */

    MCP2515_BitModify(CANCTRL, 0xE0, mode);
    SPI_BUFFER_TX2[0] = CANSTAT_BASE;
    SPI_BUFFER_TX2[1] = SPI_NULL;
    uint8_t return_value = 0;
    uint8_t data;
    uint8_t check_status;
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);
    check_status = HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_BUFFER_TX2, &SPI_BUFFER_RX2, SPI_MESSAGE_SIZE2, SPI_TIMEOUT);
//  HAL_SPI_TransmitReceive(&SPI_Structure, CANSTAT, &SPI_BLANK_RECEIVE, SPI_MESSAGE_SIZE1, SPI_TIMEOUT); // check mode has been set
//  HAL_SPI_TransmitReceive(&SPI_Structure, &SPI_NULL, &data, SPI_MESSAGE_SIZE1, SPI_TIMEOUT); // check mode has been set
    HAL_GPIO_WritePin(SPI1_CS_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
    if (check_status != 0) {
        while (1) {
        }
    }
    data = SPI_BUFFER_RX2[1];
    if ((data & mode) == mode) return_value = 1;
    return return_value;
}

/*
 * return:
 *      1 - All transmit buffers clear
 *      2 - 1 and 2 buffers clear
 *      3 - 1 and 3 buffers clear
 *      4 - 1 buffer clear
 *      5 - 2 and 3 buffers clear
 *      6 - 2 buffer clear
 *      7 - 3 buffer clear
 *      0 - no buffers clear
 */
uint8_t MCP2515_Check_Buffers_Clear(uint8_t info) {
    uint8_t result = 0x00;
    if ((info & 0x0C) != 0x0C) {
        if ((info & 0x20) != 0x20) {
            if ((info & 0xC0) != 0xC0) {
                result = 0x01;
            } else {
                result = 0x02;
            }
        } else {
            if ((info & 0xC0) != 0xC0) {
                result = 0x03;
            } else {
                result = 0x04;
            }
        }
    }
    else {
        if ((info & 0x20) != 0x20) {
            if ((info & 0xC0) != 0xC0) {
                result = 0x05;
            } else {
                result = 0x06;
            }
        } else {
            if ((info & 0xC0) != 0xC0) {
                result = 0x07;
            } else {
                result = 0x00;
            }
        }
    }
    return result;
}

uint16_t MCP2515_ReceivingMessage(uint8_t MCP2515_info, uint8_t MCP2515_RXdata)
{
    /* Buffer used for reception */
    uint8_t MCP2515_RxBuffer1 = 0;
    uint8_t MCP2515_RxBuffer2 = 0;
    uint16_t return_value = 0;

    /* Receiving a Message */
    if ((MCP2515_info & 0x01) == 0x01 || (MCP2515_info & 0x02) == 0x02) {                   // If Rx Buffer 1 and 2 are full
        if ((MCP2515_RXdata & 0xC0) == 0xC0) {                                  // if both Rx buffers hold messages
            MCP2515_RxBuffer1 = MCP2515_Read(RXB0D0);
            MCP2515_RxBuffer2 = MCP2515_Read(RXB1D0);
            if ((MCP2515_RXdata & 0x06) == 0x06) {                              // if messages are related (rollover)
                return_value = return_value | MCP2515_RxBuffer1;
                return_value = return_value << 8;
                return_value = return_value | MCP2515_RxBuffer2;
            }
        }
        else if ((MCP2515_RXdata & 0x40) == 0x40) {         // if Rx buffer 1 holds a message (buffer 2 holds a noise trip)
            return_value = MCP2515_Read(RXB0D0);
        }
        else if ((MCP2515_RXdata & 0x80) == 0x80) {         // if Rx buffer 2 holds a message (buffer 1 holds a noise trip)
            return_value = MCP2515_Read(RXB1D0);
        }
    }
    return return_value;
}

void MCP2515_SendingMessage(uint8_t MCP2515_info, uint16_t MCP2515_send_long_data, uint8_t MCP2515_send_data)
{
    /* Buffer used for transmission */
    uint8_t MCP2515_TxBuffer1;
    uint8_t MCP2515_TxBuffer2;

    uint8_t MCP2515_status_buffers;

    /* Sending a Message */
    if (MCP2515_send_data != 0 || MCP2515_send_long_data != 0) {                    // checks if a message is required to be sent
        MCP2515_status_buffers = MCP2515_Check_Buffers_Clear(MCP2515_info);                 // checks to see which Tx buffers are free
        while (MCP2515_status_buffers == 0){                                // if no buffers are free, loop until one is free
            MCP2515_status_buffers = MCP2515_Check_Buffers_Clear(MCP2515_info);
        }
        if (MCP2515_send_long_data != 0) {                                  // if a 16 bit message is required to be sent
            while ((MCP2515_status_buffers == 4) || MCP2515_status_buffers > 5) {   // loop until two buffers are free
                MCP2515_status_buffers = MCP2515_Check_Buffers_Clear(MCP2515_info);
            }
            MCP2515_TxBuffer1 = MCP2515_send_long_data;
            MCP2515_send_long_data = MCP2515_send_long_data >> 8;
            MCP2515_TxBuffer2 = MCP2515_send_long_data;
            if (0 < MCP2515_status_buffers && MCP2515_status_buffers < 3) {         // send through buffer 1 and 2
                MCP2515_Single_Write(TXB0D0, MCP2515_TxBuffer1);
                MCP2515_Single_Write(TXB1D0, MCP2515_TxBuffer2);
                MCP2515_SendBuffer(0x03);
                MCP2515_TxBuffer1 = 0x00;
                MCP2515_TxBuffer2 = 0x00;
            }
            else if (MCP2515_status_buffers == 3) {                         // send through buffer 1 and 3
                MCP2515_Single_Write(TXB0D0, MCP2515_TxBuffer1);
                MCP2515_Single_Write(TXB2D0, MCP2515_TxBuffer2);
                MCP2515_SendBuffer(0x05);
                MCP2515_TxBuffer1 = 0x00;
                MCP2515_TxBuffer2 = 0x00;
            }
            else if (MCP2515_status_buffers == 5) {                         // send through buffer 2 and 3
                MCP2515_Single_Write(TXB1D0, MCP2515_TxBuffer1);
                MCP2515_Single_Write(TXB2D0, MCP2515_TxBuffer2);
                MCP2515_SendBuffer(0x06);
                MCP2515_TxBuffer1 = 0x00;
                MCP2515_TxBuffer2 = 0x00;
            }
            MCP2515_send_long_data = 0x00;
        }
                                                                    // send a single message
        else if (MCP2515_send_data != 0) {                                  // send through buffer 1
            if (0 < MCP2515_status_buffers && MCP2515_status_buffers < 5) {
                MCP2515_Single_Write(TXB0D0, MCP2515_send_data);
                MCP2515_SendBuffer(0x01);
            }
            else if (4 < MCP2515_status_buffers && MCP2515_status_buffers < 7) {    // send through buffer 2
                MCP2515_Single_Write(TXB1D0, MCP2515_send_data);
                MCP2515_SendBuffer(0x02);
            }
            else if (MCP2515_status_buffers == 7) {                         // send through buffer 3
                MCP2515_Single_Write(TXB2D0, MCP2515_send_data);
                MCP2515_SendBuffer(0x04);
            }
            //MCP2515_send_data = 0;
        }
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ What does the scope show you is happening on MISO? Do you get a non-zero value from reading any register? What do you read if you do not drive the chip select, but instead pull up MISO to VDD with a small resistor? Some chips require you to go through a sequence to unlock certain registers, but reading zero sounds as likely to be a configuration or electrical problem, so try some of these tests and see if you can get some non-zero values. \$\endgroup\$ – Chris Stratton Jul 26 '16 at 4:27
  • 1
    \$\begingroup\$ You should include the relevant code here (and scope output as Chris suggested). You haven't given us much to debug from. \$\endgroup\$ – skrrgwasme Jul 26 '16 at 5:35
  • \$\begingroup\$ Will try seeing if i get a non-zero value. I can't say I have tried doing any of those tests yet so will give it a go thanks Chris. And I will add the code now \$\endgroup\$ – Nicholas Lloyd Jul 27 '16 at 6:04
-1
\$\begingroup\$

mcp2515.h

/*
 * STM32F7xx_MCP2515.h
 * Library for Microchip MCP2515 CAN Controller
 *
 *  Created on: Jun 28, 2016
 *      Author: Nicholas Lloyd
 *
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
 */

#ifndef STM32F7XX_MCP2515_H_
#define STM32F7XX_MCP2515_H_

#include "stm32f7xx_hal_def.h"

typedef struct
{
    unsigned long IDType; // EID if ide set, SID otherwise
    uint8_t StdFrameRemoteReq; // Standeard Frame Remote Transmit Request
    uint8_t RemoteTxReq; // Remote Transmission Request
    uint8_t ExtIDFlg; // Extended ID Flag
    uint8_t NumDataBytes; // Number of Data Bytes
    uint8_t Data[8]; // Data bytes
} Frame;

/* Make adjustments to the LED Port and Pin location if necessary */
#define USER_LED_PORT           GPIOB
//#define USER_LED_RED          GPIO_PIN_0
#define USER_LED_BLUE           GPIO_PIN_7
//#define USER_LED_GREEN        GPIO_PIN_14

/* SPI Defines */
/* Definition for SPIx Pins */
#define SPI1_GPIO_PORT                   GPIOA
#define SPI1_AF                          GPIO_AF5_SPI1
#define SPI1_SCK_PIN                     GPIO_PIN_5
#define SPI1_MISO_PIN                    GPIO_PIN_6
#define SPI1_MOSI_PIN                    GPIO_PIN_7

/* Definition for Button Pin */
#define SPI1_CS_PIN                      GPIO_PIN_14
#define SPI1_CS_PORT                     GPIOD

/* Definitions of the SPI message sizes*/
#define SPI_MESSAGE_SIZE1               1
#define SPI_MESSAGE_SIZE2               2
#define SPI_MESSAGE_SIZE3               3
#define SPI_MESSAGE_SIZE4               4

#define SPI_TIMEOUT                 0xF000

/* CAN Defines */
// MCP2515 SPI Commands
#define CAN_RESET_BASE          0xC0
#define CAN_RESET               ((uint8_t *)0xC0)
#define CAN_READ_BASE           0x03
#define CAN_READ                ((uint8_t *)0x03)
#define CAN_WRITE_BASE          0x02
#define CAN_WRITE               ((uint8_t *)0x02)
#define CAN_RTS_BASE            0x80
#define CAN_RTS                 ((uint8_t *)0x80)
#define CAN_STATUS_BASE         0xA0
#define CAN_STATUS              ((uint8_t *)0xA0)
#define CAN_BIT_MODIFY_BASE     0x05
#define CAN_BIT_MODIFY          ((uint8_t *)0x05)
#define CAN_RX_STATUS_BASE      0xB0
#define CAN_RX_STATUS           ((uint8_t *)0xB0)
#define CAN_READ_BUFFER_BASE    0x90
#define CAN_READ_BUFFER         ((uint8_t *)0x90)
#define CAN_LOAD_BUFFER_BASE    0X40
#define CAN_LOAD_BUFFER         ((uint8_t *)0X40)

// Register Bit Masks
// CANSTAT
#define MODE_CONFIG         0x80
#define MODE_LISTEN         0x60
#define MODE_LOOPBACK       0x40
#define MODE_SLEEP          0x20
#define MODE_NORMAL         0x00
// CANINTF
#define RX0IF               0x01
#define RX1IF               0x02
#define TX0IF               0x04
#define TX1IF               0x08
#define TX2IF               0x10
#define ERRIF               0x20
#define WAKIF               0x40
#define MERRF               0x80

// Configuration Registers
#define CANSTAT_BASE        0x0E
#define CANSTAT             ((uint8_t *)0x0E)
#define CANCTRL             0x0F
#define BFPCTRL             0x0C
#define TEC                 0x1C
#define REC                 0x1D
#define CNF3                0x28
#define CNF2                0x29
#define CNF1                0x2A
#define CANINTE             0x2B
#define CANINTF             0x2C
#define EFLG                0x2D
#define TXRTSCTRL           0x0D

// TX Buffer 0
#define TXB0CTRL            0x30
#define TXB0SIDH            0x31
#define TXB0SIDL            0x32
#define TXB0EID8            0x33
#define TXB0EID0            0x34
#define TXB0DLC             0x35
#define TXB0D0              0x36
#define TXB0D1              0x37
#define TXB0D2              0x38
#define TXB0D3              0x39
#define TXB0D4              0x3A
#define TXB0D5              0x3B
#define TXB0D6              0x3C
#define TXB0D7              0x3D

// TX Buffer 1
#define TXB1CTRL            0x40
#define TXB1SIDH            0x41
#define TXB1SIDL            0x42
#define TXB1EID8            0x43
#define TXB1EID0            0x44
#define TXB1DLC             0x45
#define TXB1D0              0x46
#define TXB1D1              0x47
#define TXB1D2              0x48
#define TXB1D3              0x49
#define TXB1D4              0x4A
#define TXB1D5              0x4B
#define TXB1D6              0x4C
#define TXB1D7              0x4D

// TX Buffer 2
#define TXB2CTRL            0x50
#define TXB2SIDH            0x51
#define TXB2SIDL            0x52
#define TXB2EID8            0x53
#define TXB2EID0            0x54
#define TXB2DLC             0x55
#define TXB2D0              0x56
#define TXB2D1              0x57
#define TXB2D2              0x58
#define TXB2D3              0x59
#define TXB2D4              0x5A
#define TXB2D5              0x5B
#define TXB2D6              0x5C
#define TXB2D7              0x5D

// RX Buffer 0
#define RXB0CTRL            0x60
#define RXB0SIDH            0x61
#define RXB0SIDL            0x62
#define RXB0EID8            0x63
#define RXB0EID0            0x64
#define RXB0DLC             0x65
#define RXB0D0              0x66
#define RXB0D1              0x67
#define RXB0D2              0x68
#define RXB0D3              0x69
#define RXB0D4              0x6A
#define RXB0D5              0x6B
#define RXB0D6              0x6C
#define RXB0D7              0x6D

// RX Buffer 1
#define RXB1CTRL            0x70
#define RXB1SIDH            0x71
#define RXB1SIDL            0x72
#define RXB1EID8            0x73
#define RXB1EID0            0x74
#define RXB1DLC             0x75
#define RXB1D0              0x76
#define RXB1D1              0x77
#define RXB1D2              0x78
#define RXB1D3              0x79
#define RXB1D4              0x7A
#define RXB1D5              0x7B
#define RXB1D6              0x7C
#define RXB1D7              0x7D

// Buffer Bit Masks
#define RXB0                0x00
#define RXB1                0x02
#define TXB0                0x01
#define TXB1                0x02
#define TXB2                0x04
#define TXB_ALL             TXB0 | TXB1 | TXB2

void MCP2515_GPIO_Configuration();
void MCP2515_SPI_Configuration();

// Initialization function
int MCP2515_Initialise(int baud, uint8_t freq, uint8_t SJW);
int MCP2515_SubInitialise(int baud, uint8_t Freq, uint8_t sjw, uint8_t autoBaud);

// Basic MCP2515 SPI Command Set
void MCP2515_Reset();
uint8_t MCP2515_Read(uint8_t address);
void MCP2515_Read_Multiple(uint8_t address, uint8_t data[], uint8_t bytes);
uint8_t MCP2515_ReadBuffer(uint8_t buffer);
void MCP2515_Single_Write(uint8_t address, uint8_t data);
void MCP2515_LoadBuffer(uint8_t buffer, uint8_t data);
void MCP2515_SendBuffer(uint8_t buffers);
uint8_t MCP2515_Status();
uint8_t MCP2515_RXStatus();
void MCP2515_BitModify(uint8_t address, uint8_t mask, uint8_t data);

// Extra functions
uint8_t MCP2515_Interrupt(); // Expose state of INT pin
uint8_t MCP2515_Mode(uint8_t mode); // Returns TRUE if mode change successful
uint8_t MCP2515_Check_Buffers_Clear(uint8_t info);
uint16_t MCP2515_ReceivingMessage(uint8_t MCP2515_info, uint8_t MCP2515_RXdata);
void MCP2515_SendingMessage(uint8_t MCP2515_info, uint16_t MCP2515_send_long_data, uint8_t MCP2515_send_data);

#endif

and main.c

void RCC_Configuration(void)
{
    HAL_Init();

    RCC_ClkInitTypeDef RCC_ClkInitStruct;
    RCC_OscInitTypeDef RCC_OscInitStruct;

    RCC_OscInitStruct.OscillatorType    = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState          = RCC_HSE_ON;
    RCC_OscInitStruct.HSIState      = RCC_HSI_OFF;
    RCC_OscInitStruct.PLL.PLLState      = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource     = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM          = 8;
    RCC_OscInitStruct.PLL.PLLN          = 256;
    RCC_OscInitStruct.PLL.PLLP          = RCC_PLLP_DIV4;
    RCC_OscInitStruct.PLL.PLLQ          = 9;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        /* Initialization Error */
        while (1) {
        }
    }

    /* Activate the OverDrive to reach the 216 Mhz Frequency */
    if(HAL_PWREx_EnableOverDrive() != HAL_OK)
    {
        while(1) {};
    }

    /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
         clocks dividers */
    RCC_ClkInitStruct.ClockType       = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
    RCC_ClkInitStruct.SYSCLKSource    = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider   = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider  = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider  = RCC_HCLK_DIV2;
    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
    {
        /* Initialization Error */
        while (1) {
        }
    }

    __HAL_RCC_PWR_CLK_ENABLE();
}


int main(void)
{
    RCC_Configuration();
    SystemCoreClockUpdate();

    /* Initialise MCP2515 functions */
    MCP2515_GPIO_Configuration();
    MCP2515_SPI_Configuration();

    if (MCP2515_Initialise(500, 32, 1) == 0) {
        while (1){
        }
    }

    /* Variables in main for MCP2515 */
    uint8_t MCP2515_Info = 0;
    uint8_t MCP2515_SendData = 0xAA;
    uint16_t MCP2515_SendLongData = 0;
    uint16_t MCP2515_ReceivedData = 0;
    uint8_t MCP2515_RXdata;
    while (1)
    {
        MCP2515_Info = MCP2515_Status();
        MCP2515_RXdata = MCP2515_RXStatus();

        // Receiving a Message
        MCP2515_ReceivedData = MCP2515_ReceivingMessage(MCP2515_Info, MCP2515_RXdata);
        // Sending a Message
        MCP2515_SendingMessage(MCP2515_Info, MCP2515_SendLongData, MCP2515_SendData);
    }
}
\$\endgroup\$
  • 4
    \$\begingroup\$ Unfortunately, this post can't be merged with the question directly, because it makes the total length too large. The OP will have to do a better job of condensing his question down to the essential details, rather than dumping entire source files on us. \$\endgroup\$ – Dave Tweed Oct 25 '16 at 12:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.