嵌入式以太网串口服务器文档格式.docx
- 文档编号:7931526
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:17
- 大小:421.57KB
嵌入式以太网串口服务器文档格式.docx
《嵌入式以太网串口服务器文档格式.docx》由会员分享,可在线阅读,更多相关《嵌入式以太网串口服务器文档格式.docx(17页珍藏版)》请在冰点文库上搜索。
以太网串口服务器网络模块采用ENC28J60作为主芯片,单芯片即可实现以太网接入,利用该模块,基本上只要是个单片机,就可以实现以太网的连接,网络模块原理图如图4所示:
图4网络模块原理图
3、嵌入式以太网串口服务器的软件初始化
3.1、uip简介
uIP由瑞典计算机科学学院(网络嵌入式系统小组)的AdamDunkels开发。
其源代码由C语言编写,并完全公开。
uIP协议栈去掉了完整的TCP/IP中不常用的功能,简化了通讯流程,但保留了网络通信必须使用的协议,设计重点放在了IP/TCP/ICMP/UDP/ARP这些网络层和传输层协议上,保证了其代码的通用性和结构的稳定性。
由于uIP协议栈专门为嵌入式系统而设计,因此还具有如下优越功能:
1)代码非常少,其协议栈代码不到6K,很方便阅读和移植。
2)占用的内存数非常少,RAM占用仅几百字节。
3)其硬件处理层、协议栈层和应用层共用一个全局缓存区,不存在数据的拷贝,且发送和接收都是依靠这个缓存区,极大的节省空间和时间。
4)支持多个主动连接和被动连接并发。
5)其源代码中提供一套实例程序:
web服务器,web客户端,电子邮件发送程序(SMTP客户端),Telnet服务器,DNS主机名解析程序等。
通用性强,移植起来基本不用修改就可以通过。
6)对数据的处理采用轮循机制,不需要操作系统的支持。
由于uIP对资源的需求少和移植容易,大部分的8位微控制器都使用过uIP协议栈,而且很多的著名的嵌入式产品和项目(如卫星,Cisco路由器,无线传感器网络)中都在使用uIP协议栈。
uIP相当于一个代码库,通过一系列的函数实现与底层硬件和高层应用程序的通讯,对于整个系统来说它内部的协议组是透明的,从而增加了协议的通用性。
uIP协议栈与系统底层和高层应用之间的关系如图5所示:
图5uip在系统中的位置
从上图可以看出,uIP协议栈主要提供2个函数供系统底层调用:
uip_input和uip_periodic。
另外和应用程序联系主要是通过UIP_APPCALL函数。
当网卡驱动收到一个输入包时,将放入全局缓冲区uip_buf中,包的大小由全局变量uip_len约束。
同时将调用uip_input()函数,这个函数将会根据包首部的协议处理这个包和需要时调用应用程序。
当uip_input()返回时,一个输出包同样放在全局缓冲区uip_buf里,大小赋给uip_len。
如果uip_len是0,则说明没有包要发送。
否则调用底层系统的发包函数将包发送到网络上。
uIP周期计时是用于驱动所有的uIP内部时钟事件。
当周期计时激发,每一个TCP连接都会调用uIP函数uip_periodic()。
类似于uip_input()函数。
uip_periodic()函数返回时,输出的IP包要放到uip_buf中,供底层系统查询uip_len的大小发送。
由于使用TCP/IP的应用场景很多,因此应用程序作为单独的模块由用户实现。
uIP协议栈提供一系列接口函数供用户程序调用,其中大部分函数是作为C的宏命令实现的,主要是为了速度、代码大小、效率和堆栈的使用。
用户需要将应用层入口程序作为接口提供给uIP协议栈,并将这个函数定义为宏UIP_APPCALL()。
这样,uIP在接受到底层传来的数据包后,在需要送到上层应用程序处理的地方,调用UIP_APPCALL()。
在不用修改协议栈的情况下可以适配不同的应用程序。
3.2、程序设计
本系统要实现TCP/IP通信,还要实现和串口交换数据,因此我们采用轮询的方式,第一次调用轮询函数的时候创建两个定时器,当收到包的时候(uip_len>
0),先区分是IP包还是ARP包,针对不同的包做不同的处理,对我们来说,主要是通过uip_input处理IP包,实现数据处理。
当没有收到包的时候(uip_len=0),通过定时器处理各个TCP/UDP连接以及ARP表处理。
其轮询处理函数为:
//uip事件处理函数
//必须将该函数插入用户主循环,循环调用.
voiduip_polling(void)
{
u8i;
staticstructtimerperiodic_timer,arp_timer;
staticu8timer_ok=0;
if(timer_ok==0)//仅初始化一次
{
timer_ok=1;
timer_set(&
periodic_timer,CLOCK_SECOND/2);
//创建1个0.5秒的定时器
arp_timer,CLOCK_SECOND*10);
//创建1个10秒的定时器
}
uip_len=tapdev_read();
//读取一个IP包,数据长度.uip_len在uip.c中定义
if(uip_len>
0)//有数据
{
//处理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_len>
0)//需要回应数据
{
uip_arp_out();
//加以太网头结构,主动连接时可能要构造ARP请求
tapdev_send();
//发送数据到以太网
}
}
elseif(BUF->
type==htons(UIP_ETHTYPE_ARP))//处理arp报文,是否是ARP请求包?
uip_arp_arpin();
//当上面的函数执行后,如果需要发送数据,则全局变量uip_len>
//需要发送的数据在uip_buf,长度是uip_len(这是2个全局变量)
if(uip_len>
0)tapdev_send();
//需要发送数据,则通过tapdev_send发送
}elseif(timer_expired(&
periodic_timer))//0.5秒定时器超时
timer_reset(&
periodic_timer);
//复位0.5秒定时器
//轮流处理每个TCP连接,UIP_CONNS缺省是40个
for(i=0;
i<
UIP_CONNS;
i++)
uip_periodic(i);
//处理TCP通信事件
//当上面的函数执行后,如果需要发送数据,则全局变量uip_len>
//需要发送的数据在uip_buf,长度是uip_len(这是2个全局变量)
0)
#ifUIP_UDP//UIP_UDP
//轮流处理每个UDP连接,UIP_UDP_CONNS缺省是10个
UIP_UDP_CONNS;
uip_udp_periodic(i);
//处理UDP通信事件
if(uip_len>
0)
#endif
//每隔10秒调用1次ARP定时器函数用于定期ARP处理,ARP表10秒更新一次,旧的条目会被抛弃
if(timer_expired(&
arp_timer))
timer_reset(&
arp_timer);
uip_arp_timer();
}
}
TCP应用接口函数:
//TCP应用接口函数(UIP_APPCALL)
//完成TCP服务(包括server和client)和HTTP服务
voidtcp_demo_appcall(void)
{
switch(uip_conn->
lport)//本地监听端口80和1200
caseHTONS(80):
httpd_appcall();
break;
caseHTONS(1200):
tcp_server_demo_appcall();
default:
break;
}
rport)//远程连接1400端口
caseHTONS(1400):
tcp_client_demo_appcall();
break;
default:
}
除此之外,我们需要对串口进行初始化,并建立相应的串口程序文件,便于其它函数的调用,实现串口上数据的交换。
串口函数初始化:
voiduart_init(u32bound){
//GPIO端口设置
GPIO_InitTypeDefGPIO_InitStructure;
USART_InitTypeDefUSART_InitStructure;
NVIC_InitTypeDefNVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
//使能USART1,GPIOA时钟以及复用功能时钟
//USART1_TXPA.9
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
//PA.9
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
//复用推挽输出
GPIO_Init(GPIOA,&
GPIO_InitStructure);
//USART1_RXPA.10
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
//浮空输入
//Usart1NVIC配置
NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
//子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
//IRQ通道使能
NVIC_Init(&
NVIC_InitStructure);
//根据指定的参数初始化VIC寄存器
//USART初始化设置
USART_InitStructure.USART_BaudRate=bound;
//一般设置为9600;
USART_InitStructure.USART_WordLength=USART_WordLength_8b;
//字长为8位数据格式
USART_InitStructure.USART_StopBits=USART_StopBits_1;
//一个停止位
USART_InitStructure.USART_Parity=USART_Parity_No;
//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
//无硬件数据流控制
USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
//收发模式
USART_Init(USART1,&
USART_InitStructure);
//初始化串口
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
//开启中断
USART_Cmd(USART1,ENABLE);
//使能串口
主函数的实现是对整个嵌入式以太网串口服务器的统筹管理,实现系统的有序整合和运行。
其主函数为:
intmain(void)
delay_init();
//延时函数初始化
NVIC_Configuration();
//NVIC中断分组2:
2位抢占优先级,2位响应优先级
uart_init(9600);
//串口初始化为9600
RTC_Init();
//初始化RTC
while(tapdev_init())//初始化ENC28J60如果初始化失败,就会死在这里
delay_ms(200);
};
uip_init();
//uIP初始化
uip_ipaddr(ipaddr,192,168,1,105);
//设置本地设置IP地址uip_sethostaddr(ipaddr);
uip_ipaddr(ipaddr,192,168,1,1);
//网关IP地址(其实就是你路由器的IP地址)
uip_setdraddr(ipaddr);
uip_ipaddr(ipaddr,255,255,255,0);
//设置网络掩码
uip_setnetmask(ipaddr);
uip_listen(HTONS(80));
//监听80端口,用于WebServer
uip_listen(HTONS(1200));
//监听1200端口,用于TCPServer
tcp_client_connect();
//尝试连接到TCPServer端,用于TCPClient
udp_server_connect();
//尝试连接到UDPClient端,用于UDPServer端口1600udp_client_connect();
//尝试连接到UDPServer端,用于UDPClient端口1500
while
(1)
uip_polling();
//处理uip事件,必须插入到用户程序的循环体中
if(uip_test_mode==0){//TCP测试
if(tcp_server_tsta!
=tcp_server_sta)//TCPServer状态改变
{if(tcp_server_sta&
(1<
<
6))//收到新数据
{
printf("
TCPServerRX:
%s\r\n"
tcp_server_databuf);
//打印
tcp_server_sta&
=~(1<
6);
//标记数据已经被处理
tcp_server_tsta=tcp_server_sta;
if(tcp_client_tsta!
=tcp_client_sta)//TCPClient状态改变
{
if(tcp_client_sta&
TCPClientRX:
tcp_client_databuf);
tcp_client_sta&
tcp_client_tsta=tcp_client_sta;
}else{//UDP测试
if(udp_server_sta&
printf("
udp_server_databuf);
//打印数据
udp_server_sta&
//标记数据已经被处理
if(udp_client_sta&
UDPClientRX:
udp_client_databuf);
udp_client_sta&
}
if(FLAG1){//TCP/UDP模式切换
if(uip_test_mode==0){
tcp_server_tsta=0XFF;
tcp_client_tsta=0XFF;
uip_test_mode=!
uip_test_mode;
if(FLAG2)//TCPServer请求发送数据
{
if(uip_test_mode==0){
if(tcp_server_sta&
7))//连接还存在
{
sprintf((char*)tcp_server_databuf,"
%d\r\n"
tcnt);
tcp_server_sta|=1<
5;
//标记有数据需要发送
}
}else{
sprintf((char*)udp_server_databuf,"
udp_server_sta|=1<
//标记有数据需要发送
tcnt++;
}
if(FLAG3)//TCPClient请求发送数据
sprintf((char*)tcp_client_databuf,"
tcp_client_sta|=1<
sprintf((char*)udp_client_databuf,"
%d\r\n"
udp_client_sta|=1<
tcnt++;
delay_ms
(1);
}
4、结束语
随着数字化、智能化仪器的飞速发展,采用以太网进行通信的应用将会越来越广泛。
以太网串口服务器是网络技术与单片机技术的完美结合,用它可以方便的实现嵌入式的以太网联接,可以广泛的应用于智能交通、汽车电子、工业控制、信息家电、医学仪器等各种嵌入式系统应用场合,并且在成本、体积、功耗、灵活性等方面具有明显的优势,能为智能化仪表与
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 嵌入式 以太网 串口 服务器