How to change this library file's frequency

How to change the frequency from 16 MHZ to 8MHZ in the MCP2515.cpp attached here ?
Thanks
Adam

/* Copyright (c) 2007 Fabian Greif
 * All rights reserved.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
 */
// ----------------------------------------------------------------------------


#include <avr/io.h>
#include <util/delay.h>

#if ARDUINO>=100
#include <Arduino.h> // Arduino 1.0
#else
#include <Wprogram.h> // Arduino 0022
#endif
#include <stdint.h>
#include <avr/pgmspace.h>

#include "global.h"
#include "mcp2515.h"
#include "mcp2515_defs.h"


#include "defaults.h"

// -------------------------------------------------------------------------
// Schreibt/liest ein Byte ueber den Hardware SPI Bus

uint8_t spi_putc( uint8_t data )
{
  // put byte in send-buffer
  SPDR = data;
  
  // wait until byte was send
  while( !( SPSR & (1<<SPIF) ) )
    ;
  
  return SPDR;
}

// -------------------------------------------------------------------------
void mcp2515_write_register( uint8_t adress, uint8_t data )
{
  RESET(MCP2515_CS);
  
  spi_putc(SPI_WRITE);
  spi_putc(adress);
  spi_putc(data);
  
  SET(MCP2515_CS);
}

// -------------------------------------------------------------------------
uint8_t mcp2515_read_register(uint8_t adress)
{
  uint8_t data;
  
  RESET(MCP2515_CS);
  
  spi_putc(SPI_READ);
  spi_putc(adress);
  
  data = spi_putc(0xff);  
  
  SET(MCP2515_CS);
  
  return data;
}

// -------------------------------------------------------------------------
void mcp2515_bit_modify(uint8_t adress, uint8_t mask, uint8_t data)
{
  RESET(MCP2515_CS);
  
  spi_putc(SPI_BIT_MODIFY);
  spi_putc(adress);
  spi_putc(mask);
  spi_putc(data);
  
  SET(MCP2515_CS);
}

// ----------------------------------------------------------------------------
uint8_t mcp2515_read_status(uint8_t type)
{
  uint8_t data;
  
  RESET(MCP2515_CS);
  
  spi_putc(type);
  data = spi_putc(0xff);
  
  SET(MCP2515_CS);
  
  return data;
}

// -------------------------------------------------------------------------
uint8_t mcp2515_init(uint8_t speed)
{
    
  
  SET(MCP2515_CS);
  SET_OUTPUT(MCP2515_CS);
  
  RESET(P_SCK);
  RESET(P_MOSI);
  RESET(P_MISO);
  
  SET_OUTPUT(P_SCK);
  SET_OUTPUT(P_MOSI);
  SET_INPUT(P_MISO);
  
  SET_INPUT(MCP2515_INT);
  SET(MCP2515_INT);
  
  // active SPI master interface
  SPCR = (1<<SPE)|(1<<MSTR) | (0<<SPR1)|(1<<SPR0);
  SPSR = 0;
  
  // reset MCP2515 by software reset.
  // After this he is in configuration mode.
  RESET(MCP2515_CS);
  spi_putc(SPI_RESET);
  SET(MCP2515_CS);
  
  // wait a little bit until the MCP2515 has restarted
  _delay_us(10);
  
  // load CNF1..3 Register
  RESET(MCP2515_CS);
  spi_putc(SPI_WRITE);
  spi_putc(CNF3);
  
/*  spi_putc((1<<PHSEG21));   // Bitrate 125 kbps at 16 MHz
  spi_putc((1<<BTLMODE)|(1<<PHSEG11));
  spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0));
*/
/*  
  spi_putc((1<<PHSEG21));   // Bitrate 250 kbps at 16 MHz
  spi_putc((1<<BTLMODE)|(1<<PHSEG11));
  spi_putc((1<<BRP1)|(1<<BRP0));
*/  
  spi_putc((1<<PHSEG21));   // Bitrate 250 kbps at 16 MHz
  spi_putc((1<<BTLMODE)|(1<<PHSEG11));
  //spi_putc(1<<BRP0);
    spi_putc(speed);

  // activate interrupts
  spi_putc((1<<RX1IE)|(1<<RX0IE));
  SET(MCP2515_CS);
  
  // test if we could read back the value => is the chip accessible?
  if (mcp2515_read_register(CNF1) != speed) {
    SET(LED2_HIGH);

    return false;
  }
  
  // deaktivate the RXnBF Pins (High Impedance State)
  mcp2515_write_register(BFPCTRL, 0);
  
  // set TXnRTS as inputs
  mcp2515_write_register(TXRTSCTRL, 0);
  
  // turn off filters => receive any message
  mcp2515_write_register(RXB0CTRL, (1<<RXM1)|(1<<RXM0));
  mcp2515_write_register(RXB1CTRL, (1<<RXM1)|(1<<RXM0));
  
  // reset device to normal mode
  mcp2515_write_register(CANCTRL, 0);
//  SET(LED2_HIGH);
  return true;
}

// ----------------------------------------------------------------------------
// check if there are any new messages waiting

uint8_t mcp2515_check_message(void) {
  return (!IS_SET(MCP2515_INT));
}

// ----------------------------------------------------------------------------
// check if there is a free buffer to send messages

uint8_t mcp2515_check_free_buffer(void)
{
  uint8_t status = mcp2515_read_status(SPI_READ_STATUS);
  
  if ((status & 0x54) == 0x54) {
    // all buffers used
    return false;
  }
  
  return true;
}

// ----------------------------------------------------------------------------
uint8_t mcp2515_get_message(tCAN *message)
{
  // read status
  uint8_t status = mcp2515_read_status(SPI_RX_STATUS);
  uint8_t addr;
  uint8_t t;
  if (bit_is_set(status,6)) {
    // message in buffer 0
    addr = SPI_READ_RX;
  }
  else if (bit_is_set(status,7)) {
    // message in buffer 1
    addr = SPI_READ_RX | 0x04;
  }
  else {
    // Error: no message available
    return 0;
  }

  RESET(MCP2515_CS);
  spi_putc(addr);
  
  // read id
  message->id  = (uint16_t) spi_putc(0xff) << 3;
  message->id |=            spi_putc(0xff) >> 5;
  
  spi_putc(0xff);
  spi_putc(0xff);
  
  // read DLC
  uint8_t length = spi_putc(0xff) & 0x0f;
  
  message->header.length = length;
  message->header.rtr = (bit_is_set(status, 3)) ? 1 : 0;
  
  // read data
  for (t=0;t<length;t++) {
    message->data[t] = spi_putc(0xff);
  }
  SET(MCP2515_CS);
  
  // clear interrupt flag
  if (bit_is_set(status, 6)) {
    mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
  }
  else {
    mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);
  }
  
  return (status & 0x07) + 1;
}

// ----------------------------------------------------------------------------
uint8_t mcp2515_send_message(tCAN *message)
{
  uint8_t status = mcp2515_read_status(SPI_READ_STATUS);
  
  /* Statusbyte:
   *
   * Bit  Function
   *  2 TXB0CNTRL.TXREQ
   *  4 TXB1CNTRL.TXREQ
   *  6 TXB2CNTRL.TXREQ
   */
  uint8_t address;
  uint8_t t;
//  SET(LED2_HIGH);
  if (bit_is_clear(status, 2)) {
    address = 0x00;
  }
  else if (bit_is_clear(status, 4)) {
    address = 0x02;
  } 
  else if (bit_is_clear(status, 6)) {
    address = 0x04;
  }
  else {
    // all buffer used => could not send message
    return 0;
  }
  
  RESET(MCP2515_CS);
  spi_putc(SPI_WRITE_TX | address);
  
  spi_putc(message->id >> 3);
    spi_putc(message->id << 5);
  
  spi_putc(0);
  spi_putc(0);
  
  uint8_t length = message->header.length & 0x0f;
  
  if (message->header.rtr) {
    // a rtr-frame has a length, but contains no data
    spi_putc((1<<RTR) | length);
  }
  else {
    // set message length
    spi_putc(length);
    
    // data
    for (t=0;t<length;t++) {
      spi_putc(message->data[t]);
    }
  }
  SET(MCP2515_CS);
  
  _delay_us(1);
  
  // send message
  RESET(MCP2515_CS);
  address = (address == 0) ? 1 : address;
  spi_putc(SPI_RTS | address);
  SET(MCP2515_CS);
  
  return address;
}

where does it come from?

J-M-L:
where does it come from?

Thanks.
It was from here:

OK, this library is written for a the SparkFun CAN-Bus Shield that plugs on top of the UNO, so assumes 16Mhz

have you considered looking at a different library? the MCP2515_lib has support for 8MHz MCP2515 modules

J-M-L:
OK, this library is written for a the SparkFun CAN-Bus Shield that plugs on top of the UNO, so assumes 16Mhz

have you considered looking at a different library? the MCP2515_lib has support for 8MHz MCP2515 modules

Thanks.
I have used few of the Libs of MCP2515 which support 8MHZ, but none of them support sketch bound to the lib I posted above, I knew that I should modify the sketch relatively when change the lib file, and I'll leave this later.

I didn't find the words 'MCP2515.cpp' in the library you mentioned may same function as 'mcp_can.cpp'? I just take the one I used to explain what confused me now is the example included in the libraries attached later just setup MCP2515's Bitrate without indicated MHZ like:
..... mcp2515.setBitrate(CAN_125KBPS); .....
how can MCP2515 pickup 8MHZ or 16MHZ itself?
The example:

#include <SPI.h>
#include <mcp2515.h>

struct can_frame canMsg;
MCP2515 mcp2515(10);


void setup() {
  Serial.begin(115200);
  SPI.begin();
  
  mcp2515.reset();
  mcp2515.setBitrate(CAN_125KBPS);
  mcp2515.setNormalMode();
  
  Serial.println("------- CAN Read ----------");
  Serial.println("ID  DLC   DATA");
}

void loop() {
  
  if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK) {
      
    Serial.print(canMsg.can_id, HEX); // print ID
    Serial.print(" "); 
    Serial.print(canMsg.can_dlc, HEX); // print DLC
    Serial.print(" ");
    
    for (int i = 0; i<canMsg.can_dlc; i++)  {  // print the data
        
      Serial.print(canMsg.data[i],HEX);
      Serial.print(" ");

    }

    Serial.println();      
  }

}

mcp2515.cpp (20.9 KB)

Look in mcp2515.h and mcp2515.cpp.

You'll see that the setBitrate() function is overloaded. With only one parameter it defaults to a 16 MHz clock. If you have a different processor speed, you need to use the overloaded setBitrate() function with 2 arguments. The second argument needs to be from the CAN_CLOCK enum that's defined in mcp2515.h.

gfvalvo:
Look in mcp2515.h and mcp2515.cpp.

You'll see that the setBitrate() function is overloaded. With only one parameter it defaults to a 16 MHz clock. If you have a different processor speed, you need to use the overloaded setBitrate() function with 2 arguments. The second argument needs to be from the CAN_CLOCK enum that's defined in mcp2515.h.

Thanks and sorry about I modified my #4 reply after your post.
I have tried this method, doesn't work cause of many other contents.

Can we just go back to my original question, how to change the library file's frequency attached? Seems it used the following code setup the Bitrate:

spi_putc((1<<PHSEG21));		// Bitrate 250 kbps at 16 MHz
	spi_putc((1<<BTLMODE)|(1<<PHSEG11));
	//spi_putc(1<<BRP0);
    spi_putc(speed);

laoadam:
I have tried this method, doesn't work cause of many other contents.

No idea what that means.

gfvalvo:
No idea what that means.

Thanks.
The project sketch I tested was bound with a library, the mcp2515.cpp is included in that library, there are many errors come up when change into another mcp2515.cpp.

Well if you change the library you have a different API and thus need to rewrite your program using the new API

I guess I may need clarify what I need is how to config a MCP2515's frequency to work with a 8MHZ oscillator instead of a 16 MHZ one. Or maybe no need do any configuration, and MCP2515 just automatically suit for any external oscillator?

Thanks

laoadam:
I guess I may need clarify what I need

What you NEED to do is:

  • Post the code representing your best and latest attempt at solving this problem yourself.

  • Post a GitHub link to the EXACT MCP2515 library you're trying to use.

  • Tell us what processor board you are using.