Two MCP2515 one crystal, how to set CLKOUT

Hi!

I have two MCP2515 connected to one crystal like in datasheet - first MCP have crystal, second MCP was connect OSC1 to CLKOUT first MCP but it doesn't work. I use MCP CAN library by Cory J Fowler.
Probably CLKOUT was default off. I try to change MCP register but I'm not sure how to do it.
I tried to do that:

void setup()
{
if (CAN0.begin(MCP_ANY, CAN_125KBPS, MCP_8MHZ) == CAN_OK)
  {
    CAN0.setMode(MODE_CONFIG);
    CAN0.setMode(CLKOUT_ENABLE);
    CAN0.setMode(CLKOUT_PS1);
    CAN0.setMode(SOF_DISABLE);
    CAN0.setMode(MCP_NORMAL);
  }
  
  delay(50);
  if (CAN1.begin(MCP_ANY, CAN_125KBPS, MCP_8MHZ) == CAN_OK)
  {
    CAN1.setMode(MCP_NORMAL);
  }
}

Any help is appreciated, thanks.

SOF_DISABLE is in the CNF3 register, not CANCTRL, therefore setMode is the wrong function.
Try mcp2515_modifyRegister.

Additionally, the setMode function is hard coded to only write to bits 7-5 REQOP[2:0] of the CANCTRL register. Have a look at the source code its only three files and straightforward code.

The clock out is enabled by default but divided by 8. It is intended to be used as clock for a microcontroller for cost sensitive applications and therefore needs to be enabled at power up. Otherwise the microcontroller might not be able not start up, if it does not have a internal RC oscillator.

@mikb55
SOF_DISABLE is in the CNF3 register and CLKOUT_ENABLE, CLKOUT_PS1 is in the CANCTRL register. I must set this register, but i don't know how to do it.

I tried to do that with mcp2515_modifyRegister function but when i try compile program i have error - mcp2515_modifyRegister was private function.

@Klaus_K
I was analyzing the library and I see functions for modifying bits but I can't call it.

MCP_CAN the library is set to SOF_ENABLE by default. I checked it with a logical analyzer.

The microcontroller has its own crystal 16MHz, two MCP2515 Has one crystal 8MHz.

lumos___:
I tried to do that with mcp2515_modifyRegister function but when i try compile program i have error - mcp2515_modifyRegister was private function.

Change the private/public visibility in the header file.

lumos___:
Probably CLKOUT was default off.

It is disabled. SOF was more useful to me early on. The easiest/fastest way to modify that library would be to do the following:

In the following function:

/*********************************************************************************************************
** Function name:           mcp2515_configRate
** Descriptions:            Set baudrate
*********************************************************************************************************/
INT8U MCP_CAN::mcp2515_configRate(const INT8U canSpeed, const INT8U canClock)            
{  ...

Change:

mcp2515_setRegister(MCP_CNF3, cfg3);

To:

mcp2515_setRegister(MCP_CNF3, (cfg3 & 0x7F));

However, you are right that this should be exposed as a function in some manner though. I'll have to think about how to architect that into the library.

coryjfowler:
The easiest/fastest way to modify that library would be to do the following

Thanks a lot, it works :slight_smile: How to change the divisor? The clock out is enabled but divided by 8. I need to set the divisor to 1.

Edit:
Solved. To change divisior i put in void setup this:

CAN0.mcp2515_modifyRegister(MCP_CANCTRL, 0x03, 0);

Thank you all for your help!

This might be a way to implement it more elegantly, however I do not have any hardware right now to test on.

This would go in mcp_can.cpp:

/*********************************************************************************************************
** Function name:           setCLKOUT
** Descriptions:            Public function to set CLKOUT pin.  -- THIS IS NOT TESTED --
*********************************************************************************************************/
INT8U MCP_CAN::setCLKOUT(INT8U MODE)
{
    INT8U res = MCP2515_OK;
    INT8U temp = mcp2515_readRegister(MCP_CNF3);
    
    // If CLKOUT pin is not enabled, enable it
    if(( temp & 0x80 ))
    {
#if DEBUG_MODE
        Serial.print("Attempting to Enable CLKOUT pin!\r\n");
#endif
        res = mcp2515_setCANCTRL_Mode(MODE_CONFIG);
        if(res > 0)
        {
#if DEBUG_MODE
          Serial.print("Entering Configuration Mode Failure...\r\n"); 
#endif
          return res;
        }
	
        mcp2515_setRegister(MCP_CNF3, (temp & 0x7F));
    
        res = mcp2515_setCANCTRL_Mode(mcpMode);
        if(res > 0)
        {
#if DEBUG_MODE
          Serial.print("Returning to Previous Mode Failure...\r\nEnabling CLKOUT pin Failure...\r\n"); 
#endif
          return res;
        }
#if DEBUG_MODE
        Serial.print("Enabling CLKOUT pin Successful!\r\n");
#endif
    }
    
    mcp2515_modifyRegister(MCP_CANCTRL, 0x07, MODE);
    
    if((mcp2515_readRegister(MCP_CANCTRL) & 0x07) != MODE)
        return CAN_FAIL;
    
    return res;
}

This would go in mcp_can.h:

INT8U setCLKOUT(INT8U mode);                                           // Enables CLKOUT pin and sets CANCTRL settings

An example usage:

CAN0.setCLKOUT(CLKOUT_ENABLE | CLKOUT_PS1);