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

📄 can.c

📁 CAN通讯底层节点
💻 C
字号:
/*------------------------------------------------------------------------------
;CAN总线大坝监测系统
;底层节点
;文件名称: can.c
;函数功能:CAN总线通信
;MCU支持:  C8051F040
;上海富方软件合肥自动化分公司
;-----------------------------------------------------------------------------*/

#include "c8051F040.h"
#include "can.h"
#include "canreg.h"

#define CAN_ID 2



////////////////////////////////////////////////////////////////////////////////
// 清零所有消息对象
////////////////////////////////////////////////////////////////////////////////
void Clr_All_Msg_Obj (void){	
	unsigned char i;
   	SFRPAGE = CAN0_PAGE;

	CAN0ADR = IF1CMDMSK;       
	CAN0DATL = 0xF3;      
	// 写消息对象,Mask,Arb,Control改变
    CAN0ADR = IF1MSK1;     
    CAN0DAT = 0xFFFF;
    CAN0DAT = 0x7FFF;
	// Xtd不用,Dir滤波,所有ID或IDE位滤波
	CAN0DAT = 0x0000;
	CAN0DAT = 0x0000;     
    // 消息对象不可用,默认ID为0
	for (i = 1;i < 33;i++)
      {
		CAN0ADR = IF1CMDRQST;     
		CAN0DATL = i;
		// 应用到32个消息对象
      }   
}



////////////////////////////////////////////////////////////////////////////////
// 消息对象发送配置
////////////////////////////////////////////////////////////////////////////////
void Init_Msg_Obj_TX (unsigned char msg_num,unsigned int id){
	unsigned int temp_id;
  	SFRPAGE = CAN0_PAGE;

	CAN0ADR = IF1CMDMSK;
	CAN0DAT = 0x00b3; 
	// WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=0,TxRqst=0,DataA=1,DataB=1
	CAN0ADR = IF1ARB1;            
	CAN0DAT = 0x0000;  
	// ID15-0=0
	temp_id = id<<2;     
	// 标准id为ID28-ID18,则左移2位
	temp_id &=0x1ffc;
	temp_id |=0xa000;
	// IF1ARB2=101(id)00b,MsgVal=1,Xtd=0,标准模式,Dir=1,发送
	CAN0DAT = temp_id; 
	// 地址自增指向IF1ARB2
	CAN0DAT = 0x1088;
	// IF1MSGC=0x1088,NewDat=0,MsgLst=0,IntPnd=0,UMask=1,TxIE=0,RxIE=0,
	// RmtEn=0,TxRqst=0,EoB=1,DLC3-0=1000
	// 滤波使能,发送后IntPnd不变,远程禁止,长度为8的单块
	CAN0ADR = IF1CMDRQST;         
	CAN0DAT = msg_num;   
	// 应用到msg_num号消息
}



////////////////////////////////////////////////////////////////////////////////
// 消息对象接收配置
////////////////////////////////////////////////////////////////////////////////
void Init_Msg_Obj_RX (unsigned char msg_num,unsigned int id){
	unsigned int temp_id;
   	SFRPAGE = CAN0_PAGE;

	CAN0ADR = IF2CMDMSK; 
	CAN0DAT = 0x00bb;             
	// WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1
	CAN0ADR = IF2ARB1;           
	CAN0DAT = 0x0000; 
	temp_id = id<<2;
	temp_id &= 0x1ffc;
	temp_id |=0x8000;
	CAN0DAT = temp_id; 
	// IF1ARB2=100(id)00b,MsgVal=1,Xtd=0,标准模式,Dir=0,接收
	CAN0DAT = 0x1488;
	// NewDat=0,MsgLst=0,IntPnd=0,UMask=1,TxIE=0,RxIE=1,RmtEn=0,TxRqst=0
    // EoB=1,DLC3-0=1000,不是中断源,接收后IntPnd置1
	CAN0ADR = IF2CMDRQST;        
	CAN0DATL = msg_num;           
}



////////////////////////////////////////////////////////////////////////////////
// CAN发送数据动作
////////////////////////////////////////////////////////////////////////////////
void Can_Trans_Data (unsigned char msg_num){	
    unsigned char num;
   	SFRPAGE = CAN0_PAGE;
	
	CAN0ADR = IF1CMDMSK;          
	CAN0DAT = 0x0087;             
	// WR/RD=1,Mask=0,Arb=0,Control=0,ClrIntPnd=0,TxRqst=1,DataA=1,DataB=1
	CAN0ADR = IF1DATA1;           
	// 将8字节数据写入IF1DATA1
	for(num = 0;num < 8;num++){
		CAN0DATH = Can_sdata[num+1];
		CAN0DATL = Can_sdata[num];
		num++;
	}

    CAN0ADR = IF1CMDRQST;         
	CAN0DATL = msg_num;
	// 指向消息号 
}



////////////////////////////////////////////////////////////////////////////////
// CAN接收数据动作
////////////////////////////////////////////////////////////////////////////////
void Can_Rec_Data (unsigned char msg_num){
    unsigned char num;
   	SFRPAGE = CAN0_PAGE;

	CAN0ADR = IF2CMDMSK;       	
	CAN0DAT = 0x007f;          
	// WR/RD=0,Mask=1,Arb=1,Control=1,ClrIntPnd=1,NewDat=1,DataA=1,DataB=1
	CAN0ADR = IF2CMDRQST;      	
	CAN0DATL = msg_num;
	// 指向消息号    	   
	CAN0ADR = IF2DATA1;  

	for(num=0;num<8;num++){
	    Can_rdata[num+1] = CAN0DATH;
		Can_rdata[num] = CAN0DATL;
		num++;
	}

}



////////////////////////////////////////////////////////////////////////////////
// 主节点消息对象分别初始化,设置波特率,开启中断,并且启动CAN
////////////////////////////////////////////////////////////////////////////////
void Can_Msg_Init (void){
	SFRPAGE = CAN0_PAGE;

	CAN0CN = 0X01;
	// 初始化配置时将CAN挂起
	Clr_All_Msg_Obj();

	Init_Msg_Obj_RX(CAN_ID,CAN_ID);
	Init_Msg_Obj_RX(31,31);
	// 接收ID号
    Init_Msg_Obj_TX(32,32);
	// 发送ID号

	EIE2 |= 0x20;
	// 开启CAN中断
	SFRPAGE = CAN0_PAGE;

	CAN0CN |= 0X40;
	// CAN波特率配置可访问,
	CAN0ADR = BITREG;
	CAN0DAT = 0x7FFF;

	CAN0CN = 0x02;	
	// 自动重发开启,状态中断禁止,IE=1,CAN模块中断开启,Init清零.结束初始化操作,CAN控制器进入正常工作
}



////////////////////////////////////////////////////////////////////////////////
// CAN向上层回传数据
////////////////////////////////////////////////////////////////////////////////
void Can_Tx_Back(unsigned char Info_Data[6]){
        unsigned char i;

        Can_sdata[0] = Can_rdata[1];
		Can_sdata[1] = Can_rdata[2];

        for(i=0; i<6 ;i++){
			Can_sdata[i+2] = Info_Data[i];
		}

   		Can_Trans_Data(0x20);
}



////////////////////////////////////////////////////////////////////////////////
// CAN中断
////////////////////////////////////////////////////////////////////////////////
void CAN_ISR (void) interrupt 19 {
	SFRPAGE_SAVE = SFRPAGE;  
	SFRPAGE = CAN0_PAGE;

	/* 成功接收报文 */
	if ( CAN0STA & 0x10 ){
		CAN0STA &= 0xef;
	   
		CAN0ADR = INTPEND2;
		/* 广播 */
		if( CAN0DAT & 0x4000 )
	   		Can_Rec_Data(31);
		/* 非广播 */
	    else
			Can_Rec_Data(CAN_ID);

		Rec_From_CAN = 1;
	    // 标志成功收到下层信息
	} 

	SFRPAGE = SFRPAGE_SAVE;
}
		

⌨️ 快捷键说明

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