《嵌入式以太网串口服务器》由会员分享,可在线阅读,更多相关《嵌入式以太网串口服务器(11页珍藏版)》请在金锄头文库上搜索。
1、嵌入式以太网串口服务器 嵌入式以太网串口服务器摘要:本文提出了一种以高性能微处理器Cortex-M3芯片STM32F103C8T6和以太网控制芯片ENC28J60为核心的转换系统,实现串口(RS232)和网口(RJ45)的数据通过以太网互发,提高了传输数据的抗干扰性,节省了更新换代的成本,达到了远程控制、远程通信的目的。1、 引言随着Internet快速发展与普及,将一些设备联入网络已经成为越来越多人的共识。利用基于TCP/IP的串口数据流传输的实现来控制管理的设备硬件,无需投资大量的人力、物力来进行管理、更换或者升级,而串口服务器是为RS-232/485/422到TCP/IP之间完成数据转换
2、的通讯接口转换器。2、嵌入式以太网串口服务器的硬件设计本系统主要有三大模块组成,分别是由微处理器芯片STM32F103C8T6构成的MCU模块,由网络控制芯片ENC28J60与含RJ45和网络变压器的HR91105A构成的网口模块,由串口控制芯片MAX-232与RS232接口构成的串口模块。设备发送过来的信息通过串口模块之后,送入MCU进行处理,然后通过网络模块发送至以太网进行显示。如图一所示为服务器的系统设计框图。图1 系统设计框图2.1、MCU模块本系统设计引用了嵌入式应用方面性价比高的CortexM3 STM32F103C8T6作为处理器,CortexM3类型的STM32F103C8T6
3、处理器采用表面贴片的48管脚LQFP封装,最高工作频率为72MHZ,工作温度为-40 +85。其具有提供丰富的外围接口,包括(CAN、I2C、SPI、UART、USB等)低功耗、门数少、中断延迟小、调试容易,支持TCP/IP 协议栈中的IP/ICMP/TCP/UDP/DHCP 等协议,动态获取IP,支持标准socket 编程等优点。2.2、串口模块几乎所有的微控制器、PC 都提供串行接口,使用电子工业协会(EIA) 推荐的RS-232-C 标准。由于RS-232-C 标准所定义的高、低电平信号与STM32F103 系统的LVTTL 电路所定义的高、低电平信号完全不同,所以,两者间要进行通信必须
4、经过信号电平的转换。目前我们用USB-232电平转换芯片PL2303HX,实现USB转串口的功能。本系统采用PH2303HX芯片和USB接口设计了一个实现USB转串口接口模块。PL2303单独使用12MHZ晶振,这是USB必须使用的频率,其采用模块化电路,RXD接单片机TXD,TXD接单片机的RXD。其连接电路如图2所示:图2 USB转串口电路模块2.3、网口模块ENC28J60是带有行业标准串行外设接口(Serial Peripheral Interface,SPI)的独立以太网控制器。它可以作为任何配备有SPI的控制器的以太网接口。ENC28J60符合IEEE 802.3的全部规范,采用一
5、系列包过滤机制以对传入数据包进行限制。还提供了一个内部的DMA模块,以实现快速数据吞吐和硬件支持的IP校验和计算。与主控制器的通信通过两个中断引脚和SPI实现,数据传输速率高达10mb/s。两个专用的引脚用于连接LED,进行网络活动状态指示。ENC28J60总共只有28引脚,提供QFN/TF。ENC28J60典型应用电路如图3所示: 图3 ENC28J60典型应用电路以太网串口服务器网络模块采用ENC28J60作为主芯片,单芯片即可实现以太网接入,利用该模块,基本上只要是个单片机,就可以实现以太网的连接,网络模块原理图如图4所示: 图4 网络模块原理图 3、嵌入式以太网串口服务器的软件初始化3
6、.1、uip简介uIP 由瑞典计算机科学学院(网络嵌入式系统小组)的Adam Dunkels 开发。其源代码由C 语言编写,并完全公开。uIP 协议栈去掉了完整的TCP/IP 中不常用的功能,简化了通讯流程,但保留了网络通信必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP 这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。由于uIP 协议栈专门为嵌入式系统而设计,因此还具有如下优越功能:1) 代码非常少,其协议栈代码不到6K,很方便阅读和移植。2) 占用的内存数非常少,RAM 占用仅几百字节。3) 其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷
7、贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。4) 支持多个主动连接和被动连接并发。5) 其源代码中提供一套实例程序:web 服务器,web 客户端,电子邮件发送程序(SMTP 客户端),Telnet 服务器, DNS 主机名解析程序等。通用性强,移植起来基本不用修改就可以通过。6) 对数据的处理采用轮循机制,不需要操作系统的支持。由于uIP 对资源的需求少和移植容易,大部分的8 位微控制器都使用过uIP协议栈, 而且很多的著名的嵌入式产品和项目(如卫星,Cisco 路由器,无线传感器网络)中都在使用uIP 协议栈。uIP相当于一个代码库,通过一系列的函数实现与底层硬件和高层应用程
8、序的通讯,对于整个系统来说它内部的协议组是透明的,从而增加了协议的通用性。uIP协议栈与系统底层和高层应用之间的关系如图5所示: 图5 uip在系统中的位置从上图可以看出,uIP 协议栈主要提供2 个函数供系统底层调用:uip_input 和uip_periodic。另外和应用程序联系主要是通过UIP_APPCALL 函数。当网卡驱动收到一个输入包时,将放入全局缓冲区uip_buf 中,包的大小由全局变量uip_len约束。同时将调用uip_input()函数,这个函数将会根据包首部的协议处理这个包和需要时调用应用程序。当uip_input()返回时,一个输出包同样放在全局缓冲区uip_buf
9、 里,大小赋给uip_len。如果uip_len 是0,则说明没有包要发送。否则调用底层系统的发包函数将包发送到网络上。uIP 周期计时是用于驱动所有的uIP 内部时钟事件。当周期计时激发,每一个TCP 连接都会调用uIP 函数uip_periodic()。类似于uip_input()函数。uip_periodic()函数返回时,输出的IP 包要放到uip_buf 中,供底层系统查询uip_len 的大小发送。由于使用 TCP/IP 的应用场景很多,因此应用程序作为单独的模块由用户实现。uIP 协议栈提供一系列接口函数供用户程序调用,其中大部分函数是作为C 的宏命令实现的,主要是为了速度、代码
10、大小、效率和堆栈的使用。用户需要将应用层入口程序作为接口提供给uIP 协议栈, 并将这个函数定义为宏UIP_APPCALL()。这样,uIP 在接受到底层传来的数据包后,在需要送到上层应用程序处理的地方,调用UIP_APPCALL( )。在不用修改协议栈的情况下可以适配不同的应用程序。3.2、程序设计本系统要实现TCP/IP 通信,还要实现和串口交换数据,因此我们采用轮询的方式,第一次调用轮询函数的时候创建两个定时器,当收到包的时候(uip_len0),先区分是IP包还是ARP包,针对不同的包做不同的处理,对我们来说,主要是通过uip_input处理IP包,实现数据处理。当没有收到包的时候(u
11、ip_len=0),通过定时器处理各个TCP/UDP连接以及ARP表处理。其轮询处理函数为:/uip事件处理函数/必须将该函数插入用户主循环,循环调用.void uip_polling(void)u8 i;static struct timer periodic_timer, arp_timer;static u8 timer_ok=0; if(timer_ok=0)/仅初始化一次timer_ok = 1;timer_set(&periodic_timer,CLOCK_SECOND/2); /创建1个0.5秒的定时器 timer_set(&arp_timer,CLOCK_SECOND*10);
12、 /创建1个10秒的定时器 uip_len=tapdev_read();/读取一个IP包,数据长度.uip_len在uip.c中定义if(uip_len0) /有数据 /处理IP数据包(只有校验通过的IP包才会被接收) if(BUF-type = htons(UIP_ETHTYPE_IP)/是否是IP包? uip_arp_ipin();/去除以太网头结构,更新ARP表uip_input(); /IP包处理/当上面的函数执行后,如果需要发送数据,则全局变量 uip_len 0/需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量) if(uip_len0)/需要回应数据ui
13、p_arp_out();/加以太网头结构,主动连接时可能要构造ARP请求tapdev_send();/发送数据到以太网else if (BUF-type=htons(UIP_ETHTYPE_ARP)/处理arp报文,是否是ARP请求包?uip_arp_arpin(); /当上面的函数执行后,如果需要发送数据,则全局变量uip_len0/需要发送的数据在uip_buf, 长度是uip_len(这是2个全局变量) if(uip_len0)tapdev_send();/需要发送数据,则通过tapdev_send发送 else if(timer_expired(&periodic_timer)/0.5
14、秒定时器超时timer_reset(&periodic_timer);/复位0.5秒定时器 /轮流处理每个TCP连接, UIP_CONNS缺省是40个 for(i=0;i0/需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量) if(uip_len0)uip_arp_out();/加以太网头结构,主动连接时可能要构造ARP请求tapdev_send();/发送数据到以太网#if UIP_UDP/UIP_UDP /轮流处理每个UDP连接, UIP_UDP_CONNS缺省是10个for(i=0;i0/需要发送的数据在uip_buf, 长度是uip_len (这是2个全局变量)if(uip_len 0)uip_arp_out();/加以太网头结构,主动连接时可能要构造ARP请求tapdev_send();/发送数据到以太网#endif /