ENC28J60以太网之uIP协议
来源:互联网 发布:三国演义版本 知乎 编辑:程序博客网 时间:2024/04/28 19:50
广东省电子设计大赛准备的,智能家居网关,外围单片机通信数据需要使用TCP/IP通信,故采用ENC28J60模块。
在嵌入式系统中,以太网控制器通常也是研究热点之一,MicroChip公司的ENC28J60在嵌入式系统中应用价值较高,该芯片集成了MAC控制器和PHY,使用SPI接口,适合在引脚资源比较紧张的嵌入式系统中加入以太网连接功能,本文主要介绍了MicroChip公司的ENC28J60控制器的初始化及其编程相关的注意和要点。
uIP作为一种广泛使用的轻量级嵌入式TCP/IP协议栈,其UDP协议的实现还不够完善,目前最新的1.0版本中仅实现了UDP客户端,尚没有实现UDP服务端。为此,对其进行了以下三方面的改进:UDP服务端口的初始化;接收到UDP客户端数据包后的端口号判断及匹配;UDP服务端发送报文后目的端口的释放。
硬件平台:STC12C60S2+ENC28J60
主函数main:在函数中,对于处理应用数据的用户,对 uIP 整个流程做一个了解即可,uIP 将处理后的结果全部
都回调到uip_appcall()函数统一处理, 所以重点需要完成的工作全部在uip_appcall()函数中
/* * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This file is part of the uIP TCP/IP stack. * * $Id: main.c,v 1.10.2.1 2003/10/04 22:54:17 adam Exp $ * */#include "uip.h" #include "uip_arp.h"#include "httpd.h"//#include "telnet.h"#include "mcu_uart.h"#include "enc28j60.h"#include "tcp_server.h"#define BUF ((struct uip_eth_hdr *)&uip_buf[0])#ifndef NULL#define NULL (void *)0#endif /* NULL *//*-----------------------------------------------------------------------------------*/intmain(void){idata u8_t i, arptimer;idata u16_t j;init_uart(); //串口初始化printu("starting......\r\n");/* Initialize the device driver. */ dev_init(); //网卡初始化uip_arp_init();//ARP初始化/* Initialize the uIP TCP/IP stack. */uip_init(); //uIP协议初始化printu("uip\r\n");/* Initialize the HTTP server. *///httpd_init();tcp_server_init(); //用户自定义处,实现功能函数arptimer = 0; //ARP缓存表更新定时器printu("ok\r\n"); while(1) { /* Let the tapdev network device driver read an entire IP packet into the uip_buf. If it must wait for more than 0.5 seconds, it will return with the return value 0. If so, we know that it is time to call upon the uip_periodic(). Otherwise, the tapdev has received an IP packet that is to be processed by uIP. */ uip_len = dev_poll(); //查询网卡是否有包收到for(j=0;j<500;j++); //延时,避免服务端应答过慢,造成不必要重发包/*if(uip_len > 0){printuf("--------------- uip_len = 0x%x", uip_len);printuf("%x ----------\r\n", uip_len);for(i=0;i<uip_len;i++){printuf("%x ", uip_buf[i]);if((i+1)%16==0) printu("\r\n");}printu("\r\n");}*/ if(uip_len == 0) { for(i = 0; i < UIP_CONNS; i++) {//协议栈解析,组包,状态监测等uip_periodic(i);/* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */if(uip_len > 0) { uip_arp_out();//有包需要发送 dev_send();} }#if UIP_UDP for(i = 0; i < UIP_UDP_CONNS; i++) {uip_udp_periodic(i);/* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */if(uip_len > 0) { uip_arp_out(); dev_send();} }#endif /* UIP_UDP */ /* Call the ARP timer function every 10 seconds. */ if(++arptimer == 20) {uip_arp_timer(); //更新ARP缓存arptimer = 0; } } else {//有包 处理IP包 if(BUF->type == htons(UIP_ETHTYPE_IP)) {uip_arp_ipin();uip_input();/* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */if(uip_len > 0) { uip_arp_out(); dev_send();} } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {//处理ARPuip_arp_arpin();/* If the above function invocation resulted in data that should be sent out on the network, the global variable uip_len is set to a value > 0. */if(uip_len > 0) { dev_send();} } } } return 0;}/*-----------------------------------------------------------------------------------*/voiduip_log(char *m){// printf("uIP log message: %s\n", m);}/*-----------------------------------------------------------------------------------*/
在tcp_server_init(); //用户自定义处,实现功能函数中
#include "example0.h"#include "example1.h"#include "tcp_server.h"//#include "httpd.h"#include "uip.h"#include "mcu_uart.h"void tcp_server_init(void) //在应用程序函数中,依靠uIP事件检测函数来决定处理的方法,//另外可以通过判断当前连接的端口号来区分处理不同的连接。{httpd_init();example0_init(); //用户自定义函数,实现某些功能的,主要监听端口example1_init(); //}void tcp_server_appcall(void) {switch(uip_conn->lport) {case HTONS(80):httpd_appcall();break;case HTONS(8000):example0_app();break;case HTONS(8001):example1_app();break;}}
如example0_init中
void example0_init(void) {uip_listen(HTONS(8000));}
究竟如何调用自己编写的函数呢?在uipopt.h中,可以修改IP地址,MAC,默认网关。实现的用户自定义的函数
#define UIP_PINGADDRCONF 0#define UIP_IPADDR0 192 /**< The first octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_IPADDR1 168 /**< The second octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_IPADDR2 0 /**< The third octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_IPADDR3 44 /**< The fourth octet of the IP address of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_NETMASK0 255 /**< The first octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_NETMASK1 255 /**< The second octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_NETMASK2 255 /**< The third octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_NETMASK3 0 /**< The fourth octet of the netmask of this uIP node, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_DRIPADDR0 192 /**< The first octet of the IP address of the default router, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_DRIPADDR1 168 /**< The second octet of the IP address of the default router, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_DRIPADDR2 0 /**< The third octet of the IP address of the default router, if UIP_FIXEDADDR is 1. \hideinitializer */#define UIP_DRIPADDR3 1 /**< The fourth octet of the IP address of the default router, if UIP_FIXEDADDR is 1. \hideinitializer *//** * Specifies if the uIP ARP module should be compiled with a fixed * Ethernet MAC address or not. * * If this configuration option is 0, the macro uip_setethaddr() can * be used to specify the Ethernet address at run-time. * * \hideinitializer */#define UIP_FIXEDETHADDR 1#define UIP_ETHADDR0 0x12 /**< The first octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */#define UIP_ETHADDR1 0x34 /**< The second octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */#define UIP_ETHADDR2 0x56 /**< The third octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */#define UIP_ETHADDR3 0x78 /**< The fourth octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */#define UIP_ETHADDR4 0x90 /**< The fifth octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */#define UIP_ETHADDR5 0xAB /**< The sixth octet of the Ethernet address if UIP_FIXEDETHADDR is 1. \hideinitializer */
/*为了将用户的应用程序挂接到uIP中,必须将宏UIP_APPCALL()定义成实际的应用 程序函数名,这样每当某个uIP事件发生时,内核就会调用该应用程序进行处理*/#define UIP_APPCALL tcp_server_appcall//httpd_appcall/*
最后,如何进行测试呢:使用TCP/UDP 调试工具,上网下载的
- ENC28J60以太网之uIP协议
- 20130408-[转]ENC28J60以太网之uIP协议
- MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
- MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
- MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
- MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
- MCU51单片机uIP协议栈+ENC28J60网卡 移植、应用
- 【uip移植】在AVR单片机ATMega16A上运行uip协议栈,网卡使用ENC28J60
- STM32单片机以太网模块ENC28J60稳定 驱动程序SPI接口方便移植lwip或者uip
- 新型以太网控制器 ENC28J60
- uip协议栈TCP Client模式,以太网模块控制灯
- 以太网控制器ENC28J60编程要点
- 网络协议之以太网帧
- 新型以太网控制器ENC28J60及其接口技术
- uIP协议栈——转载:uIP之ARP:地址…
- AVR配合ENC28J60芯片移植uIP实现web客户端
- uIP TCP协议状态机
- uip协议分析
- tar命令 简单解释
- oracle学习笔记
- xshell调整透明度
- 完全背包问题_找的是最小值
- 关于100层楼,扔两个鸡蛋,求摔碎鸡蛋的临界层的问题
- ENC28J60以太网之uIP协议
- 如何搭建小型集群服务器?
- C#----对子窗体进行层叠排列
- javaweb编码问题(不断补充)
- 随想录(程序员的缺点)
- 程序性能优化之二-----ulimit
- 完全背包
- The Windows Driver Model Simplifies Management of Device Driver I/O Requests(WDM对设备驱动I/O请求管理的简化)
- java 反射知识总结