基于DeviceNet总线的从设备通迅适配器设计
时间:11-29
来源:互联网
点击:
标识对象DeviceNet产品一般都有一个标识对象实例(1实例)。此实例包含各种属性,如供货商ID、设备类型、产品代码、版本、状态、序列号、产品名称和说明。标识对象要求的服务是Get_Atrribute_Single和Reset。
报文路由对象 DeviceNet产品一般都有一个报文路由对象实例(1实例)。报文路由对象向其它对象传送显式报文。一般在DeviceNet网络中它不具有外部可视性。
DeviceNet对象 DeviceNet产品一般都有一个DeviceNet对象实例(1实例)。该实例有下列属性:节点地址或MAC ID ,波特率,总线关闭,总线 关闭计数器,单元选择和主机的MAC ID 。唯一要求的服务是Get_Atrribute_Single。
汇编对象 DeviceNet产品一般具有一个或多个可选的汇编对象。这些对象的主要任务就是将来自不同应用对象的多个属性(数据)组合成一个能够随单个信息传送的属性。
连接对象 DeviceNet产品一般至少包括两个连接对象。每个连接对象代表DeviceNet网络上两节点间虚拟连接中的一个端点。两种连接类型分别称为显式报文连接和I/O报文连接。显式报文包括属性地址,属性值和服务代码来描述所请求的行为。I/O报文只包含数据。I/O报文中,所有有关如何处理数据的信息都包含在与该I/O报文相关的连接对象中。
参数对象 在带有可配置参数的设备中都用到了可选的参数对象。将为每个可配置的参数引入一个实例。参数对象带有设备配置参数,提供访问所有参数的标准组态工具。参数对象的配置选项属性可以包括数值,量程,文本和限制等。
应用对象 配备了汇编对象或参数对象的设备通常至少应包含一个应用对象, 卷II的第六章DeviceNet对象库中有大量的标准应用对象。
设备描述(Device Profiles) DeviceNet规范不仅仅是一个物理连接协议规范。它通过定义标准的设备模型促进不同厂商设备之间的互操作性。属于同一设备模型的所有设备都必须支持共同的标识和通讯状态数据。设备描述是针对各种设备而定义的。设备描述中包括设备各种特定的数据。符合设备类型描述的多个供货商提供的简单设备(例:按钮,马达启动器,光电池,气动阀执行器)在逻辑上是可互换的。
设备描述包括下列各项:
l 设备对象模型定义-定义设备对象模型如上图所示。通常用表格列出设备中存在的所有对象类,各类中的实例数,各个对象如何影响行为,以及每个对象的公共接口。
l 设备I/O数据格式定义-通常包含用于简化和加快数据传输的汇编对象的定义,汇编对象包含所需要的数据组件的地址(类,实例和属性)。
l 设备可配置参数的定义和访问这些参数的公共接口。该信息包含在电子数据文文件(EDS)中,EDS包含在设备的用户文件中。
DeviceNet规范定义了一个电子数据文文件(EDS),EDS是一个简单文件格式,供货商可以将产品的特殊信息提供给其它供货商。这样可以具有友好的用户配置工具,可以很容易的更新,无需经常修正配置软件工具。
上面只讲述了DeviceNet协议规范的概貌,DeviceNet协议规范还是相当复杂的,整个协议规范有1000多页,有兴趣的读者可到ODVA官方网站下载。只有对协议规范有一定深度的理解后,才可以着手思考如何开发基于DeviceNet协议从设备适配器的软件系统。
三、 通迅适配器软件系统设计
下面主要介绍通讯协议的设计,软件的实现是以DeviceNet协议规范的2.0版本为指导的。不同的应用有不同的具体实现,本文只给出设计的原理和指道思想及原则。
1 DeviceNet通讯设备的上电状态流图
每个设备上电以前都有一个例行的状态流转过程,该过程描述了设备能够在DeviceNet上通讯之前必须完成的以下工作,例如重复MAC ID检测等;以及对设备通讯产生影响的网络事件。
DeviceNet状态流图
上图是DeviceNet设备上电后的状态流转图,其中一共有4个状态:发送重复MAC ID检测报文状态,等待重复MAC ID检测报文状态,在线状态,通讯出错状态。设备在各个状态之间的流转是根据网络的事件情况,如下所示:
网络事件/状态转换关系
2 CAN芯片的初始化
建立在CAN总线的通讯之前要预先有一些初始化过程。一般,独立式CAN芯片SJA1000在上电后或者上电后软件功能的重置时要初始化一下工作寄存器。当系统上电后,处理器首先运行自己的特殊初始化过程,然后再进入SJA1000的连接建立过程(SJA1000的17号管脚获得一个Reset低电平脉冲,并进入Reset模式)。在初始化SJA1000的寄存器之前,主微处理器应该检测Reset的mode/request标志,如果SJA1000已经是Reset模式,因为所有的寄存器只能在Reset模式下进行写操作,所有的寄存器都将获得的相应的配置信息。
当完成所有的初始化工作后,SJA1000就进入工作(Operation)模式,并且使CAN控制器的中断功能有效。SJA1000的初始化流程如图2所示。
下面是一段用C51编写的SJA1000初始化及一个模拟发送、接收过程的程序。
程序说明:主程序首先对SJA1000进行初始化,config1(),把接收中断打开;然后等待。
当监测到网络上有数据进入SJA1000的buffer时,进入中断服务程序service_int1()interrupt 2
using 1,并把接收数据放入buffer数组中。
首先判断是否该数据是针对5号节点的,如果不是,则丢弃,否则接收。
判断收到的10个数据属于哪一类,根据逻辑发送相应响应。
发送程序send(UIN*value,int number)中,当发送缓冲区为空,则将需要发送的数据(在Sbuffer中)发给Master设备。
include
include
define UINT unsigned int
UINT a;
UINT buffer[10];
UINT Sbuffer[6];
UINT b=0;
int i;
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_3=P1^3;
void config1() //对SJA1000进行初始化
{a=0;
XBYTE[0x4000]=0x01; //复位模式
XBYTE[0x4004]=0x11; //接收中断使能,wake_up中断使能
XBYTE[0x4005]=0xFF; //Accept Mask Register设置
XBYTE[0x4006]=0x00; //Bus Timing 0
XBYTE[0x4007]=0x1C; //时钟周期的设置
XBYTE[0x4008]=0xFA; //输出控制寄存器
XBYTE[0x401F]=0x48; //clock divider
EA=1;
EX1=1;
}
void send(UINT*value,int number)
{int i;
do
{
}while(XBYTE[0x4002]4= =0); //发送缓冲区为空,才能继续发送
for(i=0;iXBYTE[0x400A+i]=value[i]; //将发送的内容放入缓冲区
XBYTE[0x4001]=0x01; //发送命令
P1_0=!P1_0;
P1_1=0;
P1_3=!P1_3; //灯闪烁,以说明在发送中
XBYTE[0x7fff]=P1;
}
void service_int1() interrupt 2 using 1 //接收中断服务程序
{
UINT count;
UINT Status;
int c;
Status=XBYTE[0x4003]; //读一次则清中断
if (b700)
{for (c=0;c10;c++)
{buffer[c]=XBYTE[0x4014+c]; //接收信息放入buffer中
XBYTE[0x0000+10*b+c]=buffer[c];
}
b++;
}
XBYTE[0x4001]=0x04;
if (buffer[0]= =0x85)
switch (buffer[1]) //对buffer内容进行判断,决定response内容
{
case 0xc6;
Sbuffer[0]=0x85;
Sbuffer[1]=0x63;
Sbuffer[2]=0x00;
Sbuffer[3]=0xcb;
Sbuffer[4]=0x00;
send (Sbuffer,5);
break;
case 0x86;
{if (buffer[7]= =0x00)
Sbuffer[0]=0x85;
Sbuffer[1]=0x63;
Sbuffer[2]=0x00;
Sbuffer[3]=0xcb;
Sbuffer[4]=0x00;
send (Sbuffer,5);
}
else
{Sbuffer[0]=0x85;
Sbuffer[1]=0x64;
Sbuffer[2]=0x00;
Sbuffer[3]=0x94;
Sbuffer[4]=0x0e;
Sbuffer[5]=0xff;
send (Sbuffer,6);
}
}
break;
case 0x85;
{if (buffer[6]= =0x02)
Sbuffer[0]=0x85;
Sbuffer[1]=0x64;
Sbuffer[2]=0x8e;
Sbuffer[3]=0x00;
Sbuffer[4]=0x00;
send (Sbuffer,6);
}
else
{Sbuffer[0]=0x85;
Sbuffer[1]=0x64;
Sbuffer[2]=0x00;
Sbuffer[3]=0x8e;
Sbuffer[4]=0x01;
Sbuffer[5]=0x00;
send (Sbuffer,6);
}
}
break;
case 0x87;
Sbuffer[0]=0x85;
Sbuffer[1]=0x64;
Sbuffer[2]=0x00;
Sbuffer[3]=0x90;
Sbuffer[4]=0x50;
Sbuffer[5]=0x00;
send (Sbuffer,6);
break;
case 0xA0;
Sbuffer[0]=0x78;
Sbuffer[1]=0xA1;
Sbuffer[2]=0x07;
send (Sbuffer,3);
break;
case 0xA1;
Sbuffer[0]=0x78;
Sbuffer[1]=0xA1;
Sbuffer[2]=0x07;
send (Sbuffer,3);
break;
}
}
void main ()
{
config1 ();
XBYTE[0x4000]=0x22; //operation mode
While (1)
{;}
}
3 DeviceNet通讯适配器的收发中断和时钟中断的设计
CAN控制器和微处理器的数据交换可以使用中断方式和周期轮询的方式。从响应速度和执行的效率来讲,我们的应用环境使用中断的方式。因此我们必须编写自己的收发中断处理函数,其功能是将CAN控制器缓冲区中的报文拷贝到一个临时的全局缓冲区,并将该缓冲区作为高层协议处理和底层收发处理的一个接口,这样的设计具有良好的可扩展性。如果将来使用其它厂家的CAN控制器,所做的修改也仅仅是改动一些与具体硬件相应的几个底层函数。我们只要定义好互相通讯的接口,就可以将软件和硬件进行分离,在团队开发的环境中可以加快工作的进度和效率。
另外,通讯协议中经常要用到一些定时的功能,因而我们也需要在底层编写一个定时中断处理程序,该函数使用一个硬件定时器,以一个最小的计时单位周期性的为上层应用提供计时状态。
图2 SJA1000的初始化流程
4 DeviceNet通讯适配器的报文收发程序和分段服务
这里所讲的报文收发协议对不同的通讯协议有不同的定义。另外,CAN的数据长度不能超过8个字节,如何支持大于8个字节的报文要涉及到分段服务。分段协议信息由一个字节组成,其中高2位表示分段的类型,低6位作为分段的计数器,用来标识每个数据包,其计算方式是:fragmentCount=(fragmentcount+1) mod 64。下面是具体的分段的类型:
因此,在程序的设计中应当加入对分段服务协议的支持。
对于发送报文的处理与接收的过程是一个逆向过程。需要注意的是编写程序的时候要严格按照DeviceNet协议规范的定义,否则将产生不可预测的错误,为将来的协议一致性测试和底层调试都带来许多麻烦。
5 DeviceNet通讯适配器的主程序的设计
软件由头文件、初始化程序、功能子程序和主程序组成。
软件的组成结构提供了硬件和软件升级的方便。软件中将与主处理器、CAN控制器等硬件接口的部分比较独立地设计,而主程序和功能子程序主要集中于协议的完成。对将来的硬件改型和可能的协议修改都提供了较大的方便。
软件以Franklin C51语言编写,通过伟福E51L单片机开发装置进行调试。
软件结构图如下:
5.1 软件功能分解
软件由头文件、初始化程序、功能子程序和主程序组成。其功能分解如下:
头文件:定义所有的参数、类结构和函数,定义要使用的硬件资源(如定时器和寄存器等)变量名称;
初始化程序:完成对主处理器的内存及硬件(如堆栈、定时器等)初试化,完成CAN控制器的初始化。
功能子程序:详见各模块介绍。
主程序组成:主控制流程。
5.2 软件各模块功能详述
模块按以下四个部分来介绍:头文件,初始化程序,功能子程序,主程序
说明:泵和阀的实现程序非常类似,两者只相差一些参数,故此处以泵的源程序作为例子进行各个程序段的分析和说明。(详见源程序)
5.2.1 头文件
其主要操作为:
包含(include)要使用的其它头文件: reg51.h 51系列寄存器头文件
absacc.h 51系列硬件资源头文件
string.h C语言的字符操作头文件
定义(define)要使用的用户自定义数据类型;定义类(class)ID;定义连接的类型;
定义各实例(instacne)ID和定时器数量;定义全局状态(status)字对应位的内容;
定义全局事件(event)字对应位的内容;定义DeviceNet错误代码和附加错误代码;
定义DeviceNet服务代码;定义分段(fragment)值;定义连接状态;其它附加的定义;
类结构定义: Identity,DeviceNet,Connection,Message Router,Assembly,Discrete Output,
Analog Input,Analog Output
5.2.2 初始化程序
其主要操作为:SJA1000初始化;定时器初始化;各结构对象初试化;
5.2.3 功能子程序
其主要操作为:具体定义在主程序中调用的各子程序;双口RAM中断子程序;定时器中断子程序;
5.2.4 主程序
当实现所有的功能模块以后,最重要的是如果构造一个有机的主程序模块,将这些零散的模块组织起来,进行系统的初始化工作。另外还要设计一个优化的循环体周期性的执行以对DeviceNet网络上的报文产生动作。
因为我们实现的是一个从站适配器,一般在轮询的情况下只对主设备的请求报文产生相应的应答,而不会主动发送报文,除了上电时的重复MAC ID例行检测。如何构造循环体是关键,我们这里采用了事件的方式,主循环体周期对网络事件的不同可能的状态产生动作。程序中定义不同的网络事件,主程序循环体对代表这些事件的标志位不停的轮询,当某个标志位因网络事件的触发而被置1的时候,主程序就进入相应的子程序进行对应事件的操作。操作完毕之后清楚标志位,退回到主程序循环中继续轮询所有的事件标志位。
其主要操作为:设置数据缓冲区;定义全局变量;开时钟;开中断;进行主循环;
结束语
由本通讯适配器已于2002年3月13日在日本京都ASTEM RI通过ODVA一致性测试,其FCS已经成功的应用于2001年第2届北京中国国际现场总线技术交流会暨展览会,第3届上海国际工业博览会,吴忠仪表智能调节阀,东莞垃圾焚烧发电厂中的给水控制系统中。由于采用现场总线技术,取得了显著的经济效益。
DeviceNet总线 从设备 通迅适配器 相关文章:
- DeviceNet总线系统在宝莱 A4轿车后轴装配线中的应用(12-13)
- DeviceNet总线应用层协议的实现(05-09)
- DeviceNet总线在智能配电网络系统中的应用(11-29)
- 基于DeviceNet总线的智能配电应用(10-24)
- I2C器件的从设备地址的设置(11-28)
- 基于Linux的USB主/从设备之间的三种通信方式(10-26)