解析CAN总线与PC机串口通信适配器设计与实现
来源:龙人计算机研究所 作者:站长 时间:2009-09-17 10:42:44
CAN总线(Controller AreaNetwork,控制器局域网) 已成为比较流行的一种现场总线,广泛应用于控制系统中的各检测和执行机构之间的数据通信,因其具有高性能、高可靠性、高性价比、连接方便、实时性好及其独特的设计等突出优点应用于许多工业部门。而实际应用中PC机与CAN总线的人机交互设计尤为重要,它直接影响系统的运行和结果,其连接方法也成为系统设计的重点,通常采取3种连接方式:RS-232串行口通信、PCI卡、USB口通信,由于串行通信端口在系统控制领域中一直扮演着极为重要的角色,以其开发简单,资源丰富,成本低,无需驱动程序等诸多优点,不仅没有被淘汰,反而在规格上更先进,故应用广泛。结合设计中AT89C51单片机有串行通信口且接口简单的特点,选用RS-232作为CAN总线与PC机之间的连接方式。将就这一基于CAN控制器SJA1000与AT89C51的具有通用性的工业测控系统设计的软硬件设计方案作详细介绍。
CAN总线及CAN控制器SJA1000简介
CAN总线最初是德国Bosch公司在1986 年为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种支持分布式实时控制系统的串行数据通讯总线。CAN总线与其它通信网的显著不同之处在于:
(1)报文传送中不包含目标地址,它是以全网广播为基础,各接收站根据报文中反映数据性质的标识符过滤报文,该收的收下,不收的弃用。其好处是可线上网下网、即插即用和多站接收。
(2)特别强化了对数据安全性的关注,满足控制系统及其它较高数据要求的系统需求。另外CAN总线采用短帧结构,借助接收滤波的多地址帧传送,受干扰概率低,每帧信息都有CRC校验及其它检错措施。响应远程数据请求,配置灵活,具有全系统的数据相容性。节点数主要取决于总线驱动电路,目前最多可达110个节点。CAN总线符合ISO11898标准,通信速率高,最大传输速率可达1Mbit/S,最大传输距离为10km,传输介质可为双绞线。基于CAN总线以上的特点,把它应用于系统分布比较分散且需要在同一总线上挂接多个节点的场合是非常适合的。
目前广泛流行的CAN总线器件有两大类:一类是独立的CAN控制器,如PhilipS公司的PCA82C200,SJA1000及Intel82256/82257等;另一类是带有在片CAN的微控制器,如P8XC582等。其中Philips公司的PCA82C200是符合CAN2. 0A协议的总线控制器,SJA1000是它的替代产品,它是应用于汽车和一般工业环境的独立CAN总线控制器。具有完成CAN通信协议所要求的全部特性。经过简单总线连接的SJA1000可完成CAN总线的物理层和数据链路层的所有功能。其硬件与软件设计和PCA82C200的基本CAN模式(BasicCAN)兼容。同时,新增加的增强CAN模式( PeliCAN)还可支持CAN2. 0B协议。根据当前市场开发工具和课题的实际需要,选用SJA1000作为CAN控制器,同时使用了CAN控制器接口芯片PCA82C250。
SJA1000有两种工作模式:基本模式和增强模式。在基本模式下,SJA1000只可收发标准数据帧(标准数据帧的标识符为11位),且错误报警的极限值不能修改;在增强模式下,SJA1000既可接收标准数据帧,也可接收扩展数据帧(扩展数据帧的标识符为29位),可修改错误报警的极限值,并且SJA1000具有更加灵活的滤波方式,能够根据数据帧的标识符有选择地接收一些数据帧。另外,增强模式下的SJA1000能够进行自检,即可通过自发自收一组报文来判断该控制节点是否正常地挂在CAN总线上。使用者所要做的主要工作是SJA1000的初始化,收发报文的处理以及对节点脱离总线的检测量与处理。
RS-232标准
串行通信由于接线少、成本低,在数据采集和控制系统中得到了广泛的应用,1969年,美国电子工业协会( EIA)公布了RS-232C作为串行通信接口的电气标准,该标准定义了数据终端设备(DTE)和数据通信设备(DCE)间按位串行传输的接口信息,合理安排了接口的电气信号和机械要求,在世界范围内得到了广泛的应用。
系统总体结构原理及设计
该适配器利用RS-232串行通信口及CAN总线进行数据通信,实现上位机与各智能节点间的通信任务,包括控制台(上位机)向下传输命令和下位机数据的返回,以完成对下层设备的监控。图1为系统结构框图。PC机通过RS-232与CAN控制器SJA1000通信,实现信息在CAN总线上的发送与接收。底层各智能节点根据应用的不同具有不同功能,但都具有与CAN总线通信能力可以上传数据和接收数据。
CAN总线接口硬件设计
图2为CAN总线通信接口适配器硬件设计简图。
PCA82C250提供对总线的差动发送和对CAN控制器的差动接收功能,也增大了通信距离,提高了系统的瞬间抗干扰能力,保护总线,降低射频干扰(RFI),实现了热防护等功能。
系统软件设计
软件设计分PC机Visual BasiC编程和AT89C51单片机C语言编程2部分。
PC机部分
采用VB6. 0编程,这样界面非常直观,人机交互效果好。VB提供了具有通讯功能的MSComm. OCX控件,该控件可设置串行通信的数据发送和接收,对串口状态及串口通信的信息格式和协议进行设置。MSComm控件提供2种处理通讯的方式:(1)事件驱动通讯,即发送或接收数据过程中触发ONCOMM事件,通过编程访问CommEvent属性了解通信事件的类型,分别进行各自的处理;(2)查询方式,通过检查CommEvent属性的值来查询事件和错误。采取查询方式。控件MSComm是将RS-232的初级操作予以封装,用户以高级的BasiC语法即可利用RS-232与外界通信并不需要了解其他有关的初级操作,因此使用方便。
MSComm控件初始化:
MSComm1. CommPort= 2 设置串口2
MSComm1. SettingS=“9600,N,8,1” 设定工作方式
MSComm1. InBufferSize = 10 根据1次传1个CAN帧,设置输入缓冲区大小
MSComm1. InputMode = 1 二进制形式接收
MSComm1. InputLeN= 0 一次读出输入缓冲区中的所有数据
MSComm1. OutBufferSize = 10 输出缓冲区大小的设置
MSComm1. OutBufferCount= 0 清空输出缓冲区
MSComm1. PortOpeN= True 打开串口
PC机与单片机MSC51之间的通信约定如下:一般情况下PC与多个MSC51单片机系统进行主从式通信,其方案是MSC51采用串口工作方式3,即11位异步接收/发送方式,有效数据为9位,其中第9位为地址/数据信息的标志位,以此区分各从机。但现在PC机采用VB编程,其MSComm控件为标准的10位串口通信,包括8位标准数据和数据的起始位和停止位。将单片机串口设为工作方式1,即改为10位异步接收/发送方式,通讯流程如下:
通讯时首先发通信开始标志,接着发送各下位机单片机的地址信号和芯片的片选信号,然后发送单片机的工作命令字。再往下即进行数据处理,转入相应的处理功能模块,最后对数据进行效验。这个通讯流程非常简便,实现了PC机与单片机之间的主从式通讯。
以下为VB的发送接收程序:
Private SuBcmdSendàClick() 使用按钮控件
MSComm1. Output= txtSend. Text 将传送区内的字符串以Output属性送出
End Sub
Private SuBFormàLoad() 窗体的加载事件
MSComm1. PortOpeN= True 将通讯断口开启,通讯参数也可以在开启前先设定
MSComm1. RThreshold = Val (txtThreshold. Text) 设定引发接收事件的接收阈值,使程序一执行便开启通讯端口,将接收的阈值设定为阈值,设定文本框内的值。
End Sub
Private SuBMSComm1. OnComm() 通讯控件的OnComm事件。引发接收事件后,将字符收进来并放在接收的文本框中
SelectCase MSComm1. CommEvent 根据下面每一个case 语句处理每个事件和错误事件
Case comEvCD CD 线的状态发生变化
Case commEvReceive 收到Rthreshold # of
txtReceive. Text= txtReceive. Text+ Trim(MSComm1. Input)&vbCrLf
Case comEvSend 传输缓冲区有Sthreshold 个字符
End Select
End Sub
Private SuBtxtThreshold Change ( ) p阈值设定文本框的Change事件
MSComm1. Rthreshold = Val (txtThreshold. Text) p当设定的阈值变化时,实时改变通讯对象的属性
End Sub
AT89C51单片机部分
单片机部分采用C语言编程。C语言编程具有快捷、模块功能强大、可靠性好、效率高等优点。其中程序初始化包括设定串口工作方式,定时器、中断寄存器初始化,各变量的初始化。
TMOD = 0x20; //定时器1为发生器
SCON= 0x50; //串口工作方式1
TH1= 0xfd ; //设定波特率= 9600bit/s
TL1= 0xfd ;
EA= 1; //开中断
ES= 1; //允许串口中断
TR1= 1; //启动定时器T1
SPECHAR = 0xff ; //设定通讯开始标志
程序采用中断接收,查询发送的方式。串口中断服务程序流程图如图3所示。
SJA1000控制器部分
初始化子程序CANINIT()
选用CAN2. 0协议构建CAN总线控制网络,对SJA1000的初始化主要包括工作方式的设置、验收代码寄存器ACR、验收屏蔽寄存器AMR、波特率的参数设置等。
void canàinit(void) /*SJA1000的初始化子函数*/
{control = 1; /*禁止超载、出错及接收中断,并置复位请求位使其进入复位状态*/
while (control&0x01== 0);
acceptanceàcode = 0x01; /*验收码寄存器(存机号1号)*/
acceptanceàmask= 0xfe ; /*验收屏蔽码寄存器*/
busàtimingà0= 0x03; /*总线定时寄存器0,同步跳转宽度
T0= T,BPS= 125 k*/
busàtimingà1= 0x18; /*总线定时寄存器1,T1= 9T,T2=2T,波特率为500kbit/S*/
outputàcontrol = 0x1A; /*正常输出方式,TX1引脚悬浮*/
clockàdivider = 0x40; /*BASICCAN模式,RX1接固定电平*/
control = 0x1A; /*清复位请求,使其进入工作状态*/
}
发送canàsend()
发送子程序负责节点报文的发送,由CAN控制器SJA1000独立完成,将命令寄存器里的发送请求标志置位,即可发送SJA1000发送缓冲区中的报文。
void canàsend(unsigned char ID ,char*xdata) /*该子函数完成一帧数据的发送*/
{while ( (status&0x10)>> 4 == 1)àNOPà; /*检查上次请求发送是否完成*/
while ( (status&0x04)>> 2== 0)àNOPà;
Transmitbuffer1= ID;
Transmitbuffer2= 0x08;
Transmitbuffer3= txdata[0] ;
Transmitbuffer10= txdata[7] ;
Command = 0x05 ; /*发送请求*/
while ( (status&0x08)>> 3== 0);
}
接收子程序canàreceive ()
接收子程序负责节点报文的接收。SJA1000自动接收发往该节点的数据并将收到的数据放到它的接收缓冲器中。
SJA1000的报文接收主要有2种方式:中断接收方式和查询接收方式。系统采用的是中断接收方式。
{unsigned char ir ;
ir = interrupt; /*获得SJA1000的中断状态*/
EA= 0;
If ( (ir&0x04)>> 2== 1)error ( ); /*如果是出错中断,则调出错处理函数*/
If ( (ir&0x08)>> 3== 1)overruN( ); /*如果是超载中断,则调超载处理函数*/
While ( ( (ir&0x04)>> 2== 1)‖( ( (ir&0x08)>> 3)== 1){àNOPà;}
RxID[0] = Receivebuffer1;
RxID[0] = Receivebuffer2;
If ( ( (Receivebuffer2&0x10)>> 4)== 0) /*如果是数据帧,则接收数据*/
{Rxdata[0] = Receivebuffer3;
.
Rxdata[7] = Receivebuffer10;
Command = 0x04 ; /*SJA1000的接收缓存器被释放*/
}
else if ( ( (Receivebuffer2&0x10)>> 4)== 1) /*如果是远程帧,则作相应处理*/
{ /*相应处理程序*/
EA= 1;
}
}
CAN总线及CAN控制器SJA1000简介
CAN总线最初是德国Bosch公司在1986 年为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种支持分布式实时控制系统的串行数据通讯总线。CAN总线与其它通信网的显著不同之处在于:
(1)报文传送中不包含目标地址,它是以全网广播为基础,各接收站根据报文中反映数据性质的标识符过滤报文,该收的收下,不收的弃用。其好处是可线上网下网、即插即用和多站接收。
(2)特别强化了对数据安全性的关注,满足控制系统及其它较高数据要求的系统需求。另外CAN总线采用短帧结构,借助接收滤波的多地址帧传送,受干扰概率低,每帧信息都有CRC校验及其它检错措施。响应远程数据请求,配置灵活,具有全系统的数据相容性。节点数主要取决于总线驱动电路,目前最多可达110个节点。CAN总线符合ISO11898标准,通信速率高,最大传输速率可达1Mbit/S,最大传输距离为10km,传输介质可为双绞线。基于CAN总线以上的特点,把它应用于系统分布比较分散且需要在同一总线上挂接多个节点的场合是非常适合的。
目前广泛流行的CAN总线器件有两大类:一类是独立的CAN控制器,如PhilipS公司的PCA82C200,SJA1000及Intel82256/82257等;另一类是带有在片CAN的微控制器,如P8XC582等。其中Philips公司的PCA82C200是符合CAN2. 0A协议的总线控制器,SJA1000是它的替代产品,它是应用于汽车和一般工业环境的独立CAN总线控制器。具有完成CAN通信协议所要求的全部特性。经过简单总线连接的SJA1000可完成CAN总线的物理层和数据链路层的所有功能。其硬件与软件设计和PCA82C200的基本CAN模式(BasicCAN)兼容。同时,新增加的增强CAN模式( PeliCAN)还可支持CAN2. 0B协议。根据当前市场开发工具和课题的实际需要,选用SJA1000作为CAN控制器,同时使用了CAN控制器接口芯片PCA82C250。
SJA1000有两种工作模式:基本模式和增强模式。在基本模式下,SJA1000只可收发标准数据帧(标准数据帧的标识符为11位),且错误报警的极限值不能修改;在增强模式下,SJA1000既可接收标准数据帧,也可接收扩展数据帧(扩展数据帧的标识符为29位),可修改错误报警的极限值,并且SJA1000具有更加灵活的滤波方式,能够根据数据帧的标识符有选择地接收一些数据帧。另外,增强模式下的SJA1000能够进行自检,即可通过自发自收一组报文来判断该控制节点是否正常地挂在CAN总线上。使用者所要做的主要工作是SJA1000的初始化,收发报文的处理以及对节点脱离总线的检测量与处理。
RS-232标准
串行通信由于接线少、成本低,在数据采集和控制系统中得到了广泛的应用,1969年,美国电子工业协会( EIA)公布了RS-232C作为串行通信接口的电气标准,该标准定义了数据终端设备(DTE)和数据通信设备(DCE)间按位串行传输的接口信息,合理安排了接口的电气信号和机械要求,在世界范围内得到了广泛的应用。
系统总体结构原理及设计
该适配器利用RS-232串行通信口及CAN总线进行数据通信,实现上位机与各智能节点间的通信任务,包括控制台(上位机)向下传输命令和下位机数据的返回,以完成对下层设备的监控。图1为系统结构框图。PC机通过RS-232与CAN控制器SJA1000通信,实现信息在CAN总线上的发送与接收。底层各智能节点根据应用的不同具有不同功能,但都具有与CAN总线通信能力可以上传数据和接收数据。
CAN总线接口硬件设计
图2为CAN总线通信接口适配器硬件设计简图。
PCA82C250提供对总线的差动发送和对CAN控制器的差动接收功能,也增大了通信距离,提高了系统的瞬间抗干扰能力,保护总线,降低射频干扰(RFI),实现了热防护等功能。
系统软件设计
软件设计分PC机Visual BasiC编程和AT89C51单片机C语言编程2部分。
PC机部分
采用VB6. 0编程,这样界面非常直观,人机交互效果好。VB提供了具有通讯功能的MSComm. OCX控件,该控件可设置串行通信的数据发送和接收,对串口状态及串口通信的信息格式和协议进行设置。MSComm控件提供2种处理通讯的方式:(1)事件驱动通讯,即发送或接收数据过程中触发ONCOMM事件,通过编程访问CommEvent属性了解通信事件的类型,分别进行各自的处理;(2)查询方式,通过检查CommEvent属性的值来查询事件和错误。采取查询方式。控件MSComm是将RS-232的初级操作予以封装,用户以高级的BasiC语法即可利用RS-232与外界通信并不需要了解其他有关的初级操作,因此使用方便。
MSComm控件初始化:
MSComm1. CommPort= 2 设置串口2
MSComm1. SettingS=“9600,N,8,1” 设定工作方式
MSComm1. InBufferSize = 10 根据1次传1个CAN帧,设置输入缓冲区大小
MSComm1. InputMode = 1 二进制形式接收
MSComm1. InputLeN= 0 一次读出输入缓冲区中的所有数据
MSComm1. OutBufferSize = 10 输出缓冲区大小的设置
MSComm1. OutBufferCount= 0 清空输出缓冲区
MSComm1. PortOpeN= True 打开串口
PC机与单片机MSC51之间的通信约定如下:一般情况下PC与多个MSC51单片机系统进行主从式通信,其方案是MSC51采用串口工作方式3,即11位异步接收/发送方式,有效数据为9位,其中第9位为地址/数据信息的标志位,以此区分各从机。但现在PC机采用VB编程,其MSComm控件为标准的10位串口通信,包括8位标准数据和数据的起始位和停止位。将单片机串口设为工作方式1,即改为10位异步接收/发送方式,通讯流程如下:
通讯时首先发通信开始标志,接着发送各下位机单片机的地址信号和芯片的片选信号,然后发送单片机的工作命令字。再往下即进行数据处理,转入相应的处理功能模块,最后对数据进行效验。这个通讯流程非常简便,实现了PC机与单片机之间的主从式通讯。
以下为VB的发送接收程序:
Private SuBcmdSendàClick() 使用按钮控件
MSComm1. Output= txtSend. Text 将传送区内的字符串以Output属性送出
End Sub
Private SuBFormàLoad() 窗体的加载事件
MSComm1. PortOpeN= True 将通讯断口开启,通讯参数也可以在开启前先设定
MSComm1. RThreshold = Val (txtThreshold. Text) 设定引发接收事件的接收阈值,使程序一执行便开启通讯端口,将接收的阈值设定为阈值,设定文本框内的值。
End Sub
Private SuBMSComm1. OnComm() 通讯控件的OnComm事件。引发接收事件后,将字符收进来并放在接收的文本框中
SelectCase MSComm1. CommEvent 根据下面每一个case 语句处理每个事件和错误事件
Case comEvCD CD 线的状态发生变化
Case commEvReceive 收到Rthreshold # of
txtReceive. Text= txtReceive. Text+ Trim(MSComm1. Input)&vbCrLf
Case comEvSend 传输缓冲区有Sthreshold 个字符
End Select
End Sub
Private SuBtxtThreshold Change ( ) p阈值设定文本框的Change事件
MSComm1. Rthreshold = Val (txtThreshold. Text) p当设定的阈值变化时,实时改变通讯对象的属性
End Sub
AT89C51单片机部分
单片机部分采用C语言编程。C语言编程具有快捷、模块功能强大、可靠性好、效率高等优点。其中程序初始化包括设定串口工作方式,定时器、中断寄存器初始化,各变量的初始化。
TMOD = 0x20; //定时器1为发生器
SCON= 0x50; //串口工作方式1
TH1= 0xfd ; //设定波特率= 9600bit/s
TL1= 0xfd ;
EA= 1; //开中断
ES= 1; //允许串口中断
TR1= 1; //启动定时器T1
SPECHAR = 0xff ; //设定通讯开始标志
程序采用中断接收,查询发送的方式。串口中断服务程序流程图如图3所示。
SJA1000控制器部分
初始化子程序CANINIT()
选用CAN2. 0协议构建CAN总线控制网络,对SJA1000的初始化主要包括工作方式的设置、验收代码寄存器ACR、验收屏蔽寄存器AMR、波特率的参数设置等。
void canàinit(void) /*SJA1000的初始化子函数*/
{control = 1; /*禁止超载、出错及接收中断,并置复位请求位使其进入复位状态*/
while (control&0x01== 0);
acceptanceàcode = 0x01; /*验收码寄存器(存机号1号)*/
acceptanceàmask= 0xfe ; /*验收屏蔽码寄存器*/
busàtimingà0= 0x03; /*总线定时寄存器0,同步跳转宽度
T0= T,BPS= 125 k*/
busàtimingà1= 0x18; /*总线定时寄存器1,T1= 9T,T2=2T,波特率为500kbit/S*/
outputàcontrol = 0x1A; /*正常输出方式,TX1引脚悬浮*/
clockàdivider = 0x40; /*BASICCAN模式,RX1接固定电平*/
control = 0x1A; /*清复位请求,使其进入工作状态*/
}
发送canàsend()
发送子程序负责节点报文的发送,由CAN控制器SJA1000独立完成,将命令寄存器里的发送请求标志置位,即可发送SJA1000发送缓冲区中的报文。
void canàsend(unsigned char ID ,char*xdata) /*该子函数完成一帧数据的发送*/
{while ( (status&0x10)>> 4 == 1)àNOPà; /*检查上次请求发送是否完成*/
while ( (status&0x04)>> 2== 0)àNOPà;
Transmitbuffer1= ID;
Transmitbuffer2= 0x08;
Transmitbuffer3= txdata[0] ;
Transmitbuffer10= txdata[7] ;
Command = 0x05 ; /*发送请求*/
while ( (status&0x08)>> 3== 0);
}
接收子程序canàreceive ()
接收子程序负责节点报文的接收。SJA1000自动接收发往该节点的数据并将收到的数据放到它的接收缓冲器中。
SJA1000的报文接收主要有2种方式:中断接收方式和查询接收方式。系统采用的是中断接收方式。
{unsigned char ir ;
ir = interrupt; /*获得SJA1000的中断状态*/
EA= 0;
If ( (ir&0x04)>> 2== 1)error ( ); /*如果是出错中断,则调出错处理函数*/
If ( (ir&0x08)>> 3== 1)overruN( ); /*如果是超载中断,则调超载处理函数*/
While ( ( (ir&0x04)>> 2== 1)‖( ( (ir&0x08)>> 3)== 1){àNOPà;}
RxID[0] = Receivebuffer1;
RxID[0] = Receivebuffer2;
If ( ( (Receivebuffer2&0x10)>> 4)== 0) /*如果是数据帧,则接收数据*/
{Rxdata[0] = Receivebuffer3;
.
Rxdata[7] = Receivebuffer10;
Command = 0x04 ; /*SJA1000的接收缓存器被释放*/
}
else if ( ( (Receivebuffer2&0x10)>> 4)== 1) /*如果是远程帧,则作相应处理*/
{ /*相应处理程序*/
EA= 1;
}
}