软件设计Word格式.docx
《软件设计Word格式.docx》由会员分享,可在线阅读,更多相关《软件设计Word格式.docx(31页珍藏版)》请在冰豆网上搜索。
UDP协议:
支持点对点、一点对多点的UDP数据包通信。
(3)RS-232串口数据收发模块
RS-232串口采用中断方式实现对现场总线数据的收发。
4.2系统初始化模块设计
在正式创建工程,编译相关实现代码之前,我们需要对系统进行初始化,其中包括对串口、对以太网网口的初始化,地址等进行相关的配置工作,也包括一些所使用到的宏定义。
4.2.1串口初始化
#definerULCON0(*(volatileunsigned*)0x50000000)//UART0Linecontrol
#definerUCON0(*(volatileunsigned*)0x50000004)//UART0Control
#definerUFCON0(*(volatileunsigned*)0x50000008)//UART0FIFOcontrol
#definerUMCON0(*(volatileunsigned*)0x5000000c)//UART0Modemcontrol
#definerUTRSTAT0(*(volatileunsigned*)0x50000010)//UART0Tx/Rxstatus
#definerUERSTAT0(*(volatileunsigned*)0x50000014)//UART0Rxerrorstatus
#definerUFSTAT0(*(volatileunsigned*)0x50000018)//UART0FIFOstatus
#definerUMSTAT0(*(volatileunsigned*)0x5000001c)//UART0Modemstatus
#definerUBRDIV0(*(volatileunsigned*)0x50000028)//UART0Baudratedivisor
//littleendian
#definerUTXH0(*(volatileunsignedchar*)0x50000020)//UART0TransmissionHold
#definerURXH0(*(volatileunsignedchar*)0x50000024)//UART0Receivebuffer
4.2.2网口初始化
#definerEXTINT0(*(volatileunsigned*)0x56000088)//Externalinterruptcontrolregister0
#definerEINTMASK(*(volatileunsigned*)0x560000a4)//Externalinterruptmask
#definerEINTPEND(*(volatileunsigned*)0x560000a8)//Externalinterruptpending
在初始化所需要的的函数程序后,开始对核心操作系统μC/OS-II进行移植。
4.3核心操作系统μC/OS-II模块
4.3.1μC/OS-II嵌入式系统在ARM上的移植
为了本系统有更为快速的用户响应,本设计中移植了μC/OS-II。
μC/OS-II是一款完全公开的源代码,具有以下几个特点:
(1)可移植性(Portable)
绝大部分C/OS-II的源码是用移植性很强的ANSIC写的。
和微处理器硬件相关的那部分是用汇编语言写的。
汇编语言写的部分已经压到最低限度,使得C/OS-II便于移植到其他微处理器上。
C/OS-II可以在绝大多数8位、16位、32位以至64位微处理器、微控制器、数字信号处理器(DSP)上运行。
(2)可固化(ROMable)
C/OS-II是为嵌入式应用而设计的,这就意味着,只要用户有固化手段(C编译、连接、下载和固化),C/OS-II可以嵌入到用户的产品中成为产品的一部分。
(3)可裁剪(Scalable)
可以只使用C/OS-II中应用程序需要的那些系统服务。
也就是说某产品可以只使用很少几个C/OS-II调用,这样可以减少产品中的C/OS-II所需的存储器空间(RAM和ROM)。
这种可剪裁性是靠条件编译实现的。
(4)多任务
C/OS-II可以管理64个任务,然而,目前这一版本保留8个给系统。
应用程序最多可以有56个任务
(5)可确定性
全部C/OS-II的函数调用与服务的执行时间具有可确定性。
(6)任务栈
每个任务有自己单独的栈,C/OS-II允许每个任务有不同的栈空间,以便压低应用程序对RAM的需求。
(7)系统服务
C/OS-II提供很多系统服务,例如邮箱、消息队列、信号量、块大小固定的内存的申请与释放、时间相关函数等。
(8)中断管理
中断可以使正在执行的任务暂时挂起,如果优先级更高的任务被该中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达255层。
(9)稳定性与可靠性
C/OS-II获得美国航空管理局(FAA)的认可,确定可以用于飞行器中。
μC/OS-II内核介绍:
μC/OS-II主要有一个内核,只有任务管理和任务调度,无文件系统、界面系统、外设管理系统等。
其特点是小巧、源代码公开、注解详细、实时性强、可移植性好、多任务、基于优先级的可剥夺型调度。
μC/OS-II是专门为单片机嵌入式系统应用而设计的,主体代码用标准的ANSIC语言编写而成,十分易于移植。
μC/OS-II是一种基于优先级的抢占式多任务实时操作系统,包含了实时内核、任务管理、时间管理、任务间通信同步(信号量,邮箱,消息队列)和内存管理等功能。
它可以使各个任务独立工作,互不干涉,很容易实现准时而且无误执行,使实时应用程序的设计和扩展变得容易,使应用程序的设计过程大为减化。
μC/OS-II的内核总共有16个文件,其中11个文件与微处理器类型无关,移植后无需修改,可直接使用;
3个文件与CPU类型相关,在移植时需要根据CPU情况进行修改;
2个文件与具体应用有关。
如图4.4:
图4.4μC/OS-II内核文件
多任务的并发执行通常依赖于一个多任务操作系统,多任务操作系统的核心是系统调度器,它使用任务控制块(TCB)来管理任务调度功能。
TCB用来保存任务的当前状态、优先级、要等待的事件或资源、任务程序代码的起始地址、初始堆栈指针等信息。
实时应用程序设计的关键就是确定如何把问题分割成多个任务,以及如何确定每个任务的优先级和任务之间的通信。
典型地,每个任务都是一个无限的循环,每个任务都处在休眠态、就绪态、运行态、挂起态(等待某一事件发生)和被中断态等五种状态之一。
一旦有更高优先级的任务准备就绪,当前正在运行的低优先级任务的CPU使用权就立即被剥夺,该任务转为就绪态或挂起态,CPU的使用权移交给那个更高优先级的任务。
这种类型的内核就是可剥夺型内核。
使用可剥夺型内核,准备就绪的最高优先级任务总能得到CPU的使用权。
如果中断服务使得一个高优先级任务准备就绪,那么中断服务完成后,被中断的任务将被挂起,高优先级的任务继续运行。
同样,若中断期间有高优先级任务准备就绪,中断服务完成以后,可剥夺型内核运行说明如下:
低优先级任务正在运行时,有一个异步事件发生,中断打入。
若此时中断是开放的,则CPU转入中断服务子程序。
假设中断服务子程序使一个更高优先级的任务进入就绪态。
中断服务完成后,应用程序不再返回到原来被中断的任务,而是执行准备就绪的高优先级任务。
中断返回到哪个任务,则由一个内核函数决定的。
高优先级任务开始处理中断服务子程序所标识的异步事件。
高优先级任务执行完毕以后挂起,内核进行任务切换。
值得注意的是:
若高优先级的任务不自我挂起,低优先级的任务就永远都没有运行的机会。
若此时没有比原来被中断的那个任务优先级更高的任务准备就绪,则被中断的任务将重新获得CPU的使用权;
若有更高优先级的任务准备就绪,那么CPU将运行这个更高优先级的任务,原被中断的任务还是得不到执行,直到没有比它更高优先级的任务准备就绪,才能重新获得CPU的控制权。
对于可剥夺型内核,CPU的使用权是可预测的和可确定的,可使任务级响应得以优化。
由于μC/OS-II的源代码完全公开的原因,因此现在很多单片机开发板都能很轻易的移植μC/OS-II。
本次设计中,所用的开发板是基于ARM9的TQ2440,也完美的移植了μC/OS-II操作系统。
移植的程序本身就实现几个简单的功能函数,但实现的功能与本次设计没有相关。
在此不作过多解释。
4.3.2核心操作系统μC/OS-II模块的建立
设计中所使用的操作系统μC/OS-II移植后,建立设计流程,实现相关功能。
本次设计中,以太网和现场数据网之间的系统程序设计目的是需要实现RS232和RJ45两种接口之间的数据交换,程序流程如下图:
图4.5系统流程图
在建立了主要的流程后,开始对μC/OS-II系统程序的建立。
图4.6应用程序实现
用户任务的定义方法如下:
voidMyTask(void*pdata)//定义用户任务
{
for(;
;
)
{
...
}
}
voidmain()
TargetInit();
//初始化目标板
OSInit();
//初始化uCOS-II
OSTimeSet(0);
//初始化系统时基
OSTaskCreate(MainTask,(void*)0,&
MainTaskStk[MainTaskStkLengh-1],MainTaskPrio);
//创建系统初始任务
OSStart();
//开始任务
return0;
值得注意的是,μC/OS-II中用户应用程序必须使用空闲任务OSTaskldle(),而且这个任务是不能用软件来删除的。
4.3应用模块设计
4.4.1TCP/IP网络协议处理模块设计
本系统中从网络上过来的以太网数据,是按照TCP/IP协议标准打包的,从现场总线过来的数据我们在这简单地看成是透明数据,所以从RS-232串口送来的数据,我们只要按照TCP/IP协议进行封包,而反过来则将以太网协议数据进行解包即可。
这就涉及到TCP/IP协议栈的问题。
网关设计的主体部分是以TCP/IP协议栈在单片机上的实现为基础的,即完成原始数据的封包与解包,实现数据格式的转换。
而涉及到的协议主要包括UDP协议、IP协议、ARP协议。
TCP/IP协议叫做传输控制/网际协议,它是Internet国际互联网络的基础。
TCP/IP是网络中使用的基本的通信协议。
TCP/IP协议的基本传输单位是数据包(datagram),TCP协议负责把数据分成若干个数据包,并给每个数据包加上包头(就像给一封信加上信封),包头上有相应的编号,以保证在数据接收端能将数据还原为原来的格式,IP协议在每个包头上再加上接收端主机地址,这样数据找到自己要去的地方,如果传输过程中出现数据丢失、数据失真等情况,TCP协议会自动要求数据重新传输,并重新组包。
总之,IP协议保证数据的传输,TCP协议保证数据传输的质量。
TCP/IP协议数据的传输基于TCP/IP协议的四层结构:
应用层、传输层、网络层、接口层,数据在传输时每通过一层就要在数据上加个包头,其中的数据供接收端同一层协议使用,而在接收端,每经过一层要把用过的包头去掉,这样来保证传输数据的格式完全一致。
封包解包协议分析
1.IP
IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层UDP层;
相反,IP层也把从UDP层接收来的数据包传送到更低层。
IP数据包是不可靠的。
IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。
4位版本
4位首部长度
8位服务类型
16位总长度
16位标识符
3位标志
13位偏移量
8位生存时间TTL
8位协议
16位首部校验和
32位IP源地址
32位目的地址
选项(可无)
数据
表4.1IP包头
我们用单片机实现TCP/IP协议要作一些简化,不考虑数据分片和优先权。
因此,在此我们不讨论服务类型和标志偏移域,只需填“0”即可。
协议“版本”为4,“头长度”单位为32Bit,“总长度”以字节为单位,表示整个IP数据报长度。
“标识”是数据包的ID号,用于识别不同的IP数据包。
“生存时间”TTL是个数量级的概念,防止无用数据包一直存在网络中。
一般每经过路由器时减1,因此通过TTL可以算出数据包到达目的地所经过的路由器个数。
“协议”域表示创建该数据包的高级协议类型。
如1表示ICMP协议,6表示TCP协议,17表示UDP协议等。
IP数据包为简化数据转发时间,仅采用头校验的方法,数据正确性由高层协议保证。
2.UDP
UDP协议模块把上层应用程序传来的数据包加上源端口和目的端口号,计算校验和并填充,然后发给IP模块即可;
UDP如果接收到IP模块送来的数据包只需进行校验,无误后根据端口号送给上层应用程序即可。
UDP的校验和字段是可选的,如果该字段值为零就说明不进行校验。
设计者把这个字段作为可选项的目的,是为了那些在可靠性很好的局域网上使用UDP的实现者尽量减少开销。
UDP协议实现如图4.7。
UDP包头内容如下:
源端口:
源端使用的端口号;
目的端口:
目的端使用的端口号;
UDP长度:
包括UDP包头以及数据在内UDP报长度;
UDP校验和:
校验UDP包是否出错,不用校验,该项可设为0。
图4.7UDP协议的实现流程图
3.ARP
ARP,即地址解析协议,实现通过IP地址得知其物理地址。
在TCP/IP网络环境下,每个主机都分配了一个32位的IP地址,这种互联网地址是在网际范围标识主机的一种逻辑地址。
为了让报文在物理网路上传送,必须知道对方目的主机的物理地址。
这样就存在把IP地址变换成物理地址的地址转换问题。
首先,ARP发送一份称为ARP请求的以太网数据帧给以太网上的所有主机,这一过程称为广播。
ARP请求数据帧中包含目的主机的IP地址,其意思是“如果你是这个IP地址的拥有者,请回答你的硬件地址”。
然后,目的主机的ARP层收到这份广
播后,识别出这是发送端在询问它的硬件地址。
最后,发送主机收到ARP应答后,使ARP进行请求一一应答交换的IP数据报文就可以实现数据传送了。
ARP是在源主机不知目的物理地址的前提下才需要的。
协议的实现可以从两个方面来考虑:
一是发送方,在以太网帧的传输中是以物理地址为目的地址的,但在应用层我们是以网络的IP地址来操作的,当给定一个目的站的IP地址时,图4.8ARP协议实现流程图
发送方软件会查询它的ARP缓存,看是否有从该IP地址到物理地址的映射。
协议流程图如图4.8所示。
HDLC帧格式及CRC校验算法设计:
在HDLC中,数据和控制报文均以帧的标准格式传送。
HDLC中的帧类似于BSC的字符块,但BSC协议中的数据报文和控制报文是独立传输的,而HDLC中的命令应以统一的格式按帧传输。
HDLC的完整的帧由标志字段(F)、地址字段(A)、控制字段(C)、信息字段(I)、帧校验序列字段(FCS)等组成。
标志段(1Byte)
地址段(1Byte)
控制段(1Byte)
信息段
(2Byte)
CRC校验段
0x7E
0xFF
Data1
Data2
Crc1
Crc2
表4.2HDLC帧格式
1.标志字段(F)
标志字段为01111110的比特模式,用以标志帧的起始和前一帧的种止。
标志字段也可以作为帧与帧之间的填充字符。
通常,在不进行帧传送的时刻,信道仍处于激活状态,在这种状态下,发方不断地发送标志字段,便可认为一个新的帧传送已经开始。
2.地址字段(A)
地址字段的内容取决于所采用的操作方式。
在操作方式中,有主站、从站、组合站之分。
每一个从站和组合站都被分配一个唯一的地址。
命令帧中的地址字段携带的是对方站的地址,而响应帧中的地址字段所携带的地址是本站的地址。
某一地址也可分配给不止一个站,这种地址称为组地址,利用一个组地址传输的帧能被组内所有拥有该组的站接收。
但当一个站或组合站发送响应时,它仍应当用它唯一的地址。
3.控制字段(C)
控制字段用于构成各种命令和响应,以便对链路进行监视和控制。
发送方主站或组合站利用控制字段来通知被寻址的从站或组合站执行约定的操作;
相反,从站用该字段作对命令的响应,报告已完成的操作或状态的变化。
该字段是HDLC的关键。
控制字段中的第一位或第一、第二位表示传送帧的类型,HDLC中有信息帧(I帧)、监控帧(S帧)和无编号帧(U帧)三种不同类型的帧。
控制字段的第五位是P/F位,即轮询/终止(Poll/Final)位。
在本课题中地址段和控制段默认为0XFF。
4.信息字段(I)
信息字段可以是任意的二进制比特串。
比特串长度未作限定,其上限由FCS字段或通信站的缓冲器容量来决定,目前国际上用得较多的是1000~2000比特;
而下限可以为0,即无信息字段。
但是,监控帧(S帧)中规定不可有信息字段。
5.帧校验序列字段(FCS)
帧校验序列字段可以使用16位CRC,对两个标志字段之间的整个帧的内容进行校验。
FCS的生成多项式CCITTV4.1建议规定的X16+X12+X5+1。
紧接着,是关于CRC校验算法的相关内容,循环冗余码CRC检验技术广泛应用于测控及通信领域。
CRC计算可以靠专用的硬件来实现,但是对于低成本的微控制器系统,在没有硬件支持下实现CRC检验,关键的问题就是如何通过软件来完成CRC计算,也就是CRC算法的问题。
CRC校验的基本思想是利用线性编码理论,在发送端根据要传送的k位二进制码序列,以一定的规则产生一个校验用的监督码(既CRC码)r位,并附在信息后边,构成一个新的二进制码序列数共(k+r)位,最后发送出去。
在接收端,则根据信息码和CRC码之间所遵循的规则进行检验,以确定传送中是否出错。
字节型算法的一般描述为:
本字节的CRC码,等于上一字节CRC码的低8位左移8位,与上一字节CRC右移8位同本字节异或后所得的CRC码异或。
字节型算法如下:
1)CRC寄存器组初始化全为1。
2)CRC寄存器组向右移8位,并保存到CRC寄存器组。
3)原CRC寄存器组高8位(右移8位)与数据字节进行异或运算,得出一个指向值表的索引。
4)索引所指的表值与CRC寄存器组做异或运算。
5)
数据指针加1,如果数据没有全部处理完,则重复步骤2)。
6)得出CRC,并取反。
程序代码如下:
unsignedshortGetCrc16(unsignedchar*pData,unsignedcharnLength)
unsignedshortfcs=0xffff;
//初始化
while(nLength>
0)
fcs=(fcs>
>
8)^crctab16[(fcs^*pData)&
0xff];
nLength--;
pData++;
return~fcs;
//取反
检查给定长度数据的16位CRC是否正确的程序如下:
bitIsCrc16Good(unsignedchar*pData,unsignedcharnLength)
//初始化
8)^crctab16[(fcs^*pData)&
}
return(fcs==0xf0b8);
//0xf0b8是CRC-ITU的"
MagicValue"
}
HDLC解帧模块的流程图:
图4.9HDLC解帧模块流程图
如图4.9所示,本模块要求从RS232串口发来HDLC协议数据,经中断函数送入缓冲区,并实现CRC校验,提取原始数据等功能。
串行口中断是以字节为单位响应的。
当协议数据从SBUF进入时,首先要存入某个变量,并对此数据进行判断,确定数据是否为帧内数据。
这个过程是以一个函数的形式实现的。
依次为判断帧头位置,设置帧标志位,判断帧尾位置,对数据进行CRC校验,执行数据存储等。
最终原始数据存入串口缓冲区。
在此过程中,事先规定HDLC帧长度为8个字节,所以要设计一个HDLC帧的缓冲区,为六个字节,即去掉标志段的剩余部分。
接收中断发生后,数据作为函数的参数进入解帧校验部分,以此提取原始信息。
若为代码如下:
unsignedcharxdataHdlcRecvBuffer[6];
unsignedcharHdlcRecvBufferTail;
unsignedcharSerialByte;
unsignedchar*p,*Datar;
unsignedchar*Datas=&
HdlcRecvBuffer[0];
bitF_times,Flagcrc;
unsignedcharf_8=0x7e;
unsignedcharACData_Len=6;
voidHdlc_ipacket(unsignedcharHSerialByte)
if(F