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

📄 lpc2300can.c

📁 lpc2368关于can模块的代码 对于从事此方面的兄弟有一定帮助
💻 C
字号:
/****************************************Copyright (c)**************************************************
***文件名称:CAN验收滤波测试程序
***作者:张利刚
***单位:中科院微系统所嘉兴分中心网络组
***时间:2008年7月17日
********************************************************************************************************/



#include    "LPC2300CAN.h"
extern MessageDetail MessageDetailT;
extern MessageDetail MessageCAN0;                        // 引用CAN0通道帧变量
extern MessageDetail MessageCAN1;                        // 引用CAN1通道帧变量


/*********************************************************************************************************
** 函数名称: void	enable_IRQ(void)
** 功能描述: 使能IRQ中断
** 输 入: 	无
** 输 出: 无
** 说明:系统必须处于特权模式
********************************************************************************************************/
static	__inline	void	Enable_IRQ(void)
{
	int	tmp;
	__asm
	{	
		MRS	tmp,CPSR
		BIC	tmp,tmp,#0x80
		MSR	CPSR_c,tmp
	}
}


/*
*********************************************************************************************************
**函数原型		:  	void INI_LED(void);
**参数说明		:  	无
**返回值		:	无
**说	明		:	初始化LED
*********************************************************************************************************/
void INI_LED(void)
{
	uint32 LED1 = 1 << 25;		// P1.25控制LED1
	uint32 LED2 = 1 << 26;		//P1.26控制LED2
	uint32 LED3 = 1 << 27;		// P1.25控制LED3
	uint32 LED4 = 1 << 28;		//P1.26控制LED4
	//LED
	PINSEL1 = 0x00000000;			// 所有管脚连接GPIO	
	IO1DIR  = LED1+LED2+LED3+LED4;				
}

/*
*********************************************************************************************************
**函数原型		:  	void OPEN_CLOSE_LED(unsigned int num);
**参数说明		:  	LED灯编号
**返回值		:	无
**说	明		:	LED灯的闪烁
*********************************************************************************************************/

void OPEN_CLOSE_LED(unsigned int num)
{	
	uint32 LED1 = 1 << 25;		// P1.25控制LED1
	uint32 LED2 = 1 << 26;		//P1.26控制LED2
	uint32 LED3 = 1 << 27;		// P1.25控制LED3
	uint32 LED4 = 1 << 28;		//P1.26控制LED4
	unsigned int loop;
	switch(num)
	{
		case 1:
			IO1SET |=LED1;
		for(loop=0;loop<100000;loop++)
			;
			IO1CLR |=LED1;
			break;
		case 2:
			//开和关LED2
		IO1SET |=LED2;
			for(loop=0;loop<100000;loop++)
				;
			IO1CLR |=LED2;
			break;
		case 3:
			//开和关LED3
			IO1SET |=LED3;
			for(loop=0;loop<100000;loop++)
				;
			IO1CLR |=LED3;
			break;
		case 4:
			//开和关LED4
			IO1SET |=LED4;
			for(loop=0;loop<100000;loop++)
				;
			IO1CLR |=LED4;
		break;
		default:
			break;
	}
	 
}



/*
*********************************************************************************************************
**函数原型		:  	unsigned char Enter_SWRst(unsigned char Ch);
**参数说明		:  	Ch:CAN控制器号,0表示第一路CAN
**返回值		:	0:失败
**				:	1: 成功	
**说	明		:	CAN控制器进入软件复位模式
*********************************************************************************************************/
unsigned char Enter_SWRst(unsigned char Ch)
{
	unsigned long regaddr;
	REG_CANMOD regmod;
	regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;			
	regmod.DWord = RGE(regaddr);		//读取CAN1MOD寄存器
	regmod.Bits.RM = 1;					//RM位置“1”
	RGE(regaddr) = regmod.DWord;		//回写CAN1MOD寄存器
	regmod.DWord = RGE(regaddr);		//验证写入值	
	return (0 != regmod.Bits.RM)? 1:0; 
}
/*
*********************************************************************************************************
**函数原型		:  	unsigned char Quit_SWRst(unsigned char Ch);
**参数说明		:  	Ch:CAN控制器号,0表示第一路CAN
**返回值		:	0:失败
**				:	1: 成功	
**说	明		:	CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char Quit_SWRst(unsigned char Ch)
{
	unsigned long regaddr;
	REG_CANMOD regmod;
	regaddr = (unsigned long)(&CAN1MOD)+Ch*CANOFFSET;			
	regmod.DWord = RGE(regaddr);		//读取CAN1MOD寄存器
	regmod.Bits.RM = 0;					//RM位置“0”
	RGE(regaddr) = regmod.DWord;		//回写CAN1MOD寄存器
	regmod.DWord = RGE(regaddr);		//验证写入值	
	return (0 != regmod.Bits.RM)? 0:1; 
}
/*
*********************************************************************************************************
**函数原型		:  	unsigned char CAN_Init(unsigned char Ch, unsigned long Baud);
**参数说明		:  	Ch:CAN控制器号,0表示第一路CAN
**				:	Baud:CAN波特率值
**返回值		:	无
**说	明		:	CAN控制器退出软件复位模式
*********************************************************************************************************/
unsigned char CAN_Init(unsigned char Ch, unsigned long Baud)
{
	unsigned long regaddr;
	switch(Ch)						//配置CAN控制器引脚
	{
		case 0:
		    PCONP |= 0x01L<<13;				//打开CAN1控制器电源
			PINSEL0 &= ~(0x03L<<0);/*RD1*/
			PINSEL0 |= (0x01L<<0);
			PINSEL0 &= ~(0x03L<<2);/*TD1*/
			PINSEL0 |= (0x01L<<2);
			break;
		case 1:
		    PCONP |= 0x01L<<14;				//打开CAN1控制器电源
			PINSEL0 &= ~(0x03L<<8);/*RD2*/
			PINSEL0 |= (0x02L<<8);
			PINSEL0 &= ~(0x03L<<10);/*TD2*/
			PINSEL0 |= (0x02L<<10);
			break;
		default:
			break;
	}
	Enter_SWRst(Ch);
	regaddr = (unsigned long)(&CAN1BTR)+Ch*CANOFFSET;
	RGE(regaddr) = Baud;
	
	
		
	if(Ch == 0)
	{
	    CAN1CMR |= (0x01<<2);		                 //释放接收缓冲区
	    CAN1ICR &= ~(0x01);
	    CAN1IER |= ((1<<0)|(1<<2));	 //使能CAN0接收与错误报警中断
	}
    else
    {
    	CAN2CMR |= (0x01<<2);
        CAN2ICR &= ~(0x01);
	    CAN2IER |= ((1<<0)|(1<<2));   //使能CAN1接收与错误报警中断
    }
	Quit_SWRst(Ch);
	
	/*初始化中断*/
	VICIntSelect &= (~(1<<23));                  //设置通道为IRQ中断
	*(volatile uint32 *)((&VICVectAddr0) + 23) =(uint32)CANIntPrg; //设置中断入口地址
	*(volatile uint32 *)((&VICVectPri0)  + 23) = 9;   //设置第23通道的中断优先级为9
	VICIntEnable |=(1<<23);	                     //使能CAN1/CAN2的中断向量
	
	//CAN_AFMR &= ~0x07;	                         //验收过滤设置为旁路模式
	//CAN_AFMR|=(1<<1);

	CAN_AFMR &= ~0x07;	                         //验收过滤设置为正常模式
	CAN_AFMR|=0x00;
	
    if((CAN_AFMR & 0x07) == 0x00)
    	return 1;
    else
    	return 0; 

}
/*
*********************************************************************************************************
**函数原型		:  	unsigned char CANRCV(unsigned char Ch, MessageDetail MessageCAN)
**参数说明		:  	
**输入变量      :   Ch:CAN控制器号,0表示第一路CAN
**				:	*MessageCAN: 存放CAN帧信息的结构体
**输出变量      :   *MessageCAN: 存放CAN帧信息的结构体
**返回值		:	无
**说	明		:	接受CAN帧放在指定的结构体中 
*********************************************************************************************************/
unsigned char CANRCV(unsigned char Ch, MessageDetail *MessageCAN)
{
   unsigned long mes;
   unsigned long regaddr;
   
   regaddr = (unsigned long)(&CAN1RFS)+Ch*CANOFFSET;				//处理DLC、RTR、FF
   mes = RGE(regaddr);
   MessageCAN->LEN =  (mes >>16) & 0x0F;                            //获取帧长度
   MessageCAN->FF  =  (mes >>31);                                   //获取FF
   
   regaddr = (unsigned long)(&CAN1RID)+Ch*CANOFFSET;				//处理ID
   mes = RGE(regaddr);
   if(MessageCAN->FF)												//FF为1,ID为29位
   {
		MessageCAN->CANID = mes & 0x1fffffff;
   }
   else                                                             //FF为0 ,ID为11位
   {	
		MessageCAN->CANID = mes & 0x000007ff;
   }
   
   regaddr = (unsigned long)(&CAN1RDA)+Ch*CANOFFSET;				//处理 数据A
   mes = RGE(regaddr);
   MessageCAN->DATAA = mes; 
   
   regaddr = (unsigned long)(&CAN1RDB)+Ch*CANOFFSET;				//处理 数据B
   mes = RGE(regaddr);
   MessageCAN->DATAB = mes;
   
   return(1);                                        
}


/*
*********************************************************************************************************
**函数原型		:  	unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data);
**参数说明		:  	LEN:数据长度
**				:	*data 发送数据所在的数组 
				:   
**返回值		:	操作成功返回 1 失败返回 0
**说	明		:	 用户填写发送 帧信息
*********************************************************************************************************/
  unsigned char writedetail(unsigned char LEN,unsigned char FF, unsigned int ID,unsigned char *data)
{
	unsigned char i;
	if(LEN>8)
	{
		return(0);
	}
	else
	{
		MessageDetailT.LEN=LEN;
		MessageDetailT.FF=FF;
		MessageDetailT.CANID=ID;
		MessageDetailT.DATAA=0;			//先清零
		MessageDetailT.DATAB=0;
	
		for(i=0;i<LEN;i++)
		{
			if(i<4)
			{
				MessageDetailT.DATAA |= (*(data+i)<<(i*8)); 
			}
			else
			{
				MessageDetailT.DATAB |= (*(data+i)<<((i-4)*8));
			}
		}
	//MessageDetailT.DATAB = ID;	
	return(1);
	}
}
/*
*********************************************************************************************************
**函数原型		:  	unsigned char CANSend(unsigned char Ch, unsigned char BUFNum);
**参数说明		:  	Ch:CAN控制器号,0表示第一路CAN
**				:	BUFNum 选择缓冲区
				:   MessageDetailT 报文的特征信息及数据
**返回值		:	无
**说	明		:	CAN发送帧
*********************************************************************************************************/
unsigned char CANSend(unsigned char Ch, unsigned char BUFNum)
{
	unsigned long CAN32reg;
	unsigned long regaddr;
	unsigned char FFflag;
	
	BUFNum-=1;		// 计算地址方便。
	
	
	regaddr = (unsigned long)(&CAN1TFI1)+Ch*CANOFFSET+BUFNum*0X10;	// 3缓冲区间地址差 0x10
	CAN32reg = RGE(regaddr);
	CAN32reg &= ~((0x0fL<<16) | (0x01L<<30) | (0x80000000));        //清 DLC,RTR.FF位?
	CAN32reg |= ((unsigned long)MessageDetailT.LEN<<16) | ((unsigned long)MessageDetailT.FF<<31);
	RGE(regaddr)=CAN32reg;
	
	FFflag = MessageDetailT.FF;
	
	regaddr = (unsigned long)(&CAN1TID1)+Ch*CANOFFSET+BUFNum*0X10;	//写帧ID
	CAN32reg = RGE(regaddr);
	if(FFflag)														//FF为1,ID为29位
	{
		CAN32reg &=0x70000000;
		CAN32reg |= (MessageDetailT.CANID & 0x1fffffff);
	}
	else
	{
		CAN32reg &= 0xfffff800;										//FF为0 ,ID为11位
		CAN32reg |= (MessageDetailT.CANID & 0x000007ff);
	}
	RGE(regaddr)=CAN32reg;
	
	regaddr = (unsigned long)(&CAN1TDA1)+Ch*CANOFFSET+BUFNum*0X10;	// 写帧数据A
	RGE(regaddr) = MessageDetailT.DATAA;
	
	regaddr = (unsigned long)(&CAN1TDB1)+Ch*CANOFFSET+BUFNum*0X10;	// 写帧数据B
	RGE(regaddr) = MessageDetailT.DATAB;
	
	regaddr = (unsigned long)(&CAN1CMR)+Ch*CANOFFSET;				//写控制寄存器,发送
	CAN32reg = RGE(regaddr);
	
	CAN32reg &= ~0x03;
	CAN32reg |= 0x03;
	CAN32reg &= ~((1<<5)|(1<<6)|(1<<7));
	switch(BUFNum)
	{
		case 0: CAN32reg |= 01<<5;break;
		case 1: CAN32reg |= 01<<6;break;
		case 2: CAN32reg |= 01<<7;break;
		default: break;
	}
	RGE(regaddr)=CAN32reg;
	
	OPEN_CLOSE_LED(2);
	
	regaddr = (unsigned long)(&CAN1GSR)+Ch*CANOFFSET;				//查询发送状态
	CAN32reg = RGE(regaddr);

	if(CAN32reg&(1<<3))			//所有的请求已成功完成
	{
		
		return(1);				//发送成功返回 1
	}	
	else { return (0);}			//发送失败返回 0 
	
}
/*
********************************************************************************************
**函数原型	:  	void	CANIntPrg(void)
**参数说明	:  	无
**返回值		:	无	
**说	明		:	CAN控制器中断处理函数
******************************************************************************************/
void	__irq CANIntPrg(void)
{
 	unsigned char j;
	unsigned int CAN32reg,mes;
	unsigned int regaddr;

	for(j=0;j<2;j++)				//最大CAN通道数为2,分别检测两个通道的中断 
	{
		regaddr = (unsigned long)(&CAN1ICR)+j*CANOFFSET;	
		CAN32reg=RGE(regaddr);	
		
		if((CAN32reg&(1<<0))!= 0)	//RI 接收中断
		{
			CAN32reg &= ~(0x01);
			RGE(regaddr) = CAN32reg;

            if(j==0)
            {
            	OPEN_CLOSE_LED(1);
			   CANRCV(j, &MessageCAN0);                      			//收到CAN0中断,接收帧
			   /* 填写发送帧*/
			   MessageDetailT.LEN=MessageCAN0.LEN;
		       MessageDetailT.FF=MessageCAN0.FF;
		       MessageDetailT.CANID=MessageCAN0.CANID;
		       MessageDetailT.DATAA=MessageCAN0.DATAA;			
		       MessageDetailT.DATAB=MessageCAN0.DATAB;
		       /* CAN0发送,以第一个缓冲区*/
			   CANSend(j, 1);
			
			   regaddr = (unsigned long)(&CAN1CMR)+j*CANOFFSET;				
			   mes=RGE(regaddr);
			   mes |= (1<<2);												//释放接收缓冲区
			   RGE(regaddr)=mes;
			}
			
			if(j==1)
            {
			   CANRCV(j, &MessageCAN1);                      			//收到CAN1中断,接收帧
			   /* 填写发送帧*/
			   MessageDetailT.LEN=MessageCAN1.LEN;
		       MessageDetailT.FF=MessageCAN1.FF;
		       MessageDetailT.CANID=MessageCAN1.CANID;
		       MessageDetailT.DATAA=MessageCAN1.DATAA;			
		       MessageDetailT.DATAB=MessageCAN1.DATAB;
		       /* CAN1发送,以第二个缓冲区*/
			   CANSend(j, 2);
			   regaddr = (unsigned long)(&CAN1CMR)+j*CANOFFSET;				
			   mes=RGE(regaddr);
			   mes |= (1<<2);												//释放接收缓冲区
			   RGE(regaddr)=mes;
			}
	
		}
		/* 根据需要添加
		if((CAN32reg&(1<<1))!= 0)	// TI1 第一发送缓冲区发送完成中断

		{
			;
		}
		if((CAN32reg&(1<<9))!= 0)	// TI2 第二发送缓冲区发送完成中断

		{
			;
		}
		if((CAN32reg&(1<<10))!= 0)	// TI3 第三发送缓冲区发送完成中断
		{
			;
		}
		*/
		if((CAN32reg&(1<<7))!= 0)	// BEI 总线错误中断
		{
			Enter_SWRst(j);
			regaddr = (unsigned long)(&CAN1GSR)+j*CANOFFSET;				
			mes=RGE(regaddr);
			mes &=0x00ff;												
			RGE(regaddr)=mes;	    //总线错误清除处理
			Quit_SWRst(j);
		}
		if((CAN32reg&(1<<6))!= 0)	// ALI 仲裁丢失中断
		{
			//添加用户代码
		}
		if((CAN32reg&(1<<3))!= 0)
		{
			//添加用户代码
			//ClrCanDataOver(j);	//释放接收缓冲区
		}
		
	}
		
	VICVectAddr = 0;	
}

⌨️ 快捷键说明

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