程序.docx
- 文档编号:268782
- 上传时间:2023-04-28
- 格式:DOCX
- 页数:18
- 大小:116.64KB
程序.docx
《程序.docx》由会员分享,可在线阅读,更多相关《程序.docx(18页珍藏版)》请在冰点文库上搜索。
程序
串口初始化
#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
网口初始化
#definerEXTINT0(*(volatileunsigned*)0x56000088)//Externalinterruptcontrolregister0
#definerEINTMASK(*(volatileunsigned*)0x560000a4)//Externalinterruptmask
#definerEINTPEND(*(volatileunsigned*)0x560000a8)//Externalinterruptpending
在建立了主要的流程后,开始对μ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(),而且这个任务是不能用软件来删除的。
ARP,即地址解析协议,实现通过IP地址得知其物理地址。
程序代码如下:
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)
{
unsignedshortfcs=0xffff;//初始化
while(nLength>0)
{
fcs=(fcs>>8)^crctab16[(fcs^*pData)&0xff];
nLength--;
pData++;
}
return(fcs==0xf0b8);//0xf0b8是CRC-ITU的"MagicValue"
}
HDLC解帧模块流程图
如图所示,本模块要求从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_times==0)
{
if(HSerialByte==f_8)//若为帧头
{
HdlcRecvBufferTail=0;//清零
F_times=1;//设置帧标志位
}
}
elseif(HSerialByte==f_8)//终止段
{
F_times=0;
p=&HdlcRecvBuffer[0];//指向地址段
Flagcrc=IsCrc16Good(p,ACData_Len);
if(Flagcrc==1)
{
CommRecBuffer[CommRecBufferTail]=*(Datas+2);
CommRecBufferTail++;
CommRecBuffer[CommRecBufferTail]=*(Datas+3);
CommRecBufferTail++;
}
}
else//帧内数据
{
HdlcRecvBuffer[HdlcRecvBufferTail]=HSerialByte;
HdlcRecvBufferTail++;
if(HdlcRecvBufferTail==7)
HdlcRecvBufferTail=0;
}
}
voidserial(void)reentrantinterrupt4//串口中断函数
{
if(_testbit_(TI))//发送中断
{
TI=0;
CommSendBufferHead++;
if(CommSendBufferHead==DB_SENDMAXSIZE)
{
CommSendBufferHead=0;
}
if(CommSendBufferHead!
=CommSendBufferTail)
{
SBUF=CommSendBuffer[CommSendBufferHead];//sendthenextbyte
SendItComm=0;
}
else
{
SendItComm=1;
}
}
if(_testbit_(RI))//接收中断
{
RI=0;
if(CommRecBufferTail==CommRecBufferHead)
{
CommRecDataOverflowFlag=1;
}
SerialByte=SBUF;
Hdlc_ipacket(SerialByte);
FlagRecComm=1;
if(CommRecBufferTail==50)
{
CommRecBufferTail=0;
uip_slen=50;
}//OSSemPost(EVENT_RS232_ARRIVED)
}
}
HDLC封帧模块流程图如图3.5。
图4.10HDLC封帧流程图
本模块要求从以太网端发来的以太网帧通过DM9000芯片处理后,存入uip_buf缓冲区,并作为base[i]进入HDLC封帧函数。
封装要求按照规定帧长度进行分开封装,即两字节作为一组数据封装为HDLC帧,最终存储到CommSendBuffer缓冲区,并发送到串口。
程序代码如下:
unsignedintlocallen=0;
unsignedcharhdlczhen[8];
unsignedcharj;
unsignedshortcrc16;
unsignedcharnLength;
unsignedchar*pData;
unsignedshorthcrc16;
voidHdlc_Packet(unsignedchar*localBuffer)//封帧函数
{
hdlczhen[0]=0x7e;
hdlczhen[1]=0xff;
hdlczhen[2]=0xff;
hdlczhen[7]=0x7e;
for(locallen=0;;locallen++)
{
if(localBuffer[locallen]==0)break;
hdlczhen[3]=localBuffer[locallen++];//信息段
if(localBuffer[locallen]==0)break;
hdlczhen[4]=localBuffer[locallen];
pData=&hdlczhen[1];
nLength=4;
crc16=GetCrc16(pData,nLength);
hcrc16=crc16>>8;
hdlczhen[5]=(unsignedchar)crc16;//校验段
hdlczhen[6]=(unsignedchar)hcrc16;
for(j=0;j<8;j++)//存入串口发送缓冲区
{
CommSendBuffer[CommSendBufferTail]=hdlczhen[j];
CommSendBufferTail++;
if(CommSendBufferTail==DB_SENDMAXSIZE)
{
CommSendBufferTail=0;
}
}
}
}
voidSendCommString(unsignedchar*base)//发送数据
{
unsignedchari=0;
unsignedchart=0;
if(base[0]==0)return;
Hdlc_Packet(base);
if(SendItComm)
{
SendItComm=0;
SBUF=CommSendBuffer[CommSendBufferHead];//发送到串口
}
while(CommSendBufferHead!
=CommSendBufferTail);
}
以太网驱动模块设计
以太网结构的定义程序:
这里,将要介绍一些以太网端的关键程序,首先需要注意的是一些以太网头部结构的定义,紧接着,在以太网头部+ARP首部结构里,需要定义一些硬件类型,软件类型,包括硬件地址长度、软件地址长度的声明。
最重要的是发送端的MAC地址,IP地址,相应的则是接收端相对应的MAC、IP地址;IP首部结构里面,定义好我们需要的标示符,协议,源IP地址,目的IP地址,主要程序如下所示:
typedefstructeth_hdr//以太网头部结构,为了以后使用方便
{
unsignedchard_mac[6];//目的地址
unsignedchars_mac[6];//源地址
unsignedshorttype;//协议类型
}ETH_HDR;
typedefstruct_arp_hdr//以太网头部+ARP首部结构
{
ETH_HDRethhdr;//以太网首部
unsignedshorthwtype;//硬件类型(1表示传输的是以太网MAC地址)
unsignedshortprotocol;//协议类型(0x0800表示传输的是IP地
址)
unsignedcharhwlen;//硬件地址长度(6)
unsignedcharprotolen;//协议地址长度(4)
unsignedshortopcode;//操作(1表示ARP请求,2表示ARP应答)
unsignedcharsmac[6];//发送端MAC地址
unsignedcharsipaddr[4];//发送端IP地址
unsignedchardmac[6];//目的端MAC地址
unsignedchardipaddr[4];//目的端IP地址
}ARP_HDR;
typedefstructip_hdr//以太网头部+IP首部结构
{
ETH_HDRethhdr;//以太网首部
unsignedcharvhl;//4位版本号4位首部长度(0x45)
unsignedchartos;//服务类型(0)
unsignedshortlen;//整个IP数据报总字节长度
unsignedshortipid;//IP标识
unsignedshortipoffset;//3位标识13位偏移
unsignedcharttl;//生存时间(32或64)
unsignedcharproto;//协议(1表示ICMP,2表示IGMP,6表
示TCP,17表示UDP)
unsignedshortipchksum;//首部校验和
unsignedcharsrcipaddr[4];//源IP
unsignedchardestipaddr[4];//目的IP
}IP_HDR;
以太网地址协议的参数设置程序:
在和现场数据网进行通信的时候,需要设置相应的参数,才能实现两种类型网络之间的通信,以下程序对以太网目的地址,源地址,帧类型,协议作出了相应的具体设置。
unsignedcharhost_mac_addr[6]={0xff,0xff,0xff,0xff,0xff,0xff};
unsignedcharmac_addr[6]={0x00,0x01,0x02,0x03,0x04,0x05};//{0x52,0x54,0x4c,0x38,0xf7,0x42};
unsignedcharip_addr[4]={192,168,1,50};
unsignedcharhost_ip_addr[4]={192,168,1,120};
ARP_HDR*ARPBUF;
//ARP_HDR*ARPBUF;
#defineHON(n)((((unsignedshort)((n)&0xff))<<8)|(((n)&0xff00)>>8))
charcomm;
unsignedchararpsendbuf[60]={
0xff,0xff,0xff,0xff,0xff,0xff,//以太网目标地址
0x00,0x01,0x02,0x03,0x04,0x05,//以太网源地址
0x08,0x06,//帧类型:
ARP帧
//0x06,0x08,
0x00,0x01,//硬件类型:
以太网
//0x01,0x00,
0x08,0x00,//协议类型:
IP协议
//0x00,0x08,
0x06,//硬件地址长度:
6字节
0x04,//协议地址长度:
4字节
0x00,0x01,//操作:
ARP请求
//0x01,0x00,
0x00,0x01,0x02,0x03,0x04,0x05,//发送端硬件地址
192,168,1,50,//发送端协议地址
0x00,0x00,0x00,0x00,0x00,0x00,//接收端硬件地址
0,0,0,0//接收端协议地址
};
串行口工作在方式l,其波特率=
2smod/32*(T1的溢出率)。
其中,Tl方式2是8位计数。
串口中断处理程序如下:
voidserial(void)reentrantinterrupt4
{
if(_testbit_(TI))//测试TI标志以判断是否为发送引起的中断
{TI=0;
CommSendBufferHead++;
if(CommSendBufferHead==DB_SENDMAXSIZE)
CommSendBufferHead=0;//超出最大长度,则清零
if(CommSendBufferHead!
=CommSendBufferTail)
{SBUF=CommSendBuffer[CommSendBufferHead];
SendItComm=0;//发送下个字节}
elseSendItComm=1;
}
if(_testbit_(RI))//测试RI标志以判断是否为接收引起的中断
{RI=0;
if(CommRecBufferTail==CommRecBufferHead)
CommRecDataOverflowFlag=1;
CommRecBuffer[CommRecBufferTail]=SBUF;//接收数据
CommRecBufferTail++;
FlagRecComm=1;
if(CommRecBufferTail==50)//收到50字节,就设置uip_slen
{CommRecBufferTail=0;
uip_slen=50;}
}
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 程序