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

📄 mcp2510.c

📁 在移植成功ucos核的基础上扩充了该操作系统的许多没有功能。如文件系统
💻 C
📖 第 1 页 / 共 2 页
字号:
*	参数: 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 + -