📄 mcp2510.c
字号:
* 参数: address为MCP2510寄存器地址*
* can_id为设置的ID值 *
* IsExt表示是否为扩展ID *
\*******************************************/
void MCP2510_Write_Can_ID(int address, U32 can_id, BOOL IsExt)
{
U32 tbufdata;
if (IsExt) {
can_id&=0x1fffffff; //29位
tbufdata=can_id &0xffff;
tbufdata<<=16;
tbufdata|=(can_id>>(18-5)&(~0x1f));
tbufdata |= TXB_EXIDE_M;
}
else{
can_id&=0x7ff; //11位
tbufdata= (can_id>>3)|((can_id&0x7)<<13);
}
MCP2510_Swrite(address, (unsigned char*)&tbufdata, 4);
}
// Setup the CAN buffers used by the application.
// We currently use only one for reception and one for transmission.
// It is possible to use several to get a simple form of queue.
//
// We setup the unit to receive all CAN messages.
// As we only have at most 4 different messages to receive, we could use the
// filters to select them for us.
//
// mcp_init() should already have been called.
void MCP2510_Setup(PCanFilter pfilter)
{
// As no filters are active, all messages will be stored in RXB0 only if
// no roll-over is active. We want to recieve all CAN messages (standard and extended)
// (RXM<1:0> = 11).
//SPI_mcp_write_bits(RXB0CTRL, RXB_RX_ANY, 0xFF);
//SPI_mcp_write_bits(RXB1CTRL, RXB_RX_ANY, 0xFF);
// But there is a bug in the chip, so we have to activate roll-over.
if(pfilter){ //有过滤器
MCP2510_WriteBits(RXB0CTRL, (RXB_BUKT|RXB_RX_STDEXT|RXB_RXRTR|RXB_RXF0), 0xFF);
MCP2510_WriteBits(RXB1CTRL, RXB_RX_STDEXT, 0xFF);
}
else{
MCP2510_WriteBits(RXB0CTRL, (RXB_BUKT|RXB_RX_ANY|RXB_RXRTR), 0xFF);
MCP2510_WriteBits(RXB1CTRL, RXB_RX_ANY, 0xFF);
}
}
//wait for tx buffers ready
int MCP2510_transmitWait(unsigned char address)
{
unsigned char result,i=0;
for(;;){
result=MCP2510_Read(address);
if((result&TXB_TXREQ_M)==0){
break;
}
if(result & (TXB_MLOA_M|TXB_TXERR_M)){
MCP2510_WriteBits(address, 0, TXB_TXREQ_M);
MCP2510_transmit(address);
i++;
if(i>3) return FALSE;
}
OSTimeDly(1);
}
}
/***********************************************************************************\
发送数据
参数:
data,发送数据
Note: 使用三个缓冲区循环发送,
2004-1-2 添加了做缓冲区有效检测,未测试
\***********************************************************************************/
int MCP2510_canWrite(PCanData data)
{
static int ntxbuffer=0;
switch(ntxbuffer){
case 0:
MCP2510_transmitWait(TXB0CTRL);
MCP2510_Write_Can(ntxbuffer, data);
MCP2510_transmit(TXB0CTRL);
ntxbuffer=1;
break;
case 1:
MCP2510_transmitWait(TXB1CTRL);
MCP2510_Write_Can(ntxbuffer, data);
MCP2510_transmit(TXB1CTRL);
ntxbuffer=2;
break;
case 2:
MCP2510_transmitWait(TXB2CTRL);
MCP2510_Write_Can(ntxbuffer, data);
MCP2510_transmit(TXB2CTRL);
ntxbuffer=0;
break;
}
return TRUE;
}
/***********************************************************************************\
中断服务程序
\***********************************************************************************/
void MCP2510_ISR()
{
/* U8 byte;
byte=MCP2510_Read(CANINTF);
if(byte & RX0INT){
MCP2510_Read_Can(3,&(MCP2510_Candata[nCanRevpos]));
MCP2510_WriteBits(CANINTF, ~RX0INT, RX0INT); // Clear interrupt
NextCanDataPos(nCanRevpos);
OSSemPost(CAN_Rev_Sem);
}
if(byte & RX1INT){
MCP2510_Read_Can(4,&(MCP2510_Candata[nCanRevpos]));
MCP2510_WriteBits(CANINTF, ~RX1INT, RX1INT); // Clear interrupt
NextCanDataPos(nCanRevpos);
OSSemPost(CAN_Rev_Sem);
}*/
U8 byte;
while((byte=MCP2510_Read(CANINTF)) & (RX0INT|RX1INT|ERRIE)){
if(byte &ERRIE)
{
Uart_Printf("ERRIE\n");
MCP2510_WriteBits(CANINTF, ~ERRIE,ERRIE); // Clear interrupt
}
if(byte & RX0INT){
MCP2510_Read_Can(3,&(MCP2510_Candata[nCanRevpos]));
MCP2510_WriteBits(CANINTF, ~RX0INT, RX0INT); // Clear interrupt
NextCanDataPos(nCanRevpos);
OSSemPost(CAN_Rev_Sem);
}
if(byte & RX1INT){
MCP2510_Read_Can(4,&(MCP2510_Candata[nCanRevpos]));
MCP2510_WriteBits(CANINTF, ~RX1INT, RX1INT); // Clear interrupt
NextCanDataPos(nCanRevpos);
OSSemPost(CAN_Rev_Sem);
}
}
// rEXTINPND=(1<<2); //clear Extint 6 bit
// rI_ISPC=BIT_EINT4567; //clear i_ispc
}
/*********************************************************************\
CAN设备初始化函数
参数: bandrate,CAN波特率
LoopBack,是否是LoopBack模式
pfilter,CAN过滤器结构体指针,
如果为NULL,则接受所有数据
\*********************************************************************/
int init_MCP2510(CanBandRate bandrate, BOOL LoopBack, PCanFilter pfilter)
{
unsigned char i,j,a;
MCP2510_Reset();
MCP2510_SetBandRate(bandrate,FALSE);
// Disable interrups.
MCP2510_Write(CANINTE, NO_IE);
if(!pfilter){
// Mark all filter bits as don't care:
MCP2510_Write_Can_ID(RXM0SIDH, 0, TRUE);
MCP2510_Write_Can_ID(RXM1SIDH, 0, TRUE);
// Anyway, set all filters to 0:
MCP2510_Write_Can_ID(RXF0SIDH, 0, 0);
MCP2510_Write_Can_ID(RXF1SIDH, 0, 0);
MCP2510_Write_Can_ID(RXF2SIDH, 0, 0);
MCP2510_Write_Can_ID(RXF3SIDH, 0, 0);
MCP2510_Write_Can_ID(RXF4SIDH, 0, 0);
MCP2510_Write_Can_ID(RXF5SIDH, 0, 0);
}
else{
// Mark
MCP2510_Write_Can_ID(RXM0SIDH, pfilter->Mask, TRUE);
MCP2510_Write_Can_ID(RXM1SIDH, pfilter->Mask, TRUE);
// set all filters to same = pfilter->Filter:
MCP2510_Write_Can_ID(RXF0SIDH, pfilter->Filter, pfilter->IsExt);
MCP2510_Write_Can_ID(RXF1SIDH, pfilter->Filter, pfilter->IsExt);
MCP2510_Write_Can_ID(RXF2SIDH, pfilter->Filter, pfilter->IsExt);
MCP2510_Write_Can_ID(RXF3SIDH, pfilter->Filter, pfilter->IsExt);
MCP2510_Write_Can_ID(RXF4SIDH, pfilter->Filter, pfilter->IsExt);
MCP2510_Write_Can_ID(RXF5SIDH, pfilter->Filter, pfilter->IsExt);
}
//Enable clock output
if(LoopBack)
MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLKEN | CLK1);
else
MCP2510_Write(CLKCTRL, MODE_NORMAL| CLKEN | CLK1);
// Clear, deactivate the three transmit buffers
a = TXB0CTRL;
for (i = 0; i < 3; i++) {
for (j = 0; j < 14; j++) {
MCP2510_Write(a, 0);
a++;
}
a += 2; // We did not clear CANSTAT or CANCTRL
}
// and the two receive buffers.
MCP2510_Write(RXB0CTRL, 0);
MCP2510_Write(RXB1CTRL, 0);
// The two pins RX0BF and RX1BF are used to control two LEDs; set them as outputs and set them as 00.
MCP2510_Write(BFPCTRL, 0x3C);
//Open Interrupt
MCP2510_Write(CANINTE, RX0IE|RX1IE);
MCP2510_Setup(pfilter);
return TRUE;
}
void MCP2510_CanOpen()
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
INT8U err;
U32 temp;
OS_ENTER_CRITICAL();
SetISR_Interrupt(EINT4567_OFFSET, MCP2510_ISR,EINT6_OFFSET);
/* temp=rINTMSK;
rINTMSK=0xffffffff;
rI_ISPC=BIT_EINT4567;
rINTMSK=(~BIT_EINT4567)&temp;*/
if(CAN_Rev_Sem)
OSSemDel(CAN_Rev_Sem, OS_DEL_ALWAYS, &err);
CAN_Rev_Sem=OSSemCreate(0);
OS_EXIT_CRITICAL();
}
void MCP2510_CanClose()
{
// Disable interrups.
MCP2510_Write(CANINTE, NO_IE);
MCP2510_Write(CLKCTRL, MODE_LOOPBACK);
}
BOOL MCP2510_canRead(PCanData data, int ntimeout)
{
INT8U err;
OSSemPend(CAN_Rev_Sem, ntimeout, &err);
if(err==OS_TIMEOUT)
return FALSE;
memcpy(data, &(MCP2510_Candata[nCanReadpos]),sizeof(CanData));
NextCanDataPos(nCanReadpos);
return TRUE;
}
BOOL MCP2510_canFlushInput()
{
static CanData data;
U8 byte;
//Close Interrupt
MCP2510_Write(CANINTE, NO_IE);
byte=MCP2510_Read(CANINTF);
MCP2510_WriteBits(CANINTF, ~(RX0INT|RX1INT), RX0INT|RX1INT); // Clear interrupt
while(MCP2510_canRead(&data,1));
//Open Interrupt
MCP2510_Write(CANINTE, RX0IE|RX1IE);
return TRUE;
}
can_driver_t mpc2510_can_driver = {
init_MCP2510,
MCP2510_CanOpen,
MCP2510_CanClose,
MCP2510_canRead,
MCP2510_canWrite,
MCP2510_canFlushInput,
NULL
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -