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

📄 sja1000.c

📁 基于C51的现场总线CAN转串口RS232的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
				TX_Buff_Tail = 0;  // 指针循环
		} while((i<8) &&(TX_Buff_Head != TX_Buff_Tail));
		
		if ((CANConfig.Mode & 0x04) == 0)
		{//标准帧
			REG_RxBuffer0 = i;    
		}
		else
		{//扩展帧
			REG_RxBuffer0 = 0x80 + i;    	
		}
		
		REG_CMR = 0x01;         //发送命令 
	}
	
	ON_CAN_INT();

	return TRUE;

}





/*******************************************************************
 	 CAN初始化函数
参数:Mode:0:设置成basic模式  1:设置成PELICAN模式
返回: 初始化成功返回TRUE,否则FALSE
注:先调PeliCan,有时间再调BasicCan
*/
bit CAN_Init(void)
{
	unsigned char Temp,i;
	
	RESET_SJA1000();  //复位芯片

	//设置之前先进入复位模式



	/*00000001,进入复位模式, MOD |   |   |   |SM|AFM|STM|LOM|RM|
	SM: 睡眠模式   1 睡眠;没有CAN中断等待和总线活动时,CAN控制器进入睡眠模式	0 唤醒;从睡眠状态唤醒 
	AFM 验收滤波器模式   1 单;选择单个验收滤波器(32位长度)	0 双;选择两个验收滤波器(每个有16位激活)
	STM 自检测模式   1 自检测; 此模式可以检测所有节点,没有任何活动的节点使用自接收命令;即使没有应答,CAN控制器也会成功发送
			0 正常模式;成功发送时必需应答信号
	LOM 只听模式   1只听;这种模式中,即使成功接收信息,CAN控制器也不向总线发应答信号;错误计数器停止在当	0 正常模式
	RM 复位模式   1 复位;检测到复位模式位被置位,中止当前正在接收/发送的信息,进入复位模式
					0 正常;复位模式位接收到’1-0’的跳变后,CAN控制器回到工作模式   */

	i = 0;
	do {
		REG_MODE = 0x01; 
		Temp = REG_MODE;
		if ((Temp & 0x01) == 0x01)
		{
			break;  //成功进入复位模式
		}
		Delay(10);  //延时一定时间
		Temp = REG_MODE;
		if ((Temp & 0x01) == 0x01)
		{
			break;  //成功进入复位模式
		}
		i++;
	} while(i< 10);
	if (i > 9)
	{
		return FALSE;
	}
	/***至此芯片已经进入复位模式************/

	if((CANConfig.Mode & 0x01)  == CAN_MODE_BASICCAN)
	{//确保进入工作模式,确保的时候,加一个超时显示
			


       return TRUE;
	}
	else if ((CANConfig.Mode & 0x01)  == CAN_MODE_PELICAN)
	{

		REG_IR_ABLE = 0x00;  //禁止中断

		REG_BTR0 = CANConfig.BTR0;// 设置波特率
		REG_BTR1 = CANConfig.BTR1;// 设置波特率
		
		/*00011010, 输出控制寄存器OCR |OCTP1|OCTN1|OCPOL1|OCTP0|OCTN0|OCPOL0|OCMODE1|OCMODE0| 
		OCMODE1=1,OCMODE=0 正常工作模式   
		驱动  TXD  OCTPX   OCTNX  OCPOLX      TXX                            
		上拉   0     1       1       0        低   
		1     1       1       0        高
		*/
		REG_OCR = 0x1a;  
		//最高位是1,CAN 控制器工作于PeliCAN 模式.其它位暂不用管。
		REG_CDR = 0xc0;    //11000000 ,
		REG_RBSA = 0x00;   //硬件复位后就是0x00。

		REG_ACR0 = CANConfig.ACR0;//根据ID号设置。当与ID号相等,并且与相应的AMR位(相关的话,置0。不相关置1)或运算等于1,则接受。
		REG_ACR1 = CANConfig.ACR1;    //接收屏蔽寄存器AMR的作用应该是可以接收相似的来自不同ID的数据。
		REG_ACR2 = CANConfig.ACR2;
		REG_ACR3 = CANConfig.ACR3;
		
		REG_AMR0 = CANConfig.AMR0;
		REG_AMR1 = CANConfig.AMR1;
		REG_AMR2 = CANConfig.AMR2;
		REG_AMR3 = CANConfig.AMR3;

		if ((CANConfig.Mode & 0x02) == 0)  //设置滤波器的模式
		{
			REG_MODE = 0x0;
		}
		else
		{
			REG_MODE = 0x08;
		}
		

							 /*11111111, 中断使能寄存器IER  |BEIE|ALIE|EPIE |WUIE|DOIE|EIE|TIE|RIE|
							 BEIE 总线错误中断使能      1 使能;如果检测到总线错误,则CAN控制器请求相应的中断
							 0 禁能
							 ALIE 仲裁丢失中断使能      1 使能;如果CAN控制器已丢失了仲裁,则请求相应的中断
							 0 禁能
							 EPIE 错误消极中断使能      1 使能;若CAN控制器的错误状态改变(从消极到活动或反之), 则请求相应的中断
							 0 禁能
							 WUIE 唤醒中断使能          1 使能;如果睡眠模式中的CAN控制器被唤醒,则请求相应的中断
							 0 禁能
							 DOIE 数据溢出中断使能      1 使能;如果数据溢出状态位被置位,CAN控制器请求相应的中断
							 0 禁能
							 EIE 错误报警中断使能       1 使能;如果错误或总线状态改变,CAN控制器请求相应的中断
							 0 禁能
							 TIE 发送中断使能           1使能;当信息被成功发送或发送缓冲器又可访问(例如,中止发送命令后)时,CAN控制器请求相应的中断
							 0 禁能
							 RIE 接收中断使能           1 使能;当接收缓冲器状态是’满’时,CAN控制器请求相应的中断
														0 禁能                 */
		
		if ((CANConfig.Mode & 0x04) == 0)  //帧类型
		{//标准帧
			REG_RxBuffer0 = 0x00;
		}
		else
		{//扩展帧
			REG_RxBuffer0 = 0x80;
		}
		
		REG_RxBuffer1 = CANConfig.EFF0;//0xac;//TX 识别码1         
		REG_RxBuffer2 = CANConfig.EFF1;//0xff;//TX 识别码2
		REG_RxBuffer3 = CANConfig.EFF2;//0xff;//TX 识别码3
		REG_RxBuffer4 = CANConfig.EFF3;//0x00;//TX 识别码4   末三位不影响

		
	}


	//进入工作模式
	Temp = REG_MODE;
	if ((Temp & 0x01) !=0)
	{//没有进入工作模式
		return FALSE;
	}

	
	//打开中断
	REG_IR_ABLE = 0xff;   //中断使能置0xff
	ON_CAN_INT();         //打开CAN中断
	return TRUE;
	
}
/************************************************************************
         单片机初始化函数
参数:无
返回: 初始化成功返回TRUE.
注:

*/  
bit MCU_Init(void)
{


	
	TMOD = 0x20;     //定时器1,工作模式2(8位自动重装TL1<-TH1)
	TH1 = 0xfd;      //JJ:装入的初始值要计算。 波特率为9600。
	TL1 = 0xfd;       //     _______________________________
	TR1 = 1;          //TCON |TF1|TR1|TF0|TR0|   |   |  |  | 
	//     TR1或TR0为1,而GATE(TMOD.7)=0时,T1或T0计数.复位时TMOD和TCON的所有位均清0.
	//      _______________________________        
	SCON = 0x50;      //SCON: |SM0|SM1|SM2|REN|TB8|RB8|TI|RI|
	//      SM0=0,SM1=1 ,工作方式1,8位UART(异步收发),波特率:SMOD=0时,T1溢出率/32或SMOD=1时,T1溢出率/16.溢出率=1/溢出周期
	PCON = 0x00;      //当PCON = 0x80 时, SMOD=1 ,使串行口波特率加倍 。其它位不用管。
	//当PCON = 0x00 时,SMOD=0, 使串行口波特率不加倍。  
	PS = 1;
	//      _______________________________                   
	EA = 1;           //IE:   |EA|   |   |ES|ET1|EX1|ET0|EX0|                                                                                         ____  _____
	//EA:中断允许总控制位,EA=1,开。  ES,串口断允许位。ES = 1,开.   ET1或ET0,定时器/计时器T1或T0的溢出中断允许位。EX1或EX0,外部中断INT1或INT0的中断允许位
	ES = 1;
	return TRUE;

}

//---------------   串口中断服务函数   --------------------//
void UART_int(void) interrupt 4  using 1
{
	unsigned char Temp;

	if(RI)
	{ 
	    Temp = SBUF;
	    RI = 0;
	  // 数据存入接收缓冲区
		if( (UART_RX_Buff_Head == (UART_RX_Buff_Tail-1)) ||
		    ((UART_RX_Buff_Head == UART_RX_Buff_LEN-1) &&( UART_RX_Buff_Tail == 0) )) // 空了一个字节的位置
		{	// 数据满
			
		
		}
	 	else
		{
			UART_RX_Buff[UART_RX_Buff_Head] = Temp; 
	
			UART_RX_Buff_Head++;
			if(UART_RX_Buff_Head == UART_RX_Buff_LEN ) 
				UART_RX_Buff_Head = 0;  // 指针循环
		}
	}
	else if(TI)
	{
		TI = 0;
		if(UART_TX_Buff_Tail == UART_TX_Buff_Head) // 头、尾指针都为0,或相等时,数据为空
		{
			// Tx_Buff 空
			// Do Nothing!
		}
		else
		{
			SBUF = UART_TX_Buff[UART_TX_Buff_Tail];  // 先发送,再加指针。
			UART_TX_Buff_Tail++;
		}
		if(UART_TX_Buff_Tail == UART_TX_Buff_LEN) 
			UART_TX_Buff_Tail = 0; // 尾指针循环
	}


} 

/**************************************************************************
    中断服务函数
*/
void CAN_INT_Serverce(void) interrupt 0 using 2
{
	unsigned char Status,i;
	unsigned char xdata * p;

	
	Status=REG_IR;   //读中断寄存器的同时,使REG_IR为0x00,除了接收中断(若RXFIFO中还有数据)。

	//判断发送中断
	if ((Status&0x02) == 0x02)   //如果发送中断为1,
	{
		if(TX_Buff_Tail == TX_Buff_Head) // 头、尾指针都为0,或相等时,数据为空
		{
			//没有数据要发送了
		}
		else
		{
			p = (unsigned char xdata *)(SJA_REG_BaseADD + 0x15);
			i = REG_SR;

			if ((i & 0x04) == 0x04)
			{//发送缓冲区处于释放状态时,可以将部分数据发送出去
				i = 0;
				do {
					*p++ = TX_BUFF[TX_Buff_Tail++];
					i++;
					if(TX_Buff_Tail == TX_BUFF_LEN ) 
						TX_Buff_Tail = 0;  // 指针循环
				} while((i<8) &&(TX_Buff_Head != TX_Buff_Tail));
				
				if ((CANConfig.Mode & 0x04) == 0)
				{//标准帧
					REG_RxBuffer0 = i;    
				}
				else
				{//扩展帧
					REG_RxBuffer0 = 0x80 + i;    	
				}  
				REG_CMR = 0x01;         //发送命令 
			}

		}
	}
	//判断接受中断
	if ((Status&0x01) == 0x01)   //如果接收中断为1,
	{
		while(REG_Receive_Counter != 0)   //RX信息计数器(RMC)
		{
			p = (unsigned char xdata *)(SJA_REG_BaseADD + 0x15);
			i = REG_RxBuffer0 & 0x0f;
			do {
				RX_BUFF[RX_Buff_Head++] = *p++;
				i--;
				if(RX_Buff_Head == RX_BUFF_LEN ) 
					RX_Buff_Head = 0;  // 指针循环
				
				if( (RX_Buff_Head == (RX_Buff_Tail-1)) ||
					((RX_Buff_Head == RX_BUFF_LEN-1) &&( RX_Buff_Tail == 0) )) //
				{//接受缓冲区满了,丢掉后面的数据
					break;
				}
				
			} while(i);
			
			REG_CMR = 0x04;  //释放缓冲区
		}
		
	}
	
}


/**********************************************************************
		主函数
*/

void main(void)
{ 
	unsigned char i;
	
	unsigned char Buf[8];
	
	CANConfig.ACR0 = 0xac;
	CANConfig.ACR1 = 0xff;
	CANConfig.ACR2 = 0xff;
	CANConfig.ACR3 = 0xff;

	CANConfig.AMR0 = 0;
	CANConfig.AMR1 = 0xff;
	CANConfig.AMR2 = 0xff; 
	CANConfig.AMR3 = 0xff;
	
	CANConfig.BTR0 = 0x43;
	CANConfig.BTR1 = 0x2f;

	CANConfig.EFF0 =  0xac;
	CANConfig.EFF1 =  0xff;
	CANConfig.EFF2 =  0xff;
	CANConfig.EFF3 =  0xff; 
	
	CANConfig.Mode =  0x07;  //扩展帧 

	CAN_Init();         //初始化SJA1000
	MCU_Init();         //初始化单片机
	
	while(1)
	{
		/******************/
		


		//CAN_Send("Hello !",7);  //发送到串口
		//UART_Send("Hello !",7);  //发送到串口
		Delay(10000);
		/**************************/
		if((i = CAN_Read(Buf,8)) !=0)
		{	
			UART_Send(Buf,i);  //发送到串口
		}
		Delay(1000);
		if((i = UART_Read(Buf,8)) !=0)
		{	
			CAN_Send(Buf,i);  //发送到串口
		}
	};
}

⌨️ 快捷键说明

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