自己做的ARM的UDP通信实验 - 图文

更新时间:2024-04-20 08:10:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

自己做的ARM的UDP通信实验

【摘要】

利用基于嵌入式实时操作系统μC/OS-II的ZLG/IP软件包,利用实验板光盘提供的UDPtest软件可以实现实验板跟PC机的数据收发。目 录

第1章 硬件实现 .................................................................................... 1

1.1 RTL8019AS网络控制器介绍 .............................................................. 1

第2章 μC/OS-II操作系统 .................................................................... 3

2.1 μC/OS-II系统简介 ............................................................................... 3 2.2 μC/OS-II的特点 ................................................................................... 3 2.3 任务模式 ............................................................................................... 3 2.4 支持的指令集 ....................................................................................... 4 2.5 移植μC/OS-II ....................................................................................... 4

第3章 ZLG/IP软件包结构和配置 ....................................................... 6

3.1 ZLG/IP软件包结构 .............................................................................. 6

第4章 设计过程 ..................................................................................... 8

4.1 设计步骤 ............................................................................................... 8 4.2 实验程序 ............................................................................................. 10 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6

宏定义 ....................................................................................... 10 RTL8019AS监听任务 .............................................................. 11 UDP通信程序 .......................................................................... 12 创建系统任务并初始化 ........................................................... 14 主程序 ....................................................................................... 15 定时器中断控制 ....................................................................... 16

第5章 实验结果 ................................................................................... 19 第6章 课程设计体会 .......................................... 错误!未定义书签。

i

第1章 硬件实现

1.1 RTL8019AS网络控制器介绍

RTL8019AS是一种全双工即插即用的以太网控制器,它在一块芯片上集成了RTL8019内核和一个16KB的SDRAM存储器。它兼容RTL8019控制软件和NE2000 8bit或16bit的传输,支持UTP,AUI,BNC和PNP自动检测模式,支持外接闪烁存储器读写操作,支持I/O口地址的完全解码,具有LED指示功能。其接口符合Ethernet2和IEEE802.3(10Base5,10Base2,10BaseT)标准。

RTL8019AS采用100脚PQFP封装,其主要引角功能如下:

引角1-4,97-100:中断控制INT0-7; 引角33:复位控制;

引脚34:使能控制角AEN,低电平有效; 引脚6,7,70,89:数字电源,+5V; 引脚14,28,83,86:数字地GND; 引脚47,57:模拟电源:+5V; 引脚44,52:模拟地;

引脚7-13,15,16,18-27:ISA地址总线; 引脚36-43,87,88,90-95:ISA数据总线; 引脚31:Boot ROM读操作控制; 引脚32:Boot ROM写操作控制; 引脚62:RX接收数据显示LED1脚; 引脚63:TX发送数据显示LED2脚; 引脚58,59:接收数据TP IN+/-; 引脚45,46:发送数据TP OUT+/-; 引脚50,51:外接晶体。

1

图 1 RTL8019AS接线图

2

第2章 μC/OS-II操作系统

2.1 μC/OS-II系统简介

μC/OS-II读做“microCOS2”,意为“微控制器操作系统版本2”。μC/OS-II是著名的、源码公开的实时内核,可用于各类8位、16位和32位单片机、arm或 DSP等等。μC/OS-II是一个完整的、可移植、可固化、可剪裁的占先式实时多任务内核。应用程序处于整个系统的顶层.每个任务都可以认为自己独占了CPU,因而可以设计成为一个无限循环。

2.2 μC/OS-II的特点

? 可移植性(portable) ? 可固化(ROMmable) ? 可剪裁(scalable) ? 可剥夺(preemptive) ? 多任务 ? 可确定性 ? 任务栈 ? 系统服务 ? 中断管理 ? 稳定性与可靠性

多任务是指:μC/OS-II可以管理 64 个任务,然而,μC/OS-II的作者建议用户保留 8 个给μC/OS-II。这样,留给用户的应用程序最多可有 56 个任务。

系统服务指:μC/OS-II 提供很多系统服务,例如信号量、互斥信号量、时间标志、消息邮箱、消息队列、块大小固定的内存的申请与释放及时间管理函数等。

中断管理指:中断可以使正在执行的任务暂时挂起,如果优先级更高的任务被中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达 255 层。

2.3 任务模式

ARM7 处理器核具有用户、系统、管理、中止、未定义、中断和快中断七种模式 。

3

用户模式(USER MODE)是ARM 通常执行状态,用于执行大多数应用程序;快速中断模式(FIQ MODE)支持数据传输或通道处理;中断模式(IRQ MODE)用于通用中断处理;超级用户模式(SVC MODE)是一种操作系统受保护的模式:数据中止模式(ABT MODE)指令预取指中止、数据中止时进入该模式;未定义模式(UND MODE)当执行未定义的指令时进入该模式;系统模式(SYS MODE)是操作系统一种特许的用户模式。

除了用户模式之外,其他模式都归为特权模式,特权模式用于中断服务、异常或者访问受保护的资源

特权模式中除系统模式之外另5种模式又称为异常模式,在移植过程中必须设置中断向量表来处理异常。uCOS II的移植主要处理标准中断(IRQ)、快速中断(FIQ)和软件中断(SWI)。

2.4 支持的指令集

带T变量的ARM7处理器核具有两个指令集:标准32位ARM指令集和16位 Thumb指令集,两种指令集有不同的应用范围,μC/OS-II包含了这些指令集的切换(TaskIsARM()和 TaskIsTHUMB()用于改变指令集)。

2.5 移植μC/OS-II

μC/OS-II 要求所有.C 文件的都要包含都文件includes.h,这样使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。使用includes.h的缺点是它可能会包含一些实际不相关的头文件,这意味着每个文件的编译时间可能会增加,但却增强了代码的可移植性。在本移植中另外增加了一个头文件config.h,我们要求所有用户程序必须包含config.h,在config.h中包含 includes.h 和特定的头文件和配置项。而μC/OS-II 的系统文件依然只是包含 includes.h,即μC/OS-II 的系统文件完全不必改动。所有的配置改变包括头文件的增减均在config.h中进行,而includes.h定下来后不必改动(μC/OS-II 的系统文件需要包含的东西是固定的)。这样,μC/OS-II 的系统文件需要编译的次数大大减少,编译时间随之减少。

μCOS-II 不使用C语言中的 short、int、long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。代之以移植性强的整数数据类型,这样,既直观又可移植。

在使用周立功提供的μC/OS-II模板的任何功能之前,必须调用函数OSInit(),它完成μC/OS-II的初始化并建立空闲任务。在开始多任务之前,必须建立至少一个用户任务(不包括μC/OS-II的空闲任务),这是通过调

4

用函数OSTaskCreate()或函数OSTaskCreateExt()实现。最后函数main()调用函数 OSStart()将控制权交给μC/OS-II内核main()函数也就结束了。μC/OS-II应用程序主函数如下:

程序清单 1

int main (void) {

OSInit(); uC/OS-II

OSTaskCreate(TaskStart,(void *)0, &TaskStartStk[127], 3); //创建起动任务 OSStart(); }

//开始多任务

//

5

第3章 ZLG/IP软件包结构和配置

3.1 ZLG/IP软件包结构

为了使软件可移植性强、易维护,该软件包采用分层的方法编写。包括网络传输用到的协议、硬件驱动及μC/OS-II的结构进行分层。ZLG/IP包相关文件说明如表格 1

表格 1 软件包相关文件说明

文件名 ARP.C CRC.C Ethernet.C HARDWARE.C IP.C ICMP.C Socket.C TCP.C UDP.C 简要说明 地址解析协议 循环冗余码校验 以太网标准 硬件驱动 网络互联协议 因特网控制消息协议 本地端口协议 传输控制协议 用户数据包协议 传输层有两个协议传输数据:传输控制协议TCP和用户数据报协议UDP。TCP协议是面向连接的一个协议,可靠性高,费用也高;UDP协议是提供最少服务和费用的传输层协议。

UDP是最简单的传输层协议,它具有以下特点:

? 无连接:UDP不基于连接来传输数据。

? 不可靠:UDP的数据报发送时没有定序,所以UDP传送的数据是不可靠的,只有靠应用层协议中增加超时重发等功能才能提供可靠的服务。

? 提供应用层协议标识:UDP报头有定义应用层协议标识和目标应用层标识。

? 提供UDP报的校验和:UDP报头包含有整个UDP报(包括报头和有效负载)及伪报头的校验和,计算方法与计算IP数据报校验和的计算方法相同。

? 缓冲:UDP协议不提供任何数据接收或发送的缓

6

冲区。缓冲区应该由应用层协议提供。

? 分段:UDP协议不提供分段传输方式,所以应用层协议要尽量发送小的包。

SOCKET接口函数是TCP/IP的API。使用SOCKET API函数编写UDP通信的任务时,分为服务器方式两种。服务器方式是先接收到数据再进行处理,而客户机则是先发生数据后等待回应处理,它们用到的SOCKET API函数都是相同的。如图 2所示就是UDP通信时服务器端和客户机通信函数应用过程图。

服务器端客户机端socket创建套接字socket创建套接字Blind()本地IP和端口与套接字相连Blind()本地IP和端口与套接字相连Recvfrom()和sendto()直接完成数据收发Recvfrom()和sendto()直接完成数据收发Closesocket()删除套接字Closesocket()删除套接字结束结束

图 2 UDP通信是SOCKET API函数的应用

7

第4章 设计过程

4.1 设计步骤

由于使用DM9000的网络控制芯片的Magic2200的实验箱有点问题,后来我们改用使用RTL8019AS网络控制芯片的EasyARM2200教学实验平台。

1) 启动ADS1.2,使用ARM Executable Image for μCOS-II(lpc22xx)工程模板建立一个工程shiyan。

2) 把μCOS-II内核源码和移植文件,ZLG/IP软件包目录拷贝到已建工程目录下,如图 3所示,arm目录为移植文件目录,Source目录为μCOS-II内核源码,tcpip目录为ZLG/IP软件包目录。

图 3 项目目录结构

3) 修改tcpip\\include\\cfg_net.h文件,修改MAC地址为:0x00,0x14,0x97,0x0F,0x1F,0x9D、子网掩码为255.255.0.0、IP地址:172.30.172.77、本地网关地址为PC机IP:172.30.172.125。如程序清单 2

8

程序清单 2 MAC和IP设置

/************** first Net Port Config **************************/ #define My_Mac_1ID

{0x00,0x14,0x97,0x0F,0x1F,0x9D} //将RTL8019的物理地址存储在程序空间?

#define IP_MARK_1ID

//255.255.255.0,子网掩码

#define MY_IP_1ID {172,30,172,77} #define MY_GATEWAY_1ID {172,30,172,125} /**************End Net Port Config ***************/ 4) 修改shiyan\\src\\os_cfg.h文件,OS_MAX_EVENTS改为42,OS_LOWEST_PRIO改为62,OS_MAX_QS改为10。

5) 在ADS的项目窗口中添加TCPIP的文件组;然后把tcpip\\目录下的ARP\\Arp.c、ETHERNET\\Ethernet.c、HARDWARE\\Hardware.c、IP\\Ip.c、PING\\Icmp.c、

SOCKET\\zlg_socket.c和TCP\\Tcp.c、UDP\\Udp.c等文件添加到该文件组,最后把程序编好添加到ADS项目窗口的user文件组中,如

{255,255,0,0}

图 4 shiyan工程窗口

9

6) 在Startup.s文件的ResetInit子程序中,修改存储器接口Bank3总线配置,如程序清单

程序清单 3 存储器接口Bank3总线配置

LDR R0, =BCFG3 ;设置BCFG3寄存器 LDR R1, =0x10001460 STR R1, [R0] 4.2 实验程序

4.2.1

宏定义

首先对程序进行初始化宏定义,如程序清单 4

程序清单 4 初始化宏定义

#include \

#include \void Timer1_Init(void);

#define TASK_START_ID 0 #define TASK_1_ID 1 #define TASK_2_ID 2 #define TASK_3_ID 3 #define TASK_4_ID 4 #define TASK_5_ID 5 #define TASK_6_ID 6

#define TASK_START_PRIO 10 #define TASK_1_PRIO 11 #define TASK_2_PRIO 12 #define TASK_3_PRIO 13 #define TASK_4_PRIO 14 #define TASK_5_PRIO 15 #define TASK_6_PRIO 16

10

#define MSG_QUEUE_SIZE 20

OS_EVENT OS_EVENT OS_EVENT OS_EVENT

OS_STK task0_stack[3000]; OS_STK task1_stack[1000]; OS_STK task2_stack[2000]; OS_STK task3_stack[1000]; OS_STK task4_stack[2000];

4.2.2

RTL8019AS监听任务

*RecPackedFlag;

*RecBufOverFlowFlag; *RecTcpPackedFlag; *RecPingPackedFlag;

网络控制器监听程序,如程序清单 5

程序清单 5 网卡监听任务

void TaskB(void *pdata) //重要的监听RTL8019AS任务 {

void * UdpTemp; uint8 eer; while (1) { }

11

UdpTemp=OSQPend(RecUdpQFlag,0,&eer);

if(eer==OS_NO_ERR)

Udp_Process((Rec_Ptr *)UdpTemp); eer=eer; { }

}

4.2.3 UDP通信程序

UDP通信程序见程序清单 6

程序清单 6 UDP服务器

void TaskD(void *pdata) {

uint8 add[36]={\当接收到“A”时发送的数据

uint8 add1[10]={\当出错是发送的数据 uint8 rec_buffer[100]; //发送缓存区 SOCKET s;

uint8 couter_byte=5; //重复发送的次数

int rec_coute,send_coute; uint16 iii;

struct sockaddr servaddr,clientaddr;

OSTimeDly(60);

servaddr.sin_family=0; //设置客户机IP servaddr.sin_addr[0]=172; servaddr.sin_addr[1]=30; servaddr.sin_addr[2]=172; servaddr.sin_addr[3]=125;

servaddr.sin_port=1026; //设置服务器端口号

OSTimeDly(60);

s=*socket( 0, SOCK_DGRAM, UDP_PROTOCOL);//建clientaddr.sin_family=0; //设置本地IP

立SOCKET

clientaddr.sin_addr[0]=172; clientaddr.sin_addr[1]=30; clientaddr.sin_addr[2]=172; clientaddr.sin_addr[3]=77;

clientaddr.sin_port=1025; //设置本地监听端口号 iii=bind(

(SOCKET

12

* )&s, (struct

sockaddr*)&clientaddr,sizeof(clientaddr)); //绑定服务器地址

while (1) {

rec_coute=recvfrom( s, rec_buffer, 100, 0, (struct

sockaddr*)&servaddr, &iii ); //接收数据

if(rec_coute>0) { }

while(couter_byte!=0) //循环发送数据 {

send_coute=sendto(s,

if(send_coute==34) OSTimeDly(40); send_coute=sendto(s,

add1,

9,

0,

(struct

add,

34,

0,

(struct

if(rec_buffer[0]=='A') //如果第一个数据是“A”

couter_byte=5;

send_coute=sendto(s, rec_buffer, rec_coute, 0, (struct else

sockaddr*)&servaddr, sizeof(servaddr) ); //把接收的数据返回

sockaddr*)&servaddr, sizeof(servaddr) );

}

}

else

sockaddr*)&servaddr, sizeof(servaddr) ); //出错后发送的数据

OSTimeDly(40); couter_byte--;

}

13

4.2.4 创建系统任务并初始化

创建系统任务并初始化如程序清单 7

程序清单 7 系统任务

void task0(void *pdata)

{ /*在第1个任务中设置定时器0及中断*/ UBYTE iii;

#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;

#endif

TargetInit();

OSTaskCreateExt(TaskB,

//

重要

的监听

RTL8019AS任务

(void *)0, &task1_stack[999], TASK_1_PRIO, TASK_1_ID, &task1_stack[0], 1000, (void *)0, 0);

OSTaskCreateExt(TaskD, //接受数据和发送数据 (void *)0, &task3_stack[999], TASK_3_PRIO, TASK_3_ID, &task3_stack[0], 1000, (void *)0, 0);

14

SetNetPort();

//RTL8019芯片初始化,在global.c中定

InitNic(0); Initial_arp(); Tcp_Initial();

Udp_Initial(); while(1) { }

void Uart_SendChar(INT8U data) {

while((U0LSR & 0x00000020) == 0); U0THR = data; }

4.2.5

主程序

程序清单 8 主程序

do {

OSTimeDly(4);

iii=Rec_Packet();

}

while(iii!=0);

}

int main (void) {UBYTE iii;

Timer1_Init();

OSInit(); OSTaskCreateExt(task0, (void *)0,

&task0_stack[2999], TASK_START_PRIO, TASK_START_ID,

15

&task0_stack[0], 3000, (void *)0, 0);

RecPackedFlag=

OSStart(); }

4.2.6

定时器中断控制

程序清单 9 中断控制

OSSemCreate(0);

RecBufOverFlowFlag= OSSemCreate(0); RecTcpPackedFlag= OSSemCreate(0); RecPingPackedFlag= OSSemCreate(0); SendFlag= RecIcmpQFlag= RecTcpQFlag= RecUdpQFlag=

OSSemCreate(1);

OSQCreate(&RecIcmpQ[0],Q_Max_Size); OSQCreate(&RecTcpQ[0],Q_Max_Size); OSQCreate(&RecUdpQ[0],Q_Max_Size);

void Timer1_Init(void) {

OS_ENTER_CRITICAL(); T1IR = 0xffffffff; T1TC = 0; T1TCR = 0x01; T1MCR = 0x03; T1MR0 = 0xffffff; OS_EXIT_CRITICAL();

16

}

void Timer1(void) {

static uint8 m_10sec=0; static uint8 p_sec=0; static uint8 uint8 num;

p_min=0;

OS_ENTER_CRITICAL(); T1IR = 0x01;

m_10sec++; if(m_10sec==100) {

p_sec++; m_10sec=0; if(Ping_IP_TTL>0) { }

if(p_sec==60) {

p_min++; p_sec=0; if(p_min==60)

17

Ping_IP_TTL--;

for(num=0;num

for(p_min=0;p_min

if(Gateway_IP_TTL>0)

NetPort[num].Gateway_IP_TTL--;

if(NetPort[num].ARP_TERM[p_min].TTL>0)

NetPort[num].ARP_TERM[p_min].TTL--;

断结束

}

}

{ }

p_min=0;

}

VICVectAddr = 0; // 通知中断控制器中OS_EXIT_CRITICAL();

18

第5章 实验结果

将EasyARM2200教学实验平台上的JP4跳线短接,JP6跳线设置为Bank0-RAM和Bank1-FLASH,用配套的网线连接EasyARM2200教学实验平台和PC机。

选用DebugInExram生成目标,编译连接工程。

选择Project?Debug,启动AXD进行JTAG仿真调试,全速运行。

在PC机端打开Windows操作系统的“开始”?“运行”,键入“ping 172.30.172.77 –t”如图 5,然后单击“确定”,就可以看到PING成功的信息,如图 6

图 5 运行ping命令

图 6 PING成功

19

在PC机端打开光盘配套UDPtest软件,在远程主机地址栏键入172.30.172.77,远程端口号填入1025,本地端口号填入1026就可以发送数据到EasyARM2200教学实验平台了,结果如图 7所示,发送的数据被完整地返回了,如果发送以“A”开始的字符串,就会返回5次“ZLGMCUyhbabcdefghijklmnopqrstuv wxyz”。结果如图 8所示。

图 7 返回发送的数据

图 8 输入以A开头的字符串返回结果

20

在PC机端打开光盘配套UDPtest软件,在远程主机地址栏键入172.30.172.77,远程端口号填入1025,本地端口号填入1026就可以发送数据到EasyARM2200教学实验平台了,结果如图 7所示,发送的数据被完整地返回了,如果发送以“A”开始的字符串,就会返回5次“ZLGMCUyhbabcdefghijklmnopqrstuv wxyz”。结果如图 8所示。

图 7 返回发送的数据

图 8 输入以A开头的字符串返回结果

20

本文来源:https://www.bwwdw.com/article/97vp.html

Top