AVR配合ENC28J60芯片移植uIP实现web客户端

来源:互联网 发布:网络攻击防范措施 编辑:程序博客网 时间:2024/05/10 00:22


    最近一段时间研究了一下以太网驱动,前前后后也花了好些时间,在这写下我的一点经验,希望对大家的开发有点帮助。
    概述:既然是联网,那首先要知道的无非是四层网络协议,具体每层协议是什么,做哪些工作我就不赘述了,网上多得是这方面的介绍,还有ENC28J60这个以太网驱动芯片,同样不作解释,同理,其他人说得比我好多了,没必要再写,大多数的驱动拿过来改个接口就直接能用,简单方便。我就着重讲一下此硬件基础上移植uIP协议栈的过程和注意事项,给想学习这方面的人多一点参考。
    首先要说一下:移植uIP一点也不麻烦,不要因为看到uIP中那么多的文件感觉超出了自己的驾驭能力,先告诉自己打个底,这很简单。还有一点就是:要相信这个协议栈,当得不到自己的预期结果时,可以看资料看官方文档看其他人的经验,千万不要随便修改协议内部的函数,协议栈的封装真的很好。下面进入做web客户端具体操作。

    一、 前期准备:官网下载1.0源码,创建工程,在main函数外建3个文件夹,分别放uIP,ENC28J60以及web client的文件
    二、做好ENC28J60的驱动,提供3个函数:enc28j60_init,enc28j60_send(len,package)和enc28j60_receive(maxlen,package);
    三、取出main.c加入工程,ENC28J60文件夹中放入自己写的以太网驱动,uIP中需要放的文件有:timer.c tapdev.c uip.c uip_arp.c 及对应.h文件uip_arch.h uip_arch.h uip-conf.h uipopt.h。web client需要放入的有:resolv.c webclient.c webclient-strings.c uip_lib.c及对应.h文件
    四、tapdev里函数:函数名不变以减少其他修改,这样写应该能看懂吧
void tapdev_init(void){enc28j60Init();}
unsigned int tapdev_read(void){return enc28j60PacketReceive(UIP_BUFSIZE, uip_buf);}
void tapdev_send(void){enc28j60PacketSend(uip_len, uip_buf);}
    五、timer可以全删掉,用单片机的定时器中断,一个0.5秒一个10秒,替换掉主函数的这2处,没什么难度,不作解释。
else if(timer_expired(&periodic_timer)) { //0.5s是否到 
      timer_reset(&periodic_timer);
if(timer_expired(&arp_timer)) {   //10s是否到
 timer_reset(&arp_timer); 
    六、修改uip-conf.h文件
 #define UIP_CONF_BYTE UIP_BIG_ENDIAN //单片机大端模式
 #define UIP_CONF_LOGGING 0 //值改为0,功能用不着,关这个方便,不然报错
 #define UIP_CONF_MAXCONNECTIONS 1 //原值为40,占空间太大,客户端为1就够了
 #define UIP_CONF_MAXLISTENPORTS 0 //又不是服务器,不需要监听,0就行
 #define UIP_CONF_UDP  1 //支持UDP还是需要的
    七、修改uip_popt.h文件
 #define UIP_FIXEDETHADDR  1 enc28j60,固定MAC地址
然后在uip.c中的代码#if UIP_FIXEDETHADDR后面添加:
#define UIP_ETHADDR0 0x44
#define UIP_ETHADDR1 0x33
#define UIP_ETHADDR2 0x4C
#define UIP_ETHADDR3 0x11
#define UIP_ETHADDR4 0x22
#define UIP_ETHADDR5 0x33
     八、在main函数中,首先修改本设备信息
  uip_ipaddr(ipaddr, 192,168,1,xxx);
  uip_sethostaddr(ipaddr);
  uip_ipaddr(ipaddr, 192,168,1,1);
  uip_setdraddr(ipaddr);
  uip_ipaddr(ipaddr, 255,255,255,0);
  uip_setnetmask(ipaddr);
然后打开web client注释掉的部分
 webclient_init(); 
 resolv_init();  
 uip_ipaddr(ipaddr,192,168,1,1);
 resolv_conf(ipaddr); 
 resolv_query("www.xxx.com");
    九、修改main.c的resolv_found函数,差不多改成下面这样
void resolv_found(char *name, u16_t *ipaddr) 
{
    if(ipaddr != NULL)
 {
  webclient_get(“www.xxx.com”,80, “/xxx/xxx”);
 }
}
www.xxx.com是网页服务器,80是网络端口,/xxx/xxx是网页目录
    十:这个问题可能是我用的AS6.1编译器的问题,也提一下,在webclient.c里面。
关于报错:value required as increment operand
进入错误点++((char *)uip_appdata);
把这个拆分一下就行char* temp = (char *)uip_appdata;
    Uip_appdata = ++temp;

    到这里基本的连接就结束了,只要能进入webclient_connect()这个函数,恭喜你,联网已经OK了,数据处理找webclient_datahandler(char* data,u16_t len);完善看个人需求了,写得比较粗陋,大家将就着看吧。

    再放个代码地址,感兴趣的去下吧,我加了些简单的注释http://download.csdn.net/detail/u011376744/7451509

1 0
原创粉丝点击