//////////////////////////此为接收函数///////////////////////
两个板子之间相互通信。
自测试通信OK。
#include<c8051f040.h>
#include<can.h>
#include <intrins.h>
#define uchar unsigned char //宏定义 0-255
#define uint unsigned int //宏定义 0-65535
uchar ch; //串口接收变量
bit flag; //串口接收标志
uchar status; //状态
void PORT_Init();
void external_osc();
sbit switch1=P7^6;
sbit LED=P6^6;
bit RX_flag;
bit TX_flag;
bit eror_flag;
void clear_msg_objects();
void start_CAN();
void init_msg_object_TX (uchar MsgNum,uint id);
void init_msg_object_RX (uchar MsgNum,uchar id);
void transmit_message(uchar MsgNum);
void receive_data(uchar MsgNum);
uchar JJJ;
uint CAN_TX[8]={0,0,0,0,0,0,0,0};
uint CAN_RX[8]={0,0,0,0,0,0,0,0};
void delayms(uint x)
{
uint t;
while(x--)
{
for(t=0;t<110;t++);
}
}
void UART0_Init()
{
SFRPAGE = UART0_PAGE;
SCON0 = 0x50; //允许uart0,8位UART,可变波特率,UART接收允许,使能波特率二分频功能
}
void TIMER1_Init()
{
SFRPAGE = TIMER01_PAGE;
TCON = 0X50; //定时器1允许
TMOD = 0x21; //自动重装载8位定时计数器
CKCON = 0X18; //定时器1使用系统时钟
TH1 = 0xFD;
TL1 = 0xFD;
TR1=1;
}
void PORT_Init()
{
SFRPAGE=CONFIG_PAGE;
P6MDOUT=0Xff;
P7MDOUT=0Xff;
XBR3|=0X80;
XBR2= 0X40; //该处可设定弱上拉使能
XBR0= 0x05;
}
void external_osc(void)
{
uchar n;
SFRPAGE=CONFIG_PAGE;
OSCXCN|=0X77;
for(n=0;n<255;n++);
while((OSCXCN&0x80)==0);
CLKSEL|=0x01;
}
//-----------------------------------------------------------------------------
// 函数名:void clear_msg_objects(void)
// 功 能:清除消息对象
// 描 述:
//-----------------------------------------------------------------------------
void clear_msg_objects(void)
{
uchar i, IDL=4,j;
unsigned short data_temp=0x0101;
SFRPAGE=CAN0_PAGE;
CANINIT=1;
CAN0ADR=IF1CMDMSK; //命令掩码寄存器
CAN0DATL=0Xf3; //写数据
for(i=1;i<=8;i++) //i表示消息对象
{
CAN0ADR=IF1MSK1;
CAN0DATA=0X0000;
CAN0DATA=0X0000; //需要修改 IDE过滤
CAN0ADR=IF1ARB2;
CAN0DATH=0Xa0;
CAN0DATL=IDL;
IDL += 4;
CAN0DATA=0X0088; //IF1MSGC
CAN0ADR=IF1CMDRQST;
while((CAN0DATH & 0X80) == 1);
CAN0DATL=i;
}
IDL=0x04;
for(;i<=16;i++)
{
CAN0ADR=IF1MSK1;
CAN0DATA=0XFFFF;
CAN0DATA=0X1FFF; //需要修改 IDE过滤
CAN0ADR=IF1ARB2;
CAN0DATH=0XA0;
CAN0DATL=IDL;
IDL += 4;
CAN0DATA=0X1080; //可设定newdata引发intpnd
CAN0ADR=IF1CMDRQST;
while((CAN0DATH & 0X80) == 1);
CAN0DATL=i;
}
CANINIT=0;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0X87; //87 控制位等不改
for(i=1;i<=8;i++)
{
CAN0ADR=IF1DATA1;
for(j=1;j<=4;j++)
{
CAN0DATA=data_temp;
data_temp+=257;
}
CAN0ADR=IF1CMDRQST;
CAN0DATL=i; //这里发送
}
}
void init_msg_object_TX (uchar MsgNum,uint id)
{
uint tempreg;
SFRPAGE = CAN0_PAGE;
CAN0ADR = IF1CMDMSK; //指向命令掩码寄存器
CAN0DATA = 0x00b3; //设为写,改变所有的消息对象除了标识掩码位,将数据字节0-7发送到消息对象
/* IF1 Command Mask Registers =0x00b3
WR/RD=1,Mask=1,Arb=1,Control=1,ClrIntPnd=0,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据*/
CAN0ADR = IF1ARB1; //指向IF1仲裁寄存器1
CAN0DATA = 0x0000; //ID15-0:0000;将仲裁ID设为最高优先级
/*IF1 Arbitration Registers1 =0x0000,即ID15-0=0*/
tempreg=id<<2;//标准id为ID28-ID18,所以要左移2位
tempreg&=0x1fff;
tempreg|=0xa000;
CAN0DATA = tempreg; ////自动增加地址到IF1仲裁寄存器2
/*IF1 Arbitration Registers2=101(id)00b
MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=1,为发送*/
CAN0DATA = 0x0088; //IF1消息控制寄存器:DLC = 1,禁止远程桢
/*IF1 Message Control Registers=0x0088
NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=0,RmtEn=0,TxRqst=0
EoB=1,DLC3-0=1000,即数据长度为8*/
CAN0ADR = IF1CMDRQST; //指向IF1命令请求寄存器
CAN0DATL = MsgNum;
/*IF1 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息*/
}
void init_msg_object_RX (char MsgNum,uchar id)
{
uint temp;
SFRPAGE = CAN0_PAGE;
CAN0ADR = IF2CMDMSK;
CAN0DATA = 0x00bb;
/* IF2 Command Mask Registers =0x00bb
WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据*/
CAN0ADR = IF2ARB1; //指向IF2仲裁寄存器
CAN0DATA = 0x0000;
/*IF2 Arbitration Registers1 =0x0000,即ID15-0=0*/
temp=id<<2;//标准id为ID28-ID18,所以要左移2位
temp&=0x1fff;
temp|=0x8000;
CAN0DATA = temp;
/*IF2 Arbitration Registers2=100(id)00b
MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=0,为接收*/
CAN0DATA = 0x0488;
/*IF2 Message Control Registers=0x0488
NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=1,接收中断使能;RmtEn=0,TxRqst=0
EoB=1,DLC3-0=1000,即数据长度为8*/
CAN0ADR = IF2CMDRQST;
CAN0DATL = MsgNum;
/*IF2 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息*/
}
void start_CAN(){
SFRPAGE=CAN0_PAGE;
// CAN0CN|=0X00C1; // 开测试和bt设置
// CAN0CN&=0XFFd7; //自动重发开启 错误中断禁止
CAN0CN|=0X0041; //使能CCE和INIT位
// CAN0ADR=CANTSTR;
// CAN0DATL|=0X10;
CAN0ADR=BITREG;
CAN0DATA=0X2640;
CAN0ADR = IF1CMDMSK; //指向命令掩码寄存器1
CAN0DATA = 0x0087; //写:
//设置CAN RAM为写,写数据字节, //设置发送请求位
//将发送0---3发送到消息对象
//将发送4---7发送到消息对象
CAN0ADR = IF2CMDMSK; //指向命令掩码寄存器2(设置接收,读CAN_RAM,读数据字节)
CAN0DATL = 0x1f; //设置为接受
//掩码位不变
//仲裁位不变
//发送控制位到IFx消息缓冲寄存器
//清除消息对象中断挂起位
//清除消息对象中的NewData位
//将数据字节0---3字节发送到消息缓冲寄存器中
//将数据字节4---7字节发送到消息缓冲寄存器中
CAN0CN|=0X0006;
CAN0CN&=0XFFBE;
}
void transmit_message(uchar MsgNum)
{
// uchar i;
SFRPAGE=CAN0_PAGE; //指向CAN0页面
CAN0ADR=IF1CMDMSK; //向IF1命令屏蔽寄存器写入命令
CAN0DATL=0X0083;
CAN0ADR=IF1ARB2; //指向IF1仲裁寄存器2
CAN0DATH|=0x80;
CAN0ADR=IF1DATA1; //指向数据场的第一个字节
/* for(i=0;i<4;i++)
{
CAN0DATA=CAN_TX[i]; //将4字节数据写入发送缓冲器
}*/
CAN0DATL=0x22;
CAN0ADR=IF1CMDRQST;
CAN0DATL=MsgNum; //将报文对象编号写入,则数据发送到对应的报文对象中
}
void receive_data(uchar MsgNum)
{
// uchar i;
SFRPAGE=CAN0_PAGE; //指向CAN0页面
CAN0ADR=IF2CMDMSK; //向IF2命令屏蔽寄存器写命令
CAN0DATA=0x003F;
CAN0ADR=IF2CMDRQST; //将报文对象编号写入命令请求寄存器,对应地接收
CAN0DATL=MsgNum; //得到数据就从报文RAM中移到数据缓冲器中
CAN0ADR=IF2DATA1; //指向数据场的第一个字节
/* for(i=0;i<4;i++) //读取4个字节数据
{
CAN_RX[i]=CAN0DATA;
} */
JJJ=CAN0DATL;
}
void main()
{
WDTCN = 0xde;
WDTCN = 0xad;
SFRPAGE = CONFIG_PAGE;
PORT_Init();
external_osc();
clear_msg_objects();
init_msg_object_TX(0x02,5); //广播发送
start_CAN();
init_msg_object_RX(0x02,7);
// while(switch1==1);
UART0_Init(); //串口初始化
TIMER1_Init(); //定时器1初始化
RX_flag=0;
TX_flag=0;
eror_flag=0;
EIE2 = 0x20;//允许can0中断
EIP2 |= 0x20;
ES0=1;
EA = 1;
while(1)
{
receive_data(0x02);
if(RX_flag==1)
{
RX_flag=0;
LED=!LED;
delayms(500);
}
}
}
void inter_CAN(void) interrupt 19
{
SFRPAGE = CAN0_PAGE;
status = CAN0STA; //读状态寄存器
if ((status&0x10) != 0) //Rxok位为1,则是由于接收引起的中断
{
CAN0STA = (CAN0STA&0xEF)|0x07; //复位Txok,设置LEC无变化
RX_flag=1; //接受中断标志位置位
// receive_data (); // Up to now, we have only one RX message
}
if ((status&0x08) != 0) //Txok位为1,则是由于发送引起的中断
{
CAN0STA = (CAN0STA&0xF7)|0x07; //复位Txok,设置LEC无变化
TX_flag=1; //发送完成标志置位
}
if (((status&0x07) != 0)&&((status&0x07) != 7)) //错误中断,改变LEC
{
CAN0STA = CAN0STA|0x07; //设置LEC无变化
eror_flag=1;
}
}
void UART0_ISR(void) interrupt 4
{
if(RI0)
{
ch=SBUF0;
if(ch==0xaa)
{
flag=1;
}
RI0=0;
}
if(flag==1)
{
flag=0;
SBUF0=JJJ;
while(TI0==0);
TI0=0;
}
}
/////////////////////////////////////此为发送函数////////////////////////
#include<c8051f040.h>
#include<can.h>
#include <intrins.h>
#define uchar unsigned char //宏定义 0-255
#define uint unsigned int //宏定义 0-65535
uchar status; //状态
void PORT_Init();
void external_osc();
sbit switch1=P5^0;
sbit LED=P6^6;
bit RX_flag;
bit TX_flag;
bit eror_flag;
void clear_msg_objects();
void start_CAN();
void init_msg_object_TX (uchar MsgNum,uint id);
void init_msg_object_RX (uchar MsgNum,uchar id);
void transmit_message(uchar MsgNum);
void receive_data(uchar MsgNum);
uint CAN_TX[8]={0,0,0,0,0,0,0,0};
uint CAN_RX[8]={0,0,0,0,0,0,0,0};
void delayms(uint x)
{
uint t;
while(x--)
{
for(t=0;t<110;t++);
}
}
void PORT_Init()
{
SFRPAGE=CONFIG_PAGE;
P6MDOUT=0Xff;
P7MDOUT=0Xff;
XBR3|=0X80;
XBR2=0X40; //该处可设定弱上拉使能
}
void external_osc(void)
{
uchar n;
SFRPAGE=CONFIG_PAGE;
OSCXCN|=0X77;
for(n=0;n<255;n++);
while((OSCXCN&0x80)==0);
CLKSEL|=0x01;
}
//-----------------------------------------------------------------------------
// 函数名:void clear_msg_objects(void)
// 功 能:清除消息对象
// 描 述:
//-----------------------------------------------------------------------------
void clear_msg_objects(void)
{
uchar i, IDL=4,j;
unsigned short data_temp=0x0101;
SFRPAGE=CAN0_PAGE;
CANINIT=1;
CAN0ADR=IF1CMDMSK; //命令掩码寄存器
CAN0DATL=0Xf3; //写数据
for(i=1;i<=8;i++) //i表示消息对象
{
CAN0ADR=IF1MSK1;
CAN0DATA=0X0000;
CAN0DATA=0X0000; //需要修改 IDE过滤
CAN0ADR=IF1ARB2;
CAN0DATH=0Xa0;
CAN0DATL=IDL;
IDL += 4;
CAN0DATA=0X0088; //IF1MSGC
CAN0ADR=IF1CMDRQST;
while((CAN0DATH & 0X80) == 1);
CAN0DATL=i;
}
IDL=0x04;
for(;i<=16;i++)
{
CAN0ADR=IF1MSK1;
CAN0DATA=0XFFFF;
CAN0DATA=0X1FFF; //需要修改 IDE过滤
CAN0ADR=IF1ARB2;
CAN0DATH=0XA0;
CAN0DATL=IDL;
IDL += 4;
CAN0DATA=0X1080; //可设定newdata引发intpnd
CAN0ADR=IF1CMDRQST;
while((CAN0DATH & 0X80) == 1);
CAN0DATL=i;
}
CANINIT=0;
CAN0ADR=IF1CMDMSK;
CAN0DATL=0X87; //87 控制位等不改
for(i=1;i<=8;i++)
{
CAN0ADR=IF1DATA1;
for(j=1;j<=4;j++)
{
CAN0DATA=data_temp;
data_temp+=257;
}
CAN0ADR=IF1CMDRQST;
CAN0DATL=i; //这里发送
}
}
void init_msg_object_TX (uchar MsgNum,uint id)
{
uint tempreg;
SFRPAGE = CAN0_PAGE;
CAN0ADR = IF1CMDMSK; //指向命令掩码寄存器
CAN0DATA = 0x00b3; //设为写,改变所有的消息对象除了标识掩码位,将数据字节0-7发送到消息对象
/* IF1 Command Mask Registers =0x00b3
WR/RD=1,Mask=1,Arb=1,Control=1,ClrIntPnd=0,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据*/
CAN0ADR = IF1ARB1; //指向IF1仲裁寄存器1
CAN0DATA = 0x0000; //ID15-0:0000;将仲裁ID设为最高优先级
/*IF1 Arbitration Registers1 =0x0000,即ID15-0=0*/
tempreg=id<<2;//标准id为ID28-ID18,所以要左移2位
tempreg&=0x1fff;
tempreg|=0xa000;
CAN0DATA = tempreg; ////自动增加地址到IF1仲裁寄存器2
/*IF1 Arbitration Registers2=101(id)00b
MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=1,为发送*/
CAN0DATA = 0x0088; //IF1消息控制寄存器:DLC = 1,禁止远程桢
/*IF1 Message Control Registers=0x0088
NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=0,RmtEn=0,TxRqst=0
EoB=1,DLC3-0=1000,即数据长度为8*/
CAN0ADR = IF1CMDRQST; //指向IF1命令请求寄存器
CAN0DATL = MsgNum;
/*IF1 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息*/
}
void init_msg_object_RX (char MsgNum,uchar id)
{
uint temp;
SFRPAGE = CAN0_PAGE;
CAN0ADR = IF2CMDMSK;
CAN0DATA = 0x00bb;
/* IF2 Command Mask Registers =0x00bb
WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1,一次发送8字节数据*/
CAN0ADR = IF2ARB1; //指向IF2仲裁寄存器
CAN0DATA = 0x0000;
/*IF2 Arbitration Registers1 =0x0000,即ID15-0=0*/
temp=id<<2;//标准id为ID28-ID18,所以要左移2位
temp&=0x1fff;
temp|=0x8000;
CAN0DATA = temp;
/*IF2 Arbitration Registers2=100(id)00b
MsgVal=1,Xtd=0,为标准模式,扩展ID无效,Dir=0,为接收*/
CAN0DATA = 0x0488;
/*IF2 Message Control Registers=0x0488
NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=1,接收中断使能;RmtEn=0,TxRqst=0
EoB=1,DLC3-0=1000,即数据长度为8*/
CAN0ADR = IF2CMDRQST;
CAN0DATL = MsgNum;
/*IF2 Command Request Registers=MsgNum,将以上配置写入MsgNum号消息*/
}
void start_CAN(){
SFRPAGE=CAN0_PAGE;
// CAN0CN|=0X00C1; // 开测试和bt设置
// CAN0CN&=0XFFd7; //自动重发开启 错误中断禁止
CAN0CN|=0X0041; //使能CCE和INIT位
// CAN0ADR=CANTSTR;
// CAN0DATL|=0X10;
CAN0ADR=BITREG;
CAN0DATA=0X2640;
CAN0ADR = IF1CMDMSK; //指向命令掩码寄存器1
CAN0DATA = 0x0087; //写:
//设置CAN RAM为写,写数据字节, //设置发送请求位
//将发送0---3发送到消息对象
//将发送4---7发送到消息对象
CAN0ADR = IF2CMDMSK; //指向命令掩码寄存器2(设置接收,读CAN_RAM,读数据字节)
CAN0DATL = 0x1f; //设置为接受
//掩码位不变
//仲裁位不变
//发送控制位到IFx消息缓冲寄存器
//清除消息对象中断挂起位
//清除消息对象中的NewData位
//将数据字节0---3字节发送到消息缓冲寄存器中
//将数据字节4---7字节发送到消息缓冲寄存器中
CAN0CN|=0X0006;
CAN0CN&=0XFFBE;
}
void transmit_message(uchar MsgNum)
{
// uchar i;
SFRPAGE=CAN0_PAGE; //指向CAN0页面
CAN0ADR=IF1CMDMSK; //向IF1命令屏蔽寄存器写入命令
CAN0DATL=0X0083;
CAN0ADR=IF1ARB2; //指向IF1仲裁寄存器2
CAN0DATH|=0x80;
CAN0ADR=IF1DATA1; //指向数据场的第一个字节
/* for(i=0;i<4;i++)
{
CAN0DATA=CAN_TX[i]; //将4字节数据写入发送缓冲器
}*/
CAN0DATL=0x22;
CAN0ADR=IF1CMDRQST;
CAN0DATL=MsgNum; //将报文对象编号写入,则数据发送到对应的报文对象中
}
void receive_data(uchar MsgNum)
{
uchar i;
SFRPAGE=CAN0_PAGE; //指向CAN0页面
CAN0ADR=IF2CMDMSK; //向IF2命令屏蔽寄存器写命令
CAN0DATA=0x003F;
CAN0ADR=IF2CMDRQST; //将报文对象编号写入命令请求寄存器,对应地接收
CAN0DATL=MsgNum; //得到数据就从报文RAM中移到数据缓冲器中
CAN0ADR=IF2DATA1; //指向数据场的第一个字节
for(i=0;i<4;i++) //读取4个字节数据
{
CAN_RX[i]=CAN0DATA;
}
}
void main()
{
WDTCN = 0xde;
WDTCN = 0xad;
PORT_Init();
external_osc();
clear_msg_objects();
init_msg_object_TX(0x02,5); //广播发送
start_CAN();
// init_msg_object_rx(0x01,1);
while(switch1==1);
RX_flag=0;
TX_flag=0;
eror_flag=0;
EIE2 = 0x20;//允许can0中断
// EIP2 |= 0x20;
EA = 1;
while(1)
{
transmit_message(0x02);
if(TX_flag==1)
{
TX_flag=0;
LED=!LED;
delayms(500);
}
}
}
void inter_CAN(void) interrupt 19
{
SFRPAGE = CAN0_PAGE;
status = CAN0STA; //读状态寄存器
if ((status&0x10) != 0) //Rxok位为1,则是由于接收引起的中断
{
CAN0STA = (CAN0STA&0xEF)|0x07; //复位Txok,设置LEC无变化
RX_flag=1; //接受中断标志位置位
// receive_data (); // Up to now, we have only one RX message
}
if ((status&0x08) != 0) //Txok位为1,则是由于发送引起的中断
{
CAN0STA = (CAN0STA&0xF7)|0x07; //复位Txok,设置LEC无变化
TX_flag=1; //发送完成标志置位
}
if (((status&0x07) != 0)&&((status&0x07) != 7)) //错误中断,改变LEC
{
CAN0STA = CAN0STA|0x07; //设置LEC无变化
eror_flag=1;
}
}
一周热门 更多>