笔记十四:RS232<->CAN<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
今天的笔记如题那样,就是数据在CAN与RS232协议之间互换,其实这个话题不是很新鲜了,不过真的很有探索的价值,那么我们看一看下面的图表:
从上面的图表,我们可以这样解释道:假设报文从CAN总线上被接收到某个节点之中,其中该节点调用了CAN接收函数,然后从报文中读取数据,然后赋值给与临时变量,再者将该临时变量传递给出口发送函数,经串口协议,最后数据发送在计算机中。这一回是数据时从计算器接收,其中调用了串口接收函数来处理从计算机传送来的数据,然后将数据赋值到一个临时变量,然后再调用CAN发送函数将数据发往CAN总线中。
经上述的分析中,我已经知道,所谓的CAN与RS232的互换,不过是一个变量从一个的函数到另一个函数经过传递和处理而已,而其中就有前章所学过的串口接收发送,CAN接收发送等函数,换成某种意义的话,就是将上述的函数全部整合在一次,然后再巧妙的修改就可以达到以上的效果了,感觉这么说似乎有点空虚,还是看一些实际的东西吧,比较有实感。
(图太大了...)
编程的思路如上述的流程图那样,RS232-CAN之间的转换都是有彼此的接收中断而触发的,如一,当CAN接收报文然后触发中断处理函数,会从报文中将数据读入一个临时变量,然后标志位置一。在主函数中,在不停的循环体中,判断是否CAN标志位为一呢?如果是的话,那么就会进入处理,CAN标志位清零将临时变量中的值传递给串口发送函数。RS232转CAN的摸样也是差不多了,这个就自己仔细的思考了。
好了,最后就还是献上源码吧:
//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接收函数,然后添加了串口接收函数,串口发送函数而已,当然也没有经过测试,真的很抱歉,就把它当做是一个参考用的源码吧。
文章评论(0条评论)
登录后参与讨论