⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcp2515.c

📁 CAN 程序使用MCP2515 由STM32做主芯片控制
💻 C
字号:
/*------------------------------------------------------
FILE NAME   : mcp2515.c
DESCRIPTION : CAN MCP2515 driver.
VERSION     : 1.0.0 
AUTHOR      : 
CREATE DATE : 03.12.2009
MODIFY DATE : 04.5.2009
LOGS        :-\ 
--------------------------------------------------------*/
//-----------------Include files-------------------------//
#include "..\header\type.h"
#include "..\header\mylib.h"
#include "..\header\hardware.h"
#include "..\header\spi.h"
//-----------------Function Prototype--------------------//

//-----------------Variable------------------------------//  
   
//-----------------Function------------------------------//
/*---------------------------------------------------------------
NAME       : mcp2515_write_can_id(const unsigned char mcp_addr,
             const unsigned char ext,const unsigned char can_id)
ENTRY  TYPE: void
RETURN TYPE: void
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: mcp_addr is the mcp2515 ID register,reg3-3 to 3-6;
              contain 31H...
             ext=1,there is extand ID use reg3-5 to 3-6;
			 can_id give the id to can msg,SID 11bit, extand SID 18bit;
CREATE DATE: ---
LOGS       : 1.first create 04.05.2009
-------------------------------------------------------------------------*/
#include "..\header\mcp2515.h"
#include "..\header\can.h"
#include "..\header\type.h"
/*---------------------------------delay------------------*/
unsigned int delay_ms(unsigned int n)
{
   int i,j;
   for(i=0;i<n;i++)
   for(j=0;j<10;j++)
   ;
   return 0;
}
/****************************************************************
mcp2515 intialize;
contain clock intialize, reset, speed rate set.


*******************************************************************/
unsigned char mcp2515_clock(void)
{
   GPIOA->CRH.B.CNF8  =2   ;
   GPIOA->CRH.B.MODE8 =3  ;
   RCC->CFGR.B.MCO=7; //SET MCO OUTPUT CLOCK FOR mcp2515,PLL/2;

   return 0;
}

unsigned char mcp2515_reset(void)    //reset mcp2515;
{
    CS_OFF;
    delay_ms(1);
	write_data(MCP_RESET);
//	delay_ms(5); // rough - but > 128 MCP clock-cycles
    //CS_ON;
	delay_ms(5);
	CS_ON;
    delay_ms(1);
	return 0;
}

unsigned char mcp2515_config_rate(void)   //input Fosc=8MHz
{ 
   CS_OFF;
   delay_ms(1);
   write_data(MCP_WRITE);
   write_data(MCP_CNF1);
   write_data(0x07);			// baud rate=125KHz,let TQ=1, BRP=16;
   write_data(0x32);	  //ps1=6
   write_data(0x83);	  //ps2=3
  // CS_ON;
   	CS_ON;
    delay_ms(1);
   
   return 0;
} 

/****************************************************************
read mcp2515 register;


*******************************************************************/
unsigned int mcp2515_read_register(const unsigned char address)
{
   unsigned int ret;

   CS_OFF;
   delay_ms(1);

   write_data(MCP_READ);
  // delay_ms(10);
   write_data(address);
  // delay_ms(100);
   ret = read_data();
   delay_ms(1);
   CS_ON;
   delay_ms(1);
   return ret;
}


/*********read the several register*********************/
unsigned char mcp2515_read_registers(const unsigned char address, 
	unsigned char values[], const unsigned char n)
{
	unsigned char i;	

    CS_OFF;
    delay_ms(1);

	write_data(MCP_READ);
    write_data(address);
	// mcp2515 has auto-increment of address-pointer
	for (i=0; i<n; i++) 
	  {
		values[i] = read_data();
		delay_ms(1);
      }
   	CS_ON;
    delay_ms(1);
	return 0;
}

/****************************************************************
Read the status register;


*******************************************************************/
unsigned char mcp2515_read_status(void)
{
	unsigned char sta;
	
    CS_OFF;
    delay_ms(1);

	write_data(MCP_READ_STATUS);
	sta = read_data();
	
	//delay_ms(1);
	CS_ON;
	delay_ms(1);
	return sta;
}
/****************************************************************
set the mcp2515 register,write the ID,DATA..


*******************************************************************/

/*********    set the registers*********************/
unsigned char mcp2515_set_register(const unsigned char address,const unsigned char value)
{

    CS_OFF;
    delay_ms(1);

	write_data(MCP_WRITE); //delay_ms(1);
	write_data(address);//delay_ms(1);
	write_data(value);// delay_ms(1);
	//delay_ms(1);
	CS_ON;
    delay_ms(1);

	return 0;
}

/*********set the several register*********************/
unsigned char mcp2515_set_registers(const unsigned char address, 
	const unsigned char values[], const unsigned char n)
{
	unsigned char i;
		
	
    CS_OFF;
    delay_ms(1);

	write_data(MCP_WRITE);
	write_data(address);
	// mcp2515 has auto-increment of address-pointer
	for (i=0; i<n; i++) 
	 { 
	  write_data(values[i]);
     }
//	delay_ms(1);
    CS_ON;
    delay_ms(1);
	return 0;
}

/**************************modify register***************************/
unsigned char mcp2515_modify_register(const unsigned char address, 
	const unsigned char mask, const unsigned char data)
{

   CS_OFF;
   delay_ms(1);

	write_data(MCP_BITMOD);
	write_data(address);
	write_data(mask);
	write_data(data);

		CS_ON;
    delay_ms(1);

	return 0;
}
/*---------------------------------------------------------------
NAME       : mcp2515_read_can_id(const unsigned char mcp_addr,
             const unsigned char* ext,const unsigned int* can_id)
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: 
CREATE DATE: 
LOGS       : 
        -----------------------------------------------------------------*/
 
unsigned char mcp2515_read_can_id( const unsigned char mcp_addr, 
	unsigned char* ext, unsigned int* can_id )
{
    unsigned char tbufdata[4];
		
    *ext = 0;
    *can_id = 0;
    
	mcp2515_read_registers( mcp_addr, tbufdata, 4 );
    
	*can_id = (tbufdata[0]<<3) + (tbufdata[1]>>5);
	
    // have no extend ID;
   return 0;
}
/*---------------------------------------------------------------
NAME       : mcp2515_read_can_msg()
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: 
CREATE DATE: 
LOGS       : 
-----------------------------------------------------------------*/
// Buffer can be MCP_RXBUF_0 or MCP_RXBUF_1
unsigned char mcp2515_read_can_msg( const unsigned char buffer_sidh_addr,
	CAN_MESSAGE* msg)
{

    unsigned char mcp_addr, ctrl;

	mcp_addr = buffer_sidh_addr;
	
    mcp2515_read_can_id( mcp_addr, &(msg->extended_identifier), 
		&(msg->identifier) );
    
	ctrl = mcp2515_read_register( mcp_addr-1 );
    msg->dlc = (mcp2515_read_register( mcp_addr+4 )&0x0f);
	

	if ((msg->dlc & 0x40) || (ctrl & 0x08)) {
        msg->rtr = 1;
    } else {
        msg->rtr = 0;
    }
	    msg->dlc &= 0x0F;	

     mcp2515_read_registers(mcp_addr+5,&(msg->dta[0]),msg->dlc) ;
   //msg->dta[0]=mcp2515_read_register( mcp_addr+5);
   //msg->dta[1]=mcp2515_read_register( mcp_addr+6);
   //msg->dta[2]=mcp2515_read_register( mcp_addr+7);
   //msg->dta[3]=mcp2515_read_register( mcp_addr+8);
   //msg->dta[4]=mcp2515_read_register( mcp_addr+9);
   //msg->dta[5]=mcp2515_read_register( mcp_addr+10);
   //msg->dta[6]=mcp2515_read_register( mcp_addr+11);
   //msg->dta[7]=mcp2515_read_register( mcp_addr+12);
	return 0;
}

 	 
/*---------------------------------------------------------------
NAME       : mcp2515_write_can_id(const unsigned char mcp_addr,
             const unsigned char ext,const unsigned char can_id)
ENTRY  TYPE: 
RETURN TYPE:
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: mcp_addr is the mcp2515 ID register,reg3-3 to 3-6;
              contain 31H...
             ext=1,there is extand ID use reg3-5 to 3-6;
			 can_id give the id to can msg,SID 11bit, extand SID 18bit;
CREATE DATE: 
LOGS       : 
        -----------------------------------------------------------------*/
unsigned char mcp2515_write_can_id( const unsigned char mcp_addr, 
	const unsigned char ext, const unsigned int can_id )   
{
   								 //can_id<	1FFFFFFF
         unsigned char tbufdata[4];
	
        tbufdata[0] = (unsigned char)(can_id>>3);
        tbufdata[1] = (unsigned char)(can_id<<5);
        tbufdata[2] = 0;
        tbufdata[3] = 0;	  

	mcp2515_set_registers( mcp_addr, tbufdata, 4 );	 //mcp_addr start from 31H ;

	return 0;
}

/*---------------------------------------------------------------
NAME       : mcp2515_read_can_msg()
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: 
CREATE DATE: 
LOGS       : 
-----------------------------------------------------------------*/   
// Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
unsigned char mcp2515_write_can_msg( const unsigned char buffer_sidh_addr, 
	const CAN_MESSAGE* msg)
{
    unsigned char mcp_addr, dlc;
//	unsigned char buf_dlc[10];

	mcp_addr = buffer_sidh_addr;   //id register=31H
	dlc = msg->dlc;

	 // write CAN id
    mcp2515_write_can_id( mcp_addr, msg->extended_identifier,msg->identifier );  

	mcp2515_set_register( (mcp_addr+4), (0x0F&dlc) );  // write the RTR and DLC	,RTR=0;


    mcp2515_set_registers((mcp_addr+5), &(msg->dta[0]), dlc );  // write data bytes
    

	return 0;
}

/*---------------------------------------------------------------
NAME       : mcp2515_get_free_txbuf()
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: 
CREATE DATE: 
LOGS       : 
-----------------------------------------------------------------*/  
//TXB0CTRL=30H, TXB1CTRL=31H,TXB2CTRL=32H;
unsigned char mcp2515_get_free_txbuf(unsigned char *txbuf_n)
{
	unsigned char res, i, ctrlval;
	unsigned char ctrlregs[3] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL };
	
	res = 2;			//all TXB is in busy ;
	*txbuf_n = 0x00;
	
	// check all 3 TX-Buffers
	for (i=0; i<3; i++) {
		ctrlval = mcp2515_read_register( ctrlregs[i] );
		if ( (ctrlval & 0x08) == 0 ) {
			*txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer
			res = 1;
			return res; // ! function exit 
		}
	}
	
	return res;
}

/*---------------------------------------------------------------
NAME       : mcp2515_init_can_buffers()
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 1.0.0
DESCRIPTION: 
CREATE DATE: 
LOGS       : 
-----------------------------------------------------------------*/	
unsigned char mcp2515_init_can_buffers(void)
{
	unsigned char i, a1, a2, a3;
	
	// TODO: check why this is needed to receive extended 
	//   and standard frames
	// Mark all filter bits as don't care:
    mcp2515_write_can_id(MCP_RXM0SIDH, 0, 0);
    mcp2515_write_can_id(MCP_RXM1SIDH, 0, 0);
    // Anyway, set all filters to 0:
    mcp2515_write_can_id(MCP_RXF0SIDH, 1, 0); // RXB0: extended 
    mcp2515_write_can_id(MCP_RXF1SIDH, 0, 0); //       AND standard
    mcp2515_write_can_id(MCP_RXF2SIDH, 1, 0); // RXB1: extended 
    mcp2515_write_can_id(MCP_RXF3SIDH, 0, 0); //       AND standard
    mcp2515_write_can_id(MCP_RXF4SIDH, 0, 0);
    mcp2515_write_can_id(MCP_RXF5SIDH, 0, 0);
	
	// Clear, deactivate the three transmit buffers
	// TXBnCTRL -> TXBnD7
    a1 = MCP_TXB0CTRL;
	a2 = MCP_TXB1CTRL;
	a3 = MCP_TXB2CTRL;
    for (i = 0; i < 14; i++) { // in-buffer loop
		mcp2515_set_register(a1, 0);
		mcp2515_set_register(a2, 0);
		mcp2515_set_register(a3, 0);
        a1++;
		a2++;
		a3++;
    }
	
    // and clear, deactivate the two receive buffers.
    mcp2515_set_register(MCP_RXB0CTRL, 0);
    mcp2515_set_register(MCP_RXB1CTRL, 0);

	return 0;
}

/*---------------------------------------------------------------
NAME       : 
ENTRY  TYPE: 
RETURN TYPE: 
PURPOSE    : 
VERSION    : 
DESCRIPTION: start the transmit;
CREATE DATE: 
LOGS       : 
-----------------------------------------------------------------*/	
unsigned char mcp2515_rts(void)
{  
    CS_OFF;
    delay_ms(1);

	write_data(0x81);
    
   	CS_ON;
	delay_ms(1);
	
	return 0;
}
   
 //Start the transmission from one of the tx buffers.

// Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
unsigned char mcp2515_start_transmit()
{
	// TXBnCTRL_addr = TXBnSIDH_addr - 1
    mcp2515_modify_register( 0x30 , 0x08, 0x08 );//modify the reg. TXBnCTRL.TXREQ=1,wait for data sending;
	
	return 0;
}			

//must be set in the setting mode;
unsigned char mcp2515_filter_intialize(void)
{
   //  unsigned char filter_buf[]={0x05,0x00,0,0};
	// unsigned char shield_buf[]={0x05,0x00,0,0};
	unsigned char buf[10];
  //control the shield register&filter register;
    // mcp2515_set_register(MCP_RXB0CTRL,0xf0);  //receive all message, 0x0f->0xff,enable the filter;
	// mcp2515_set_register(MCP_RXB1CTRL,0xf0); //RXB1CTRL;

	mcp2515_set_register(MCP_RXF0SIDH,0x05);   //ID=0x05 can be receive;
	mcp2515_set_register(MCP_RXF0SIDL,0x00);

	mcp2515_set_register(MCP_RXM0SIDH,0xFF);
	mcp2515_set_register(MCP_RXM0SIDL,0xE0);
	// mcp2515_set_registers(MCP_RXF0SIDH,filter_buf[0],4);
	// mcp2515_set_registers(MCP_RXM0SIDH,shield_buf[0],4);

   return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -