📄 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 + -