📄 mcp2515.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 + -