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

📄 can.c.bak

📁 ARM9200的can驱动原程序
💻 BAK
字号:
/*****************************************************************************
;Institue of Automation, Chinese Academy of Sciences
;Beijing Hengyi Embedded System Co.,Ltd (www.hyesco.com)
;File Name:		
;Description:   source for can sja1000
;Date:			2006-03-15		
;Author:		Wujh origin from jzm
;E_mail:		wujh@hyesco.com
*****************************************************************************/
#include "can.h"
#include <stdlib.h>
#include <string.h>

extern void AT91F_DBGU_Printk(char *buf,...);

//发送缓存,接受缓存
unsigned char TXdata[12]={3,4,5,6,7,8,9,10,11,12,13,14};
unsigned char RXdata[100];

unsigned char bNewData=0;//接收到新的数据
unsigned char NewDataLength=0;//接收到新的数据长度
unsigned char NewDataMode=0;//接收到新的数据格式

//定义了16M晶体下,波特率预设值
unsigned char SJA_BTR_CODETAB[]={
    0x18,0x1C,		               //;20KBPS的预设值
    0x87,0xFF,                     //;40KBPS的预设值
    0x09,0x1C,                     //;50KBPS的预设值
    0x83,0xFF,                     //;80KBPS的预设值
    0x04,0x1C,                     //;100KBPS的预设值
    0x03,0x1c,                     //;125KBPS的预设值
    0X81,0xfa,                     //;200KBPS的预设值
    0x01,0x1c,                     //;250KBPS的预设值  
    0x80,0xfa,		               //;400KBPS的预设值
    0x00,0x1c,                     //;500KBPS的预设值
    0x80,0xb6,                     //;666KBPS的预设值
    0x00,0x16,                     //;800KBPS的预设值
    0x00,0x14,                     //;1000KBPS的预设值   
};

#define  BTR_INDEX           0

//延时函数
void Delay(char x,char y)
{
    char z;
    
    do {
    z=y;
    do {; } while(--z);
    }while(--x);
    
}

//写can寄存器
void Write_CAN_REG(unsigned char can_reg_addr, 	unsigned char data)
{


	WRITE_CAN_ADDR(can_reg_addr);//写寄存器抵制
	WRITE_CAN_DATA(data);//写数据
	
}

//读CAN寄存器
unsigned char Read_CAN_REG(unsigned char can_reg_addr)
{
	unsigned char data;

	WRITE_CAN_ADDR(can_reg_addr);//写寄存器抵制
	data=READ_CAN_REG();

	return data;	
	
}

//初始化can
/*
初始化程序主要完成以下寄存器的设计:
(1)通过对SJA1000的时钟分频寄存器定义,判断是使用BassicCAN模式还是使用PeliCAN模式;
是否使能CLOCKOUT及输出时钟频率;是否使用旁路CAN输入比较器;
TX1输出是否采用专门的接收中断。
(2)通过写验收码寄存器和验收屏蔽寄存器定义接收报文的验收码,
以及对报文和验收码进行比较的相关位定义验收屏蔽码。
(3)通过写总线定时寄存器定义总线的位速率、位周期内的采样点和一个位周期内的采样数量。
(4)通过写输出寄存器定义CAN总线输出管脚TX0、TX1的输出模式和输出配置。
(5)清除SJA1000的复位请求标志,进入正常工作模式,这样SJA1000方可进行报文的发送和接收。
*/
unsigned char Init_CAN(void)
{
	unsigned char reg;
	int i;
	unsigned char ucFlag;

	
	//检测sja1000存在
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_TEST,0x5a);
		reg=Read_CAN_REG(CAN_REG_TEST);
		if(reg==0x5a)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_NO_CAN;//没有找到sja1000



	//初始化模式寄存器进入复位模式,选择单滤波方式
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_MOD,0x01);
		reg=Read_CAN_REG(CAN_REG_MOD);
		if(reg	& 0x01)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_RESET;//进入复位状态

	
	
	//设置总线控制,btr0
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_BTR0,SJA_BTR_CODETAB[BTR_INDEX]);//设置波特率,现在设置成20kbps
		reg=Read_CAN_REG(CAN_REG_BTR0);
		if(reg==SJA_BTR_CODETAB[BTR_INDEX])
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_BTR;
	
	//btr1
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_BTR1,SJA_BTR_CODETAB[BTR_INDEX+1]);
		reg=Read_CAN_REG(CAN_REG_BTR1);
		if(reg==SJA_BTR_CODETAB[BTR_INDEX+1])
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_BTR;//错误返回错误代码


	//设置输出控制
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_OCR,PARAM_OCR);//设置成正常模式,0xda
		reg=Read_CAN_REG(CAN_REG_OCR);
		if(reg==PARAM_OCR)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_OCR;

	//时钟分频器
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_CDR,PARAM_CDR);//设置成pelican模式,cbp=1,关闭时钟输出
		reg=Read_CAN_REG(CAN_REG_CDR);
		if(reg==PARAM_CDR)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_CDR;



	//接收错误计数器清零
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_RXERR,0x00);
		reg=Read_CAN_REG(CAN_REG_RXERR);
		if(reg==0x00)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_RXERR;

	//发送错误计数器清零
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_TXERR,0x00);
		reg=Read_CAN_REG(CAN_REG_TXERR);
		if(reg==0x00)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_TXERR;
	
	
	//初始化接收代码寄存器	0x0000
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_ACR0,PARAM_ACR0);
		reg=Read_CAN_REG(CAN_REG_ACR0);
		if(reg==PARAM_ACR0)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_ACR;


	//ACR1
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_ACR1,PARAM_ACR1);
		reg=Read_CAN_REG(CAN_REG_ACR1);
		if(reg==PARAM_ACR1)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_ACR;

	//ACR2
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_ACR2,PARAM_ACR2);
		reg=Read_CAN_REG(CAN_REG_ACR2);
		if(reg==PARAM_ACR2)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_ACR;
	//ACR3
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_ACR3,PARAM_ACR3);
		reg=Read_CAN_REG(CAN_REG_ACR3);
		if(reg==PARAM_ACR3)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_ACR;

	//验收屏蔽,0xffff
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_AMR0,PARAM_AMR0);
		reg=Read_CAN_REG(CAN_REG_AMR0);
		if(reg==PARAM_AMR0)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_AMR;
	//AMR1	
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_AMR1,PARAM_AMR1);
		reg=Read_CAN_REG(CAN_REG_AMR1);
		if(reg==PARAM_AMR1)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
	return ERROR_AMR;	
	
	//AMR2
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_AMR2,PARAM_AMR2);
		reg=Read_CAN_REG(CAN_REG_AMR2);
		if(reg==PARAM_AMR2)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_AMR;	

	//AMR3
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_AMR3,PARAM_AMR3);
		reg=Read_CAN_REG(CAN_REG_AMR3);
		if(reg==PARAM_AMR3)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_AMR;	
	
	//中断
	//中断使能寄存器
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_IER,PARAM_IER);
		reg=Read_CAN_REG(CAN_REG_IER);
		if(reg==PARAM_IER)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_IER;	
	
	//接收缓存器起始地址设为0
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_RBSA,PARAM_RBSA);
		reg=Read_CAN_REG(CAN_REG_RBSA);
		if(reg==PARAM_RBSA)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_RBSA;			
	
	//返回工作模式,选择单滤波模式,
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_MOD,PARAM_RET_MOD);
		reg=Read_CAN_REG(CAN_REG_MOD);
		if((reg & 0x09)==0x08)
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return ERROR_MOD;	

	return 0;
}


//发送数据
int CAN_TRANSMIT(void)
{
	unsigned char reg;
	unsigned char ucFlag;//错误标志位
	int i;
	unsigned char ucRegTXSFF;

	//发送缓存器锁定否
	ucFlag=1;
	for(i=0;i<REPEART_TIMES;i++)
	{
		reg=Read_CAN_REG(CAN_REG_SR);
		if((reg==0x0c))
		{
			ucFlag=0;
			break;
		}
	}
	if(ucFlag)
		return STATUS_TBS;
			
#ifndef SEND_EFF_DATA
	//写TX桢信息SFF
	ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_SFF;
	Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//发送数据,数据长度8,标准桢格式

	//写TX桢信息id0和id1
	Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//发送数据识别码
	Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//发送数据识别码
	//填写发送数据缓存
	for(i=0;i<8;i++)
	Write_CAN_REG((CAN_REG_TX_SFF_BUFFER+i),TXdata[i]);//包头
#else
	//写TX桢信息SFF
	ucRegTXSFF=PARAM_DATA_LENGTH | PARAM_TX_FF_EFF;
	Write_CAN_REG(CAN_REG_TX_SFF,ucRegTXSFF);//发送数据,数据长度8,EFF桢格式

	//写TX桢信息id0和id1
	Write_CAN_REG(CAN_REG_TX_ID0,PARAM_TX_ID0);//发送数据识别码
	Write_CAN_REG(CAN_REG_TX_ID1,PARAM_TX_ID1);//发送数据识别码
	Write_CAN_REG(CAN_REG_TX_ID2,PARAM_TX_ID2);//发送数据识别码
	Write_CAN_REG(CAN_REG_TX_ID3,PARAM_TX_ID3);//发送数据识别码
	//填写发送数据缓存
	for(i=0;i<8;i++)
	Write_CAN_REG((CAN_REG_TX_EFF_BUFFER+i),TXdata[i]);//包头

#endif
	//发送数据
	Write_CAN_REG(CAN_REG_CMR,0x01);//正常发送数据
	
	//判断发送数据失败
	ucFlag=1;
	for(i=0;i<REPEART_TIMES*10;i++)
	{
		reg=Read_CAN_REG(CAN_REG_SR);
		if((reg & 0x08))
		{
			ucFlag=0;
			break;
		}
		Delay(200,200);
	}
	if(ucFlag)
		return STATUS_TCS;

	return 0;
	
}


//CAN接收数据
//can中断分发向量函数
void Eint2CanInt(void)
{
         unsigned char reg,i;
         
    	//重新打开中断
    	//ClearPending(BIT_EINT2);
    
    	//访问地址指向状态寄存器,判断FIFO中的数据有没有,其实在查询的时候需要,在中断的时候
    	//不需要
    	/*
    	reg=Read_CAN_REG(CAN_REG_SR);//            
   	if((reg&0x01)==0)              	 //判断报文是否有效
   	{
      		exit(0);//
  	}*/
   
   	//读出中断状态寄存器内容,判断当前是那种中断发生,并转到响应的中断处理
   	//当然必须在初始化过程中将相应的中断屏蔽位打开了。
   	reg=Read_CAN_REG(CAN_REG_IR);//读出中断状态寄存器内容
   	switch(reg)
   	{
   		//置位;当CAN控制器检测到总线错误且中断使能寄存器中的BEIE被置位时此位被置位
   		case 0x80:
   			break;//自己添加处理程序了
   		//置位;当CAN控制器丢失仲裁,变为接收器和中断使能寄存器的ALIE为被置位时,此位被置位
   		case 0x40:
   			break;//自己添加处理程序了
   		//置位;当CAN控制器到达错误消极状态(至少一个错误计数器超过协议规定的值127)或从错误消极状态又进入错误活动状态以及中断
		//寄存器的EPIE位被置位时此位被置1
   		case 0x20:
   			break;//自己添加处理程序了
   		//置位;当CAN控制器在睡眠模式中检测到总线的活动且中断寄存器的WUIE位被置1时此位被置位
   		case 0x10:
   			break;//自己添加处理程序了
   		//置位;数据溢出状态位有0-1 跳变且中断寄存器的DOIE位被置位时此位被置1
   		case 0x08:
   			break;//自己添加处理程序了
   		//置位;错误状态位和总线状态位的改变和中断寄存器的EIE位被置位时此位被置1
   		case 0x04:
   			break;//自己添加处理程序了
   		//置位;发送缓冲器状态从’0-1’(释放)跳变且中断寄存器的TIE位被置位时此位被置1
   		case 0x02:
   			break;//自己添加处理程序了
   		//置位;接收FIFO不空且中断寄存器的RIE位被置位时此位被置1
   		case 0x01:
   			CanIntReceiveData();
   			break;
   	}
   	
   	/*
   	for(i=0;i<REPEART_TIMES;i++)
	{
		Write_CAN_REG(CAN_REG_IER,PARAM_IER);
		reg=Read_CAN_REG(CAN_REG_IER);
		if(reg==PARAM_IER)
		{
			break;
		}
	}*/
    
}
//响应中断接受数据
void CanIntReceiveData(void)
{
	unsigned  char  TempCount; 
        unsigned char reg;
        unsigned char i;
   	//判断桢信息SFF,EFF OR SFF
   	reg=Read_CAN_REG(CAN_REG_RX_SFF);
   	if((reg&0x80)==0x80)//eff,桢
   	{
   		if((reg & 0x40)==0x40)//远程桢
    			TempCount=2;////远程桢
   		else
   			TempCount=(reg & 0x0f)+4;////计算报文中数据的个数
   		
   		for(i=0;i<TempCount;i++)
   			RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);	
   		Write_CAN_REG(CAN_REG_CMR,0x04);	
   		
   		
   		bNewData=1;	
   		NewDataMode=1;
   		NewDataLength=TempCount;
			
   		
   	}
   	else//sff桢
   	{
   		if((reg & 0x40)==0x40)//远程桢
    			TempCount=2;////远程桢
   		else
   			TempCount=(reg & 0x0f)+2;////计算报文中数据的个数
   		
   		
   			
   		for(i=0;i<TempCount;i++)
   			RXdata[i]=Read_CAN_REG(CAN_REG_RX_ID0+i);

   		
   		Write_CAN_REG(CAN_REG_CMR,0x04);
   			
   		bNewData=1;		
   		NewDataMode=0;
   		NewDataLength=TempCount;
   	}
  }

//不停发送数据主程序	
void CanSendData(void)
{
	int ret;

	ret=CAN_TRANSMIT();
	if(ret)
	{
		AT91F_DBGU_Printk("Can send data error,error id=%d!\n",ret);
	}
	else
	{
		AT91F_DBGU_Printk("Can send data success!\n");
	}	
	
}


//不停接收数据主程序
void CanReceiveData(void)
{
	unsigned char i;

	if(bNewData == 1)
	{
		bNewData=0;
		
		if(NewDataMode)
			AT91F_DBGU_Printk("EFF Data,Data Lenght=%d\n",NewDataLength);//数据格式和长度
		else
			AT91F_DBGU_Printk("SFF Data,Data Lenght=%d\n\r",NewDataLength);
			
		for(i=0;i<NewDataLength;i++)
			AT91F_DBGU_Printk("RXdata[%d]=0x%x\n\r",i,RXdata[i]);//输出数据
			
		NewDataLength=0;
		NewDataMode=0;	
	}
		
}

⌨️ 快捷键说明

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