zcbzjx 发表于 2012-10-9 08:38:48

【翻译教程】enc28J60 和 Arduino (3)——作为客户端

本帖最后由 zcbzjx 于 2013-2-22 19:50 编辑

    国庆节参加完小舅子的婚礼终于回北京了,继续。。。。

    第三篇文章,我会介绍如何连接一个网站并获取返回的信息。

    当你学会了如何(使用静态ip地址或者通过DHCP服务器自动获取ip地址)把你的Arduino连接到网络后,你需要学习如何向一个网站发送数据和接收该网站的返回数据。
    为了使下面的例子更实际,我编写了一个简单的php网页,每次连接将随机返回一句格言,地址如下http://www.lucadentella.it/demo/aphorisms.php。

    我们来编写一个Arduino代码来获得这些格言并输出到串口。

DNS

    通常我们连接一个网站是键入他的域名(如www.sina.com.cn),我们的电脑,会通过一个dns服务器将他的域名解析为相应ip来进行连接。
   
    在arduino中配置你网络对应的dns服务器地址是非常重要的:

    如果你的arduino是采用DHCP服务器来进行配置,通常DNS服务器地址也是自动获取的。
    如果是静态配置,那么你调用 staticSetup()方法时需要包含DNS服务器地址。#include <EtherCard.h>
static byte mymac[] = {0xDD,0xDD,0xDD,0x00,0x00,0x01};
static byte myip[] = {192,168,1,10};
static byte gatewayip[] = {192,168,1,1};
static byte dnsip[] = {151,99,125,2};
...
ether.staticSetup(myip, gatewayip, dnsip);你可以用dnsLookup()方法验证域名服务器是否正常。char website[] PROGMEM = "www.lucadentella.it";
...
if (!ether.dnsLookup(website))
Serial.println("DNS failed");
else
Serial.println("DNS resolution done");
ether.printIp("SRV IP:\t", ether.hisip);连接

    EtherCard库提供了一个非常方便的方法browseUrl()来连接一个网站,This method prepares the connection; which is completed in following steps performed(不知道咋个翻译) – during the loop - 通过我们已经学了的2个指令:ether.packetLoop(ether.packetReceive());非常重要的是需要保持这两个指令运行,才能使代码正常工作。
   
    browseUrl()方法需要一些参数:

    prog_char urlbuf,地址的 固定部分;
    const char * urlbuf_varpart,地址的变量部分;
    prog_char hoststr,网站的名称;
    void (*callback)(byte,word,word)),这是一个回调函数名称,连接结束时调用的函数。

    地址分为两部分,以优化内存的利用率:静态部分存储在flash中(PSTR()命令),以节省RAM空间。
   
回调函数

    回调函数包含连接结束时执行的一个动作,在这个例子,是在串口打印出网站返回的格言。
    你可以选择任意的函数名称,但必须声明如下的参数:static void response_callback (byte status, word off, word len)第一个参数为连接的状态,第二个参数为响应存储在buffer中的偏移量,第三个参数为响应的长度。

    要理解偏移量(OFF)参数的含义,你必须要注意的以太网连接发送和接收的所有数据存储在我们定义的缓冲区中:byte Ethernet::buffer;你收到数据,整个数据包(包含头文件及校验字段等),都存储在这个缓冲区中,偏移量值告诉我们从那个字段开始存储这个数据包,及哪儿是我们收到的网页响应。
    下面是一个回调函数在串口打印网页的响应:static void response_callback (byte status, word off, word len) {

Serial.print((const char*) Ethernet::buffer + off);
}如果你运行这个代码(你可以在这个链接找到)(注意要把回调函数改成以上回调函数),你就可以看到如下信息:

    arduino正确配置了DHCP,它解析“www.lucadentella.it”这个域名,连接网站,打印网站响应。

    响应不仅包含格言,还包含了HTTP头文件。你需要打印所有的响应,然后通过文本编辑器(推荐notepad++),找到它们有多少个字符:

    这些行位于接收缓冲器中的格言之前。所以我们需要改变回调函数,打印207个字符之后的缓冲区的内容:static void response_callback (byte status, word off, word len) {

Serial.print((const char*) Ethernet::buffer + off + 207);
}经过以上更改,你就可以接收到正确的数据:


返回目录

弘毅 发表于 2012-10-9 09:06:52

:lol好贴。。。。

清水 发表于 2012-10-9 09:21:50

好帖,求外网连接内网教程

zhangdeyue1 发表于 2012-10-9 09:40:49

:lol等了几天了,谢谢老师分享~!

zcbzjx 发表于 2012-10-9 10:40:30

清水 发表于 2012-10-9 09:21 static/image/common/back.gif
好帖,求外网连接内网教程

能具体点么。

小猪会轮滑 发表于 2012-10-9 12:19:34

:lol:lol:lol:lol

清水 发表于 2012-10-9 12:26:24

zcbzjx 发表于 2012-10-9 10:40 static/image/common/back.gif
能具体点么。

就是我用webserve将传感器采集来的数据在网页上显示出来,但现在只能内网查看,如果我想通过外网看一下我内网的网页。我同学说要路由器什么端口映射什么的。

zcbzjx 发表于 2012-10-9 13:07:11

恩,这个和这个etherCard库没什么关系了,和路由器设置有关,建议还是通过客户端的形式,将数据发送到外网平台。可以用yeelink平台或者cosm平台。

清水 发表于 2012-10-9 15:17:26

zcbzjx 发表于 2012-10-9 13:07 static/image/common/back.gif
恩,这个和这个etherCard库没什么关系了,和路由器设置有关,建议还是通过客户端的形式,将数据发送到外网平 ...

哦,cosm我成功了,yeelink还没试过,等会我试一下。不过我还是希望自己架设服务器,这个有难度

太行摄狼 发表于 2012-10-22 07:31:47

ha好帖,这几帖弄一块就方便了

葱头同学 发表于 2012-12-15 19:26:56

本帖最后由 葱头同学 于 2012-12-15 19:46 编辑

有没有完整的代码
噢 看到了 原文有链接

鳄鱼de眼泪 发表于 2013-3-12 23:50:06

原作者没给出代码。但是在example中有。// Demo using DHCP and DNS to perform a web client request.
// 2011-06-08 <[email protected]> http://opensource.org/licenses/mit-license.php

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer;
static uint32_t timer;

char website[] PROGMEM = "www.google.com";

// called when the client request is complete
static void my_callback (byte status, word off, word len) {
Serial.println(">>>");
Ethernet::buffer = 0;
Serial.print((const char*) Ethernet::buffer + off);
Serial.println("...");
}

void setup () {
Serial.begin(57600);
Serial.println("\n");

if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
    Serial.println("DHCP failed");

ether.printIp("IP:", ether.myip);
ether.printIp("GW:", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);

if (!ether.dnsLookup(website))
    Serial.println("DNS failed");
   
ether.printIp("SRV: ", ether.hisip);
}

void loop () {
ether.packetLoop(ether.packetReceive());

if (millis() > timer) {
    timer = millis() + 5000;
    Serial.println();
    Serial.print("<<< REQ ");
    ether.browseUrl(PSTR("/foo/"), "bar", website, my_callback);
}
}

鳄鱼de眼泪 发表于 2013-3-12 23:54:40

改成本例子就是:// Demo using DHCP and DNS to perform a web client request.
// 2011-06-08 <[email protected]> http://opensource.org/licenses/mit-license.php

#include <EtherCard.h>

// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

byte Ethernet::buffer;
static uint32_t timer;

char website[] PROGMEM = "www.lucadentella.it";

// called when the client request is complete
static void response_callback (byte status, word off, word len) {

Serial.print((const char*) Ethernet::buffer + off + 207);
}

void setup () {
Serial.begin(57600);
Serial.println("\n");

if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
    Serial.println( "Failed to access Ethernet controller");
if (!ether.dhcpSetup())
    Serial.println("DHCP failed");

ether.printIp("IP:", ether.myip);
ether.printIp("GW:", ether.gwip);
ether.printIp("DNS: ", ether.dnsip);

if (!ether.dnsLookup(website))
    Serial.println("DNS failed");
   
ether.printIp("SRV: ", ether.hisip);
}

void loop () {
ether.packetLoop(ether.packetReceive());

if (millis() > timer) {
    timer = millis() + 5000;
    Serial.println();
    Serial.print("<<< REQ ");
    ether.browseUrl(PSTR("/demo/"), "aphorisms.php", website, response_callback);
}
}

鳄鱼de眼泪 发表于 2013-3-13 00:00:13

由于他服务器的变化 已经变成了 HTTP/1.1 200 OK
Date: Tue, 12 Mar 2013 15:58:01 GMT
Server: Apache
X-Powered-By: PHP/5.3.3-7+squeeze14
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 98
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/html
X-Pad: avoid browser bug

259个字符了

最好还是通过两个换行实现。

鳄鱼de眼泪 发表于 2013-3-13 00:03:36

原谅我的不仔细。
https://github.com/lucadentella/enc28j60_tutorial这是作者给的代码。
页: [1] 2 3 4
查看完整版本: 【翻译教程】enc28J60 和 Arduino (3)——作为客户端