原创 笔记十四:RS232CAN

2009-11-2 18:48 2995 9 9 分类: 汽车电子

笔记十四:RS232<->CAN<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


今天的笔记如题那样,就是数据在CAN与RS232协议之间互换,其实这个话题不是很新鲜了,不过真的很有探索的价值,那么我们看一看下面的图表:



3c913595-1eb7-4757-a9ed-32dc136c8c05.JPG



从上面的图表,我们可以这样解释道:假设报文从CAN总线上被接收到某个节点之中,其中该节点调用了CAN接收函数,然后从报文中读取数据,然后赋值给与临时变量,再者将该临时变量传递给出口发送函数,经串口协议,最后数据发送在计算机中。这一回是数据时从计算器接收,其中调用了串口接收函数来处理从计算机传送来的数据,然后将数据赋值到一个临时变量,然后再调用CAN发送函数将数据发往CAN总线中。



经上述的分析中,我已经知道,所谓的CANRS232的互换,不过是一个变量从一个的函数到另一个函数经过传递和处理而已,而其中就有前章所学过的串口接收发送,CAN接收发送等函数,换成某种意义的话,就是将上述的函数全部整合在一次,然后再巧妙的修改就可以达到以上的效果了,感觉这么说似乎有点空虚,还是看一些实际的东西吧,比较有实感。



(图太大了...)





点击看大图



编程的思路如上述的流程图那样,RS232-CAN之间的转换都是有彼此的接收中断而触发的,如一,当CAN接收报文然后触发中断处理函数,会从报文中将数据读入一个临时变量,然后标志位置一。在主函数中,在不停的循环体中,判断是否CAN标志位为一呢?如果是的话,那么就会进入处理,CAN标志位清零将临时变量中的值传递给串口发送函数。RS232CAN的摸样也是差不多了,这个就自己仔细的思考了。



好了,最后就还是献上源码吧:



//00-RS232-CAN.c


//RS232-CAN转换的例子程式


//akuei2 31-10-09



#include "reg52.h"


#include "sja1000.h"


#define uchar unsigned char



//IO口定义


sbit SJACS=P2^0;


sbit SJARST=P2^3;



//数码管码,位选码定义


uchar code Led_Code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};


uchar code Led_Select[]={0xef,0xdf,0xbf,0x7f}; 



//变量声明


uchar ACR[4],AMR[4],TXD_Buffer[13],RXD_Buffer[13],TXD_Data,RXD_Data;


uchar Click;


bit Flag_232RXD,Flag_CANRXD;



//函数声明


void Display(void);


void CAN_TXD(void);


void CAN_RXD(void);


void RS232_TXD(void);



//50微秒延迟函数


void Delay_50us(int t)


{


uchar j; 


    t--;


for(;t>0;t--)  


    for(j=19;j>0;j--);


}



//数据初始化函数


void Init_Data(void)


{


int i;



ACR[0]='C';


ACR[1]='A';


ACR[2]='N';


ACR[3]=0x01;


AMR[0]=0xff;


AMR[1]=0xff;


AMR[2]=0xff;


AMR[3]=0xff;



TXD_Buffer[0]=0x88;


TXD_Buffer[1]='C';


TXD_Buffer[2]='A';


TXD_Buffer[3]='N';


TXD_Buffer[4]=0x02;


TXD_Buffer[5]=TXD_Data;


TXD_Buffer[6]=0x00;


TXD_Buffer[7]=0x00;


TXD_Buffer[8]=0x00;


TXD_Buffer[9]=0x00;


TXD_Buffer[10]=0x00;


TXD_Buffer[11]=0x00;


TXD_Buffer[12]=0x00;



for(i=0;i<13;i++)


{


RXD_Buffer=0x00;


}



TXD_Data=0x00;


RXD_Data=0x00;


}



//CPU初始化函数


void Init_CPU(void)


{


SJACS=1;


SJARST=1;



    SCON=0x50;           //串口工作方式1,允许接收


    PCON=0x80;           //波特率翻倍   


    TMOD=0x20;           //T1用于串口波特率控制


    TL1=0xfa;            //初始化T1,波特率为9600(晶振11.0592M


    TH1=0xfa;                    


   TR1=1;               //开定时器


   ES  = 1;             //打开串口中断



IT0=1;


IT1=0;


EX0=1;


EX1=1;



EA=1;


   


}



//CAN初始化函数


void Init_CAN(void)


{


   unsigned char bdata temp;   //建立存储在bdata中的临时变量temp



   do


   {


      MODR=0x09; 


  temp=MODR;  //模式寄存器-设置复位模式而且单验收滤波模式


   }


   while(!(temp&0x01));  //判断



   CDR=0x88;     //时钟分频寄存器-设置PeliCAN模式,Clock off有效


   BTR0=0x31;    //总线时序寄存器-波特率为10kbps


   BTR1=0x1c;


   IER=0x01;      //中断使能寄存器-接收中断使能


   OCR=0xaa;     //输出控制寄存器-借签...


   CMR=0x04;     //命令寄存器-释放RXFIF0



   ACR0=ACR[0];      //接收代码寄存器-本节点地址位CAN0 


   ACR1=ACR[1]; 


   ACR2=ACR[2]; 


   ACR3=ACR[3];



   AMR0=AMR[0];    //接收屏蔽寄存器-无任何屏蔽


   AMR1=AMR[1]; 


   AMR2=AMR[2]; 


   AMR3=AMR[3];   //最后两位为无用位,必须设置为逻辑1



   do


   {


      MODR=0x08; 


  temp=MODR;   //模式寄存器-推出复位模式,保持单验收滤波模式


   }


   while(temp&0x01);   //判断...


}   



//主函数


void main(void)


{


Init_Data();


Init_CPU();


Init_CAN();


while(1)


{


Display();


if(Flag_232RXD)


{


Flag_232RXD=0;


TXD_Buffer[5]=TXD_Data;


CAN_TXD();


}


if(Flag_CANRXD)


{


Flag_CANRXD=0;


RXD_Data=RXD_Buffer[5];


RS232_CAN();


}


}


}



//数码管显示函数


void Display(void)


{


int Digit[4],i;


Digit[3]=TXD_Data/10; //第一个数码管取千位


Digit[2]=TXD_Data%10; //第二个数码管取百位


Digit[1]=RXD_Data/10; //第三个数码管取十位


Digit[0]=RXD_Data%10; //第四个数码管取个位


for(i=0;i<4;i++)


{


P0=Led_Code[Digit[3-i]]; //送数码管码


P2=Led_Select; //送位选码


Delay_50us(20); //延迟1微秒


}


}



//CAN接收函数


void CAN_TXD(void)


{


unsigned char bdata temp;



do


{


  temp=SR;         //判断报文接收完毕?


}


while(temp&0x10);    //SR.4=0 发送闲置,SR.4=1 发送状态中



do


{


  temp=SR;         //判断最后报文请求?


}


while(!(temp&0x08));  //SR.3=0 没有余报文请求,SR.3=1 还存在报文请求



do


{


  temp=SR;         //判断TXFIFO是否锁定?


}


while(!(temp&0x04));  //SR.2=0 锁定,SR.2=1 开放



TBSR0=TXD_Buffer[0];


TBSR1=TXD_Buffer[1];


TBSR2=TXD_Buffer[2];


TBSR3=TXD_Buffer[3];


TBSR4=TXD_Buffer[4];


TBSR5=TXD_Buffer[5];


TBSR6=TXD_Buffer[6];


TBSR7=TXD_Buffer[7];


TBSR8=TXD_Buffer[8];


TBSR9=TXD_Buffer[9];


TBSR10=TXD_Buffer[10];


TBSR11=TXD_Buffer[11];


TBSR12=TXD_Buffer[12];



CMR=0x01;       //命令寄存器-发送请求


}



//CAN发送函数


void CAN_RXD(void)


{


unsigned char temp;



temp = IR;


if( temp & 0x01)                   //判断是否接收中断


{


RXD_Buffer[0]=RBSR0;         //读取RXFIFO


RXD_Buffer[1]=RBSR1;


RXD_Buffer[2]=RBSR2;


RXD_Buffer[3]=RBSR3;


RXD_Buffer[4]=RBSR4;


RXD_Buffer[5]=RBSR5;


RXD_Buffer[6]=RBSR6;


RXD_Buffer[7]=RBSR7;


RXD_Buffer[8]=RBSR8;


RXD_Buffer[9]=RBSR9;


RXD_Buffer[10]=RBSR10;


RXD_Buffer[11]=RBSR11;


RXD_Buffer[12]=RBSR12;



CMR = 0X04;                  //释放RXFIFO中的空间


temp = ALC;                   //释放仲裁随时捕捉寄存器


temp = ECC;                   //释放错误代码捕捉寄存器


}



IER = 0x01;// .0=1--接收中断使能;



}



//串口发送函数


void RS232_TXD( void )


{


    EA = 0; //关闭所有中断


    ES = 0; //关闭串口中断,采用查询发送方式


    TI = 1;


    while(TI)


    {


        TI = 0; //一字节发送完后清除标志位


        SBUF = RXD_Data; //can接收到的数据发送出去


        while(!TI); //等待发送


        TI = 0;


    }


    ES = 1; //打开串口中断


    EA = 1; //打开中断


}



//CAN接收中断


void Ir_EX1(void) interrupt 2


{


EA=0;


EX1=0;


CAN_RXD();


Flag_CANRXD=1;


EX1=1;


EA=1;


}



//串口接收据函数


void RS232_RXD( void ) interrupt 4   


{


    EA = 0; //关闭所有中断


    ES = 0; //关闭串口


    if(RI==1)


    {


        RI = 0;


        TXD_Data = SBUF;


Flag_232RXD=1;


    }


    ES = 1; //打开串口


    EA = 1; //打开中断


}



以上的源码由于编辑时时间比较仓促了一点,很多地方也没有修改,仅修改了主函数,CAN接收函数,然后添加了串口接收函数,串口发送函数而已,当然也没有经过测试,真的很抱歉,就把它当做是一个参考用的源码吧。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /3 下一条