can多机通信.docx
《can多机通信.docx》由会员分享,可在线阅读,更多相关《can多机通信.docx(32页珍藏版)》请在冰豆网上搜索。
can多机通信
Node1
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:
//本程序为第7章节点1的配套程序&
//功能描述:
//INT0按键程序+显示程序+CAN两点通信程序&
//数码管1-2(从右至左)显示(十进制)本节点计数结果,数码管3-4显示(十进制)接收到的数据&&
//CAN主要参数:
//PeliCAN模式,扩展帧EFF模式&
//29位标示码结构:
&
//发送数据结构:
计数结果&
//接收数据结构:
待显示数据&
//本节点的地址:
0x01(ACR0~3:
0xff,0x01,0xff,0xff)&
//验收屏蔽寄存器:
0xff,0x00,0xff,0xff;(AMR0~3)只接收发往本节点的报文&
//报文标识符:
0x01,0x02,0x10,0x00;&
//提示:
如果CAN通讯不正常,会进入一个死循环,显示也不正常
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!
&
//【声明】作者:
PIAE小组&
#include
#include
#include
ucharjidian=0;
voidINT0_Counter(void)interrupt0using1
{//INT0按键为计数按键
EA=0;
Txd_data++;//存储计数结果,并为待发送的数据
TXD_flag=1;//要发送数据标志位
jidian++;
EA=1;
}
voidCAN_RXD(void)interrupt2
{//接收数据函数,在中断服务程序中调用
uchardataJudge;
uchardataCanDataLength;//报文数据长度变量
unsignedcharvolatilexdata*p;//外部寄存器指针
uchari;
EA=0;//关CPU中断
IE0=0;
Judge=IR;
if(Judge&0x01)
{//IR.0=1接收中断
CanDataLength=RBSR&0x0f;//CAN数据报文的数据长度
p=&RBSR;
for(i=0;i<=(CanDataLength+5);i++)
{
RX_buffer[i]=*p++;
}
jidian=RX_buffer[6];
jidian=~jidian;
if(jidian)LED_GRE=1;
if(!
jidian)LED_GRE=0;
RXD_flag=1;//置有接收标志
CMR=0X04;
Judge=ALC;//释放仲裁随时捕捉寄存器
Judge=ECC;//释放错误代码捕捉寄存器
}
IER=0x01;//.0=1--接收中断使能;
EA=1;//打开CPU中断
}
voidmain(void)
{
CPU_init();//CPU初始化
CAN_init();//SJA1000初始化,对SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
while
(1)
{
_nop_();
_nop_();
Rxd_deal();//接收处理程序
Txd_deal();//发送处理程序
led_seg7(1,Txd_data);
led_seg7(3,Rxd_data);
}
}
//*********************处理函数********************************
//*********************CPU初始化函数********************************
voidCPU_init(void)
{//初始化CPU
SJA_RST=0;//CAN总线复位管脚有效
Delay(20);
SJA_RST=1;//CAN总线复位管脚无效
SJA_CS=0;//CAN总线片选有效
EX1=1;
IT1=0;//CAN总线接收中断
IT0=1;//外部中断0负边沿触发
EX0=1;//打开外部中断0
EA=1;//打开总中断
SJA_CS=1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
}
voidRxd_deal(void)
{////////接收处理程序//////////////
if(RXD_flag)
{
EA=0;//关闭CPU中断
RXD_flag=0;
if(RX_buffer[3]==0x10)//如果该报文传输的为按键计数
{
Rxd_data=RX_buffer[5];
}
EA=1;
}
}////////接收处理程序//////////////
voidTxd_deal(void)
{//发送处理函数,主要是准备数据,并且调用发送函数
if(TXD_flag==1)
{
_nop_();
TXD_flag=0;
if(Txd_data&0x01)
{//将奇数计数值发往节点2.
//初始化标示码头信息
TX_buffer[0]=0x82;//.7=0扩展帧;.6=0数据帧;.3~0=1数据长度
TX_buffer[1]=0x01;//本节点地址
TX_buffer[2]=0x02;//
TX_buffer[3]=0x10;//
TX_buffer[4]=0x00;//
TX_buffer[5]=Txd_data;//
jidian++;
TX_buffer[6]=jidian;
}
elseif(!
(Txd_data&0x01))
{//将偶数计数值发往节点3.
//初始化标示码头信息
TX_buffer[0]=0x82;//.7=0扩展帧;.6=0数据帧;.3~0=1数据长度
TX_buffer[1]=0x01;//本节点地址
TX_buffer[2]=0x03;//
TX_buffer[3]=0x10;//
TX_buffer[4]=0x00;//
TX_buffer[5]=Txd_data;//
jidian++;
TX_buffer[6]=jidian;
}
CAN_TXD();
_nop_();
_nop_();
}
}
//*********************处理函数********************************
//*********************CAN子函数***********************
voidCAN_init(void)
{//SJA1000的初始化
ucharbdataJudge;
ucharACRR[4];
ucharAMRR[4];
ACRR[0]=0xff;
ACRR[1]=0x01;
ACRR[2]=0xff;
ACRR[3]=0xff;//接收代码寄存器
AMRR[0]=0xff;
AMRR[1]=0xff;
AMRR[2]=0xff;
AMRR[3]=0xff;//接收屏蔽寄存器,只接收发往本节点的报文
do
{//.0=1---resetMODR,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
MODR=0x09;
Judge=MODR;
}
while(!
(Judge&0x01));
CDR=0x88;//CDR.3=1--时钟关闭,.7=0---basicCAN,.7=1---PeliCAN
BTR0=0x31;
BTR1=0x1c;//总线波特率设定
IER=0x01;//.0=1--接收中断使能;.1=0--关闭发送中断使能
OCR=0xaa;//配置输出控制寄存器
CMR=0x04;//释放接收缓冲器
ACR=ACRR[0];
ACR1=ACRR[1];
ACR2=ACRR[2];
ACR3=ACRR[3];//初始化标示码
AMR=AMRR[0];
AMR1=AMRR[1];
AMR2=AMRR[2];
AMR3=AMRR[3];//初始化掩码
do
{//确保退出复位模式
MODR=0x08;
Judge=MODR;
}
while(Judge&0x01);
}//SJA1000的初始化
voidCAN_TXD(void)
{
uchardataJudge;
//初始化数据信息
EA=0;//关中断
do
{
Judge=SR;
LED_RED=0;//
}
while(Judge&0x10);//SR.4=1正在接收,等待
do
{
Judge=SR;
LED_RED=0;//
}
while(!
(Judge&0x08));//SR.3=0,发送请求未处理完,等待
do
{
Judge=SR;
LED_RED=0;//
}
while(!
(Judge&0x04));//SR.2=0,发送缓冲器被锁。
等待
LED_RED=!
LED_RED;
//LED_GRE=!
LED_GRE;//灯闪烁
TBSR=TX_buffer[0];
TBSR1=TX_buffer[1];
TBSR2=TX_buffer[2];
TBSR3=TX_buffer[3];
TBSR4=TX_buffer[4];
TBSR5=TX_buffer[5];
TBSR6=TX_buffer[6];
CMR=0x01;//置位发送请求
EA=1;
}
voidDelay(uchardelay_time)
{//延时程序
while(delay_time--)
{}
}
//*********************CAN子函数*************************
//*********************显示子函数*************************
voidled_seg7(ucharfrom,ucharnumber)//from(1_4):
数码管显示起始位置(从右到左),number:
显示的数(数码管上采用10进制显示)
{
uchardigit,temp_l;
uchartemp_h=0x7f;
temp_h=_cror_(temp_h,from-1);//确定从哪一位开始显示,即确定高四位
temp_h=temp_h&0xf0;//取高四位
temp_l=P2&0x0f;//取P2的低四位
P2=temp_h|temp_l;//设定P2口
if(number==0)
{
P0=led[0];
Delay(10);
P0=0xff;
}
else
{
while(number)
{
digit=number%10;
number/=10;
P0=led[digit];
Delay(10);
temp_h=P2&0xf0;//取P2的高四位
temp_h=temp_h|0x0f;//拼装temp_h,进行位选
temp_h=_cror_(temp_h,1);
temp_h=temp_h&0xf0;//取高四位
temp_l=P2&0x0f;//取P2的低四位
P0=0xff;
P2=temp_h|temp_l;//设定P2口
}
}
}
Node2
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//描述:
//本程序为第7章节点2的配套程序&
//功能描述:
//INT0按键程序+显示程序+CAN两点通信程序&
//数码管1-2(从右至左)显示(十进制)本节点计数结果,数码管3-4显示(十进制)接收到的数据&&
//CAN主要参数:
//PeliCAN模式,扩展帧EFF模式&
//29位标示码结构:
&
//发送数据结构:
计数结果&
//接收数据结构:
待显示数据&
//本节点的地址:
0x02(ACR0~3:
0xff,0x02,0xff,0xff)&
//验收屏蔽寄存器:
0xff,0x00,0xff,0xff;(AMR0~3)只接收发往本节点的报文&
//报文标识符:
0x02,0x01,0x10,0x00;&
//提示:
如果CAN通讯不正常,会进入一个死循环,显示也不正常
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//【声明】此程序仅用于学习与参考,引用请注明版权和作者信息!
&
//【声明】作者:
PIAE小组&
#include
#include
#include
ucharjidian=0;
voidINT0_Counter(void)interrupt0using1
{//INT0按键为计数按键
EA=0;
Txd_data++;//存储计数结果,并为待发送的数据
TXD_flag=1;//要发送数据标志位
jidian++;
EA=1;
}
voidCAN_RXD(void)interrupt2
{//接收数据函数,在中断服务程序中调用
uchardataJudge;
uchardataCanDataLength;//报文数据长度变量
unsignedcharvolatilexdata*p;//外部寄存器指针
uchari;
EA=0;//关CPU中断
IE0=0;
Judge=IR;
if(Judge&0x01)
{//IR.0=1接收中断
CanDataLength=RBSR&0x0f;//CAN数据报文的数据长度
p=&RBSR;
for(i=0;i<=(CanDataLength+5);i++)
{
RX_buffer[i]=*p++;
}
jidian=RX_buffer[6];
jidian=~jidian;
if(jidian)LED_GRE=1;
if(!
jidian)LED_GRE=0;
RXD_flag=1;//置有接收标志
CMR=0X04;
Judge=ALC;//释放仲裁随时捕捉寄存器
Judge=ECC;//释放错误代码捕捉寄存器
}
IER=0x01;//.0=1--接收中断使能;
EA=1;//打开CPU中断
}
voidmain(void)
{
CPU_init();//CPU初始化
CAN_init();//SJA1000初始化,对SJA1000寄存器的读写是采用外部寄存器寻址方式,所以不需要程序单独控制片选有效无效
_nop_();
_nop_();
while
(1)
{
_nop_();
_nop_();
Rxd_deal();//接收处理程序
Txd_deal();//发送处理程序
led_seg7(1,Txd_data);
led_seg7(3,Rxd_data);
}
}
//*********************处理函数********************************
//*********************CPU初始化函数********************************
voidCPU_init(void)
{//初始化CPU
SJA_RST=0;//CAN总线复位管脚有效
Delay(20);
SJA_RST=1;//CAN总线复位管脚无效
SJA_CS=0;//CAN总线片选有效
EX1=1;
IT1=0;//CAN总线接收中断
IT0=1;//外部中断0负边沿触发
EX0=1;//打开外部中断0
EA=1;//打开总中断
SJA_CS=1;//CAN总线片选无效,使对数据总线的操作不会影响SJA1000。
}
voidRxd_deal(void)
{////////接收处理程序//////////////
if(RXD_flag)
{
EA=0;//关闭CPU中断
RXD_flag=0;
if(RX_buffer[3]==0x10)//如果该报文传输的为按键计数
{
Rxd_data=RX_buffer[5];
}
EA=1;
}
}////////接收处理程序//////////////
voidTxd_deal(void)
{//发送处理函数,主要是准备数据,并且调用发送函数
if(TXD_flag==1)
{
_nop_();
TXD_flag=0;
TX_buffer[5]=Txd_data;//
TX_buffer[6]=jidian;
CAN_TXD();
_nop_();
_nop_();
}
}
//*********************处理函数********************************
//*********************CAN子函数***********************
voidCAN_init(void)
{//SJA1000的初始化
ucharbdataJudge;
ucharACRR[4];
ucharAMRR[4];
ACRR[0]=0xff;
ACRR[1]=0x02;
ACRR[2]=0xff;
ACRR[3]=0xff;//接收代码寄存器
AMRR[0]=0xff;
AMRR[1]=0X00;
AMRR[2]=0xff;
AMRR[3]=0xff;//接收屏蔽寄存器,只接收发往本节点的报文
do
{//.0=1---resetMODRe,进入复位模式,以便设置相应的寄存器
//防止未进入复位模式,重复写入
MODR=0x09;
Judge=MODR;
}
while(!
(Judge&0x01));
CDR=0x88;//CDR.3=1--时钟关闭,.7=0---basicCAN,.7=1---PeliCAN
BTR0=0x31;
BTR1=0x1c;//总线波特率设定
IER=0x01;//.0=1--接收中断使能;.1=0--关闭发送中断使能
OCR=0xaa;//配置输出控制寄存器
CMR=0x04;//释放接收缓冲器
ACR=ACRR[0];
ACR1=ACRR[1];
ACR2=ACRR[2];
ACR3=ACRR[3];//初始化标示码
AMR=AMRR[0];
AMR1=AMRR[1];
AMR2=AMRR[2];
AMR3=AMRR[3];//初始化掩码
do
{//确保退出复位模式
MODR=0x08;
Judge=MODR;
}
while(Judge&0x01);
}//SJA1000的初始化
voidCAN_TXD(void)
{
uchardataJudge;
//初始化标示码头信息
TX_buffer[0]=0x82;//.7=0扩展帧;.6=0数据帧;.3~0=1数据长度
TX_buffer[1]=0x02;//本节点地址
TX_buffer[2]=0x01;//
TX_buffer[3]=0x10;//
TX_buffer[4]=0x00;//
//初始化标示码头信息
//初始化发送数据单元
TX_buffer[5]=Txd_data;
TX_buffer[6]=jidian;
//初始化数据信息
EA=0;//关中断
do
{
Judge=SR;
LED_RED=0;//
}
while(Judge&0x10);//SR.4=1正在接收,等待
do
{
Judge=SR;
LED_RED=0;//
}
while(!
(Judge&0x08));//SR.3=0,发送请求未处理完,等待
do
{
Judge=SR;
LED_RED=0;//
}
while(!
(Judge&0