W5500 HTTP WEB服务器开发笔记 STM32F103单片机参考程序

W5500感觉挺火的,因为使用该芯片开发以太网硬件和软件都比较简单,一个小小的51单片机就可以瞬间变成一个WebServer WEB服务器。W5500自带16K的发送数据缓存,可以同时创建8个TCP/UDP socket连接,使用时,需要合理分配这16K的资源。

W5500的缺点也是有的,就是还是发热比较严重,不过比W5100好很多了。我在使用W5500+STM32F103设计WEB服务器时,就觉得想把网页设计的很漂亮比较困难,因为一个图片动不动就是几十K,想把jQuery包含进来发觉文件太大,后来发现Zepto.js比较适合的,压缩后就9K多一点。当然可以把一个大的文件分成好几次发送,比如把一个100K的文件分成10个部分,每次发送10K字节。不过怎么实现我还没有研究过,怎么把一个很大的网页文件分成好几次发送,反正暂时我还不知道。毕竟既然你使用单片机做WEB服务器程序,一般应该不会有需求传送很大的文件的,因为文件很大了,单片机的FLASH或者RAM容量也不够。

核心程序其实很简单的,这也是使用W5500的优势,几句代码就可以实现一个WEB服务器了,当然这样做的话同一个时刻只能支持单个用户访问,不能支持并发访问的,想要支持并发访问的话可以创建多个SOCKET呀。
    while(1)
    {
        status = getSn_SR(0);
        if (status == SOCK_INIT)
        {
            listen(0);            
        }
        else if (status == SOCK_ESTABLISHED)
        {
            if(getSn_IR(0) & Sn_IR_CON)
            {
              setSn_IR(0, Sn_IR_CON);
            }
            memset(Net_Buffer, 0, NET_BUFFER_SIZE);
            ret = recv(0, Net_Buffer, NET_BUFFER_SIZE);
            if (ret > 0)
            {
                respond();
            }
        }
        else if (status == SOCK_CLOSE_WAIT)
        {
          disconnect(0);
        }
        else if (status == SOCK_CLOSED)
        {
            ret = socket(0, Sn_MR_TCP, Host_Port, 0);
            if(ret != 0)
            {
              while(1);
            }
        }            
    }
具体一点的可以参考以下链接:http://www.embed-net.com/thread-61-1-1.html,写的还是很好的,有STM32F103的,还有STM32F4的源代码下载。

下面是我做好的WEB服务器访问效果图,将开发版用网线与PC相连,访问192.168.1.1,效果如下:


附HTTP WEB SERVER部分的详细源代码。
该源代码已在工业级网关产品上稳定运行,可放心使用。
W5500库请到官网下载,需要先掌握JavaScript、CSS、HTTP协议等基础知识。
#include "whost.h"
#include "sys.h"
#include <string.h>
#include "stm32f10x.h"
#include <stdio.h>
#include "main.h"
#include "Ethernet/wizchip_conf.h"
#include "Ethernet/W5500/w5500.h"
#include "Ethernet/socket.h"
#include "flash.h"
#include "setup.h"

#define SOCK_HOST                                    0

const wiz_NetInfo Host_Info = { 
                        .mac = {0x00,0x08,0xdc,0x02,0x00,0x01},
                        .ip = {192, 168, 1, 1},
                        .sn = {255, 255, 255, 0},
                        .gw = {192, 168, 1, 1},
                        .dns = {192, 168, 1, 1},
                        .dhcp = NETINFO_STATIC
};
uint16_t Host_Port = 80;

U8 whost_respond(void);

const char Authorization[] = {
"HTTP/1.1 401 Authorization Required\r\n"
"Server: MyServer\r\n"
"WWW-Authenticate: Basic realm=\"Cloud System\"\r\n"
"Content-Type: text/html\r\n"
"Content-Length: 169\r\n\r\n"
"<HTML>\r\n<HEAD>\r\n<TITLE>Error</TITLE>\r\n"
"<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\">\r\n"
"</HEAD>\r\n<BODY><H1>401 Unauthorized.</H1></BODY>\r\n</HTML>"
};

const char Not_Found[] = {
"HTTP/1.1 404 Not Found\r\n\
Server: MyServer\r\n\
Content-Length: 145\r\n\
Connection: close\r\n\
Content-Type: text/html\r\n\r\n\
<html><head><title>404 Not Found</title></head><body>\r\n\
<h1>Not Found</h1>\r\n\
<p>The requested URL was not found on this server.</p>\r\n\
</body></html>"
};

const char Index_Admin[] = {
"HTTP/1.1 200 OK\r\n\
Server: MyServer\r\n\
Content-Length: 2400\r\n\
Connection: keep-alive\r\n\
Content-Type: text/html\r\n\r\n\
<?xml version=\"1.0\" encoding=\"utf-8\" ?>\
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\
<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\
<meta http-equiv=\"Cache-Control\" content=\"no-cache\"/>\
<title>Cloud System Setting</title>\
<link href=\"/style.css\" rel=\"stylesheet\" type=\"text/css\" />\
</head><body>\
<h1><p>Cloud System Setting</p></h1>\
<form method=\"post\" action=\"/post\">\
<input type=\"hidden\" name=\"copyright\" value=\"microic.com\" />\
<h2>Device Information</h2>\
<div><lable>Serial Number:</lable><input id=\"serial\" type=\"text\" /></div>\
<div><lable>Version:</lable><input id=\"version\" type=\"text\" value=\"V1.0.3\" /></div>\
<h2>Serial Port</h2>\
<div><lable>Baud Rate:</lable><input name=\"baud\" type=\"text\" /></div>\
<div><lable>Parity:</lable>\
<select name=\"parity\">\
<option value =\"none\">None</option>\
<option value =\"odd\">Odd</option>\
<option value =\"even\">Even</option>\
</select></div>\
<div><lable>Timeout(ms):</lable><input name=\"timeout\" type=\"text\" /></div>\
<h2>Network</h2>\
<div><lable>Physical Address:</lable><input name=\"mac\" type=\"text\" /></div>\
<div><lable>DHCP/Static:</lable>\
<select name=\"dhcp\">\
<option value =\"true\">DHCP</option>\
<option value =\"false\">Static</option>\
</select></div>\
<div><lable>IP Address:</lable><input name=\"ip\" type=\"text\" /></div>\
<div><lable>Subnet Mask:</lable/><input name=\"sn\" type=\"text\" /></div>\
<div><lable>Default Gateway:</lable><input name=\"gw\" type=\"text\" /></div>\
<div><lable>DNS Server:</lable><input name=\"dns\" type=\"text\" /></div>\
<h2>Application</h2>\
<div><lable>Encryption Key:</lable><input name=\"key\" type=\"text\" /></div>\
<div><lable>Server Address:</lable><input name=\"server\" type=\"text\" /></div>\
<div><lable>Requested URL:</lable><input name=\"url\" type=\"text\" /></div>\
<div><lable>Update Interval(s):</lable><input name=\"interval\" type=\"text\" /></div>\
<div><lable></lable><input type=\"button\" name=\"save\" value=\"Save\" />\
  <a href=\"quit\">Exit</a></div>\
<input type=\"hidden\" name=\"support\" value=\"万硅\" />\
</form>\
<br />\
</body></html>\
"
};

const char Index_User[] = {
"HTTP/1.1 200 OK\r\n\
Server: MyServer\r\n\
Content-Length: 2400\r\n\
Connection: keep-alive\r\n\
Content-Type: text/html\r\n\r\n\
<?xml version=\"1.0\" encoding=\"utf-8\" ?>\
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\
<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\
<meta http-equiv=\"Cache-Control\" content=\"no-cache\"/>\
<title>Cloud System Setting</title>\
<link href=\"/style.css\" rel=\"stylesheet\" type=\"text/css\" />\
</head><body>\
<h1><p>Cloud System Setting</p></h1>\
<form method=\"post\" action=\"/post\">\
<input type=\"hidden\" name=\"copyright\" value=\"microic.com\" />\
<h2>Device Information</h2>\
<div><lable>Serial Number:</lable><input id=\"serial\" type=\"text\" /></div>\
<div><lable>Version:</lable><input id=\"version\" type=\"text\" value=\"V1.0.3\" /></div>\
<h2>Serial Port</h2>\
<div><lable>Baud Rate:</lable><input name=\"baud\" type=\"text\" /></div>\
<div><lable>Parity:</lable>\
<select name=\"parity\">\
<option value =\"none\">None</option>\
<option value =\"odd\">Odd</option>\
<option value =\"even\">Even</option>\
</select></div>\
<div><lable>Timeout(ms):</lable><input name=\"timeout\" type=\"text\" /></div>\
<h2>Network</h2>\
<div><lable>Physical Address:</lable><input name=\"mac\" type=\"text\" /></div>\
<div><lable>DHCP/Static:</lable>\
<select name=\"dhcp\">\
<option value =\"true\">DHCP</option>\
<option value =\"false\">Static</option>\
</select></div>\
<div><lable>IP Address:</lable><input name=\"ip\" type=\"text\" /></div>\
<div><lable>Subnet Mask:</lable/><input name=\"sn\" type=\"text\" /></div>\
<div><lable>Default Gateway:</lable><input name=\"gw\" type=\"text\" /></div>\
<div><lable>DNS Server:</lable><input name=\"dns\" type=\"text\" /></div>\
\
<input name=\"key\" type=\"hidden\" />\
<input name=\"server\" type=\"hidden\" />\
<input name=\"url\" type=\"hidden\" />\
<input name=\"interval\" type=\"hidden\" />\
\
<div><lable></lable><input type=\"button\" name=\"save\" value=\"Save\" />\
  <a href=\"quit\">Exit</a></div>\
<input type=\"hidden\" name=\"support\" value=\"万硅\" />\
</form>\
<br />\
</body></html>\
"
};

const char Js[] = {
"HTTP/1.1 200 OK\r\n\
Server: MyServer\r\n\
Content-Length: 1200\r\n\
Connection: close\r\n\
Content-Type: application/x-javascript\r\n\r\n\
function g(str){\
var obj = document.getElementById(str);\
if (obj) return obj;\
obj = document.getElementsByName(str);\
if(obj && obj.length>0) return obj[0];\
obj = document.getElementsByTagName(str);\
if(obj && obj.length>0) return obj[0];\
return new Object();\
}\
function error(){setTimeout(\"window.location.reload();\",2000);}\
function load(){\
try{\
var obj=g(\"iframe\").contentDocument.getElementById(\"data\");\
if(!obj) error();\
var items=obj.innerHTML.split(\"&\");\
for(var i=0;i<items.length;i++){\
var s=items[i].split(\"=\");g(s[0]).value=decodeURIComponent(s[1]);}\
}catch(e){}\
}\
window.onload=function(){\
load();fill();\
g(\"save\").onclick=function(){\
g(\"form\").submit();};\
};\
"
};

const char Css[] = {
"HTTP/1.1 200 OK\r\n\
Server: MyServer\r\n\
Content-Length: 600\r\n\
Connection: close\r\n\
Content-Type: text/css\r\n\r\n\
*{margin:0;padding:0px;font-family:Arial;}\
body{backgound-color:#F7F7F7;}\
form{margin:0 0 0 8px;display:block;}\
div{clear:both;padding:4px;}\
h1{padding:8px 8px 8px 16px;background-color:#ee3923;color:#FFFFFF;display:block;}\
h2{color:#222222;clear:both;padding:8px 8px 8px 16px;margin:0 0 8px 0;display:block;border-bottom:1px solid #CCCCCC;}\
lable{margin:0 0 0 20px;padding:2px;width:135px;display:block;float:left;color:#222222;}\
input,select{padding:2px;float:left;color:#666666;}\
iframe{height:0;border:0;}\
"
};

const char Head[] = {
"HTTP/1.1 200 OK\r\n\
Server: MyServer\r\n\
Content-Length: 500\r\n\
Connection: close\r\n\
Content-Type: text/html\r\n\r\n\
"
};

const char Post[] = {
"<html><head>\
<meta http-equiv=\"Content-Type\"\
content=\"text/html; charset=utf-8\" />\
<title>Post</title>\
<style>\
div{position:absolute;left:50%;bottom:15%;\
margin-left:-300px;width:600px;height:80px;text-align:center;}\
h1{font-size:72px;font-family:Arial;color:#ee3923;};\
</style>\
</head><body>\
<div><h1>Cloud System</h1></div>\
<script>\
alert(\"Your settings was saved successfully!\");\
location.href=\"/\";\
</script>\
</body></html>"
};

void whost_init(void)
{
    ctlnetwork(CN_SET_NETINFO, (void*)&Host_Info);
}

void whost_run(void)
{
    uint8_t status;
    int32_t ret;

    while(1)
    {
        IWDG_ReloadCounter();

        status = getSn_SR(SOCK_HOST);
        if (status == SOCK_INIT)
        {
            listen(SOCK_HOST);            
        }
        else if (status == SOCK_ESTABLISHED)
        {
            if(getSn_IR(SOCK_HOST) & Sn_IR_CON)
            {
        setSn_IR(SOCK_HOST, Sn_IR_CON);
            }
            memset(Net_Buffer, 0, NET_BUFFER_SIZE);
            ret = recv(SOCK_HOST, Net_Buffer, NET_BUFFER_SIZE);
            if (ret > 0)
            {
                if (whost_respond()) break;
                //disconnect(SOCK_HOST);
            }
        }
        else if (status == SOCK_CLOSE_WAIT)
        {
      disconnect(SOCK_HOST);
        }
        else if (status == SOCK_CLOSED)
        {
            ret = socket(SOCK_HOST, Sn_MR_TCP, Host_Port, SF_IO_NONBLOCK);
            if(ret != SOCK_HOST)
            {
                    while(1);
            }
        }            
    }
}

U8 whost_respond(void)
{
    char * data = NULL;
    U16 len = 0;
    if (!strstr((char *)Net_Buffer, "YWRtaW46YWRtaW4="))
    {
        send(SOCK_HOST, (U8 *)Authorization, sizeof(Authorization) - 1);
        return 0;
    }
    
    if (strstr((char *)Net_Buffer, "GET / "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Index_User, sizeof(Index_User));
        strcat((char *)App_Buffer, "<iframe style=\"width:0;\" src=\"/data\"></iframe>");
        strcat((char *)App_Buffer, "<script type=\"text/javascript\" src=\"/cloud.js\"></script>");
        strcat((char *)App_Buffer, "<script>function fill(){");
        strcat((char *)App_Buffer, "g(\"serial\").value=\"");
        strcat((char *)App_Buffer, Serial_String);    
        strcat((char *)App_Buffer, "\";");
        strcat((char *)App_Buffer, "}</script>");
        send(SOCK_HOST, (U8 *)App_Buffer, 3000);
    }
    if (strstr((char *)Net_Buffer, "GET /admin "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Index_Admin, sizeof(Index_Admin));
        strcat((char *)App_Buffer, "<iframe style=\"width:0;\" src=\"/data\"></iframe>");
        strcat((char *)App_Buffer, "<script type=\"text/javascript\" src=\"/cloud.js\"></script>");
        strcat((char *)App_Buffer, "<script>function fill(){");
        strcat((char *)App_Buffer, "g(\"serial\").value=\"");
        strcat((char *)App_Buffer, Serial_String);    
        strcat((char *)App_Buffer, "\";");
        strcat((char *)App_Buffer, "}</script>");
        send(SOCK_HOST, (U8 *)App_Buffer, 3000);
    }
    else if (strstr((char *)Net_Buffer, "POST /post "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Head, sizeof(Head));
        strcat((char *)App_Buffer, Post);
        send(SOCK_HOST, (U8 *)App_Buffer, 688);
        data = strstr((char *)Net_Buffer, "copyright=microic.com");
        if (data)
        {
            len = strlen(data) + 1;
            if (len > DATA_BUFFER_SIZE) len = DATA_BUFFER_SIZE;
            flash_store((U8 *)data, len);
        }
    }
    else if (strstr((char *)Net_Buffer, "GET /data "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Head, sizeof(Head));
        flash_read(Data_Buffer, DATA_BUFFER_SIZE);
        strcat((char *)App_Buffer, "<html><body><p id=\"data\">");
        strcat((char *)App_Buffer, (char *)Data_Buffer);
        strcat((char *)App_Buffer, "</p></body></html>");
        send(SOCK_HOST, (U8 *)App_Buffer, 688);
    }
    else if (strstr((char *)Net_Buffer, "GET /cloud.js "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Js, sizeof(Js) - 1);
        send(SOCK_HOST, (U8 *)App_Buffer, 1600);
    }
    else if (strstr((char *)Net_Buffer, "GET /style.css "))
    {
        memset(App_Buffer, '\n', APP_BUFFER_SIZE);
        memcpy(App_Buffer, Css, sizeof(Css) - 1);
        send(SOCK_HOST, (U8 *)App_Buffer, 1000);
    }
    else if (strstr((char *)Net_Buffer, "GET /quit "))
    {
        return 1;
    }
    else
    {
        send(SOCK_HOST, (U8 *)Not_Found, sizeof(Not_Found) - 1);
    }
    
    return 0;
}


发表于:2015-05-20 17:33:27

原文链接(转载请保留): http://www.multisilicon.com/blog/a23323847.html

友情链接: MICROIC
首页