📄 mcp2510.c
字号:
/*
** Copyright (C)1999 KVASER AB, http://www.kvaser.com
** This code may be freely distrubuted and used if the source is indicated.
**
** Description:
** Contains routines for handling the MCP2510 CAN controller.
** Uses the SPI bus routines found in another file.
*/
#include <stdio.h>
#include <conio.h>
// #undefine uchar
#include "..\inc\std.h"
#include "..\inc\spi.h"
#include "..\inc\spi_mcp.h"
#include "..\inc\mcp2510.h"
// #include "..\inc\mcp2510t.h"
void mcp_reset(void)
{
SPI_mcp_reset();
}
/*
** Read one or more registers in the MCP2510, starting at address
** readdata.
*/
void mcp_read( uchar MCPaddr, uchar* readdata, uchar length )
{
uchar loopCnt;
SPI_mcp_select(); // Select the MCP device at the SPI bus
// Start reading and set first address
SPI_mcp_RD_address(MCPaddr);
for (loopCnt=0; loopCnt < length; loopCnt++) {
// Get a byte and store at pointer
*readdata = SPI_putch(MCPaddr);
// Increment the pointers to next location
// Test++;
MCPaddr++;
readdata++;
}
SPI_mcp_unselect();
}
/*
** Write to one or more registers in the MCP2510, starting at address
** writedata.
*/
void mcp_write( uchar MCPaddr, const uchar* writedata, uchar length )
{
uchar loopCnt;
SPI_mcp_select();
// Start write and set first address
SPI_mcp_WR_address( MCPaddr );
for (loopCnt=0; loopCnt < length; loopCnt++) {
// Write a byte
SPI_putch( *writedata );
// Increment the pointer to next location
writedata++;
}
SPI_mcp_unselect();
}
void mcp_read_can_id( uchar mcp_addr, uchar* ext, unsigned long* can_id )
{
uchar tbufdata[4];
*ext = 0;
*can_id = 0;
mcp_read( mcp_addr, tbufdata, 4);
*can_id = (tbufdata[SIDH]<<3) + (tbufdata[SIDL]>>5);
if ( (tbufdata[SIDL] & TXB_EXIDE_M) == TXB_EXIDE_M ) {
*can_id = (*can_id<<2) + (tbufdata[SIDL] & 0x03);
*can_id <<= 16;
*can_id = *can_id +(tbufdata[EID8]<<8) + tbufdata[EID0];
*ext = 1;
}
}
// Buffer can be 4..5
void mcp_read_can( uchar buffer, uchar* ext, unsigned long* can_id,
uchar* dlc, uchar* rtr, uchar* data )
{
uchar mcp_addr = buffer*16 + 0x21, ctrl;
mcp_read_can_id( mcp_addr, ext, can_id );
mcp_read( mcp_addr-1, &ctrl, 1 );
mcp_read( mcp_addr+4, dlc, 1 );
if (/*(*dlc & RTR_MASK) || */(ctrl & 0x08)) {
*rtr = 1;
} else {
*rtr = 0;
}
*dlc &= DLC_MASK;
mcp_read( mcp_addr+5, data, *dlc );
}
void mcp_write_can( uchar buffer, uchar ext, unsigned long can_id,
uchar dlc, uchar rtr, const uchar* data )
{
uchar mcp_addr = buffer*16 + 0x21;
mcp_write(mcp_addr+5, data, dlc ); // write data bytes
mcp_write_can_id( mcp_addr, ext, can_id ); // write CAN id
if ( rtr == 1) dlc |= RTR_MASK; // if RTR set bit in byte
mcp_write((mcp_addr+4), &dlc, 1 ); // write the RTR and DLC
}
void mcp_write_can_id( uchar mcp_addr, uchar ext, unsigned long can_id )
{
unsigned int canid;
uchar tbufdata[4];
canid = (unsigned int)(can_id & 0x0FFFF);
if ( ext == 1) {
tbufdata[EID0] = (uchar) (canid & 0xFF);
tbufdata[EID8] = (uchar) (canid / 256);
canid = (unsigned int)( can_id / 0x10000L );
tbufdata[SIDL] = (uchar) (canid & 0x03);
tbufdata[SIDL] += (uchar) ((canid & 0x1C )*8);
tbufdata[SIDL] |= TXB_EXIDE_M;
tbufdata[SIDH] = (uchar) (canid / 32 );
}
else {
tbufdata[SIDH] = (uchar) (canid / 8 );
tbufdata[SIDL] = (uchar) ((canid & 0x07 )*32);
tbufdata[EID0] = 0;
tbufdata[EID8] = 0;
}
mcp_write( mcp_addr, tbufdata, 4 );
}
/*
** Start the transmission from one of the tx buffers.
*/
void mcp_transmit(uchar mcp_addr)
{
SPI_mcp_write_bits(mcp_addr, TXB_TXREQ_M, TXB_TXREQ_M);
// uchar data;
// mcp_read( mcp_addr, &data, 1);
// data |= TXB_TXREQ_M;
// mcp_write( mcp_addr, &data, 1);
}
/*
** Initialize the MCP2510.
*/
void mcp_init(void)
{
uchar data;
uchar i,j,a;
data = MODE_CONFIG;
// Go into configuration mode
mcp_write(CANCTRL, &data, 1);
//
// Bit rate calculations.
//
// In this case, we'll use a speed of 125 kbit/s.
// If we set the length of the propagation segment to 7 bit time quanta,
// and we set both the phase segments to 4 quanta each,
// one bit will be 1+7+4+4 = 16 quanta in length.
//
// If you have a 4 MHz clock, setting the prescaler (BRP) to 1
// gives a bit length of 16 * 0.5 us = 8 us => 125 kbit/s.
//
// If you have a 16 MHz clock, setting the prescaler (BRP) to 4
// gives the same result.
//
data = SJW1 + BRP4;
mcp_write(CNF1, &data, 1);
data=(BTLMODE_CNF3+SEG4*8+SEG7); // Phase Seg 1 = 4, Prop Seg = 7
mcp_write(CNF2, &data, 1);
data = SEG4; // Phase Seg 2 = 4
mcp_write(CNF3, &data, 1);
// Disable interrups.
data = NO_IE;
mcp_write(CANINTE, &data, 1);
// Mark all filter bits as don't care:
mcp_write_can_id(RXM0SIDH, 1, 0);
mcp_write_can_id(RXM1SIDH, 1, 0);
// Anyway, set all filters to 0:
mcp_write_can_id(RXF0SIDH, 0, 0);
mcp_write_can_id(RXF1SIDH, 0, 0);
mcp_write_can_id(RXF2SIDH, 0, 0);
mcp_write_can_id(RXF3SIDH, 0, 0);
mcp_write_can_id(RXF4SIDH, 0, 0);
mcp_write_can_id(RXF5SIDH, 0, 0);
data = MODE_NORMAL + CLKEN + CLK1;
mcp_write(CLKCTRL, &data, 1);
// Clear, deactivate the three transmit buffers
data = 0;
a = TXB0CTRL;
for (i = 0; i < 3; i++) {
for (j = 0; j < 14; j++) {
mcp_write(a, &data, 1);
a++;
}
a += 2; // We did not clear CANSTAT or CANCTRL
}
// and the two receive buffers.
mcp_write(RXB0CTRL, &data, 1);
mcp_write(RXB1CTRL, &data, 1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -