單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網(wǎng)單片機
W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機,它為用戶帶來前所未有的集成化體驗。這顆芯片將強大的組件集于一身,具體來說,一顆W55MH32內(nèi)置高性能Arm? Cortex-M3核心,其主頻最高可達216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨立的32KB以太網(wǎng)收發(fā)緩存,可供8個獨立硬件socket使用。如此配置,真正實現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。
在封裝規(guī)格上,W55MH32提供了兩種選擇:QFN100和QFN68。
W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復雜工控場景設計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設資源,能夠輕松應對工業(yè)控制中多樣化的連接需求,無論是與各類傳感器、執(zhí)行器的通信,還是對復雜工業(yè)協(xié)議的支持,都能游刃有余,成為復雜工控領域的理想選擇。同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網(wǎng)關模組等場景,軟件使用方法一致。更多信息和資料請進入http://www.w5500.com/網(wǎng)站或者私信獲取。
此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網(wǎng)絡通信安全再添保障。
為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32L這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實現(xiàn)調(diào)試、下載以及串口打印日志等功能。開發(fā)板將所有外設全部引出,拓展功能也大幅提升,便于開發(fā)者全面評估芯片性能。
若您想獲取芯片和開發(fā)板的更多詳細信息,包括產(chǎn)品特性、技術(shù)參數(shù)以及價格等,歡迎訪問官方網(wǎng)頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。

第九章 W55MH32 HTTP Server示例
本篇文章我們將詳細介紹如何在W55MH32芯片上面實現(xiàn)HTTP Server功能,并通過實戰(zhàn)例程,為大家講解如何通過瀏覽器修改W55MH32的網(wǎng)絡地址信息。
該例程用到的其他網(wǎng)絡協(xié)議,例如DHCP,請參考相關章節(jié)。有關W55MH32的初始化過程,也請參考相關章節(jié),這里將不再贅述。
1 HTTP協(xié)議簡介
HTTP(超文本傳輸協(xié)議,HyperText Transfer Protocol)是一種用于分布式、協(xié)作式、超媒體信息系統(tǒng)的應用層協(xié)議,基于 TCP/IP通信協(xié)議來傳遞數(shù)據(jù),是萬維網(wǎng)(WWW)的數(shù)據(jù)通信的基礎。設計 HTTP最初的目的是為了提供一種發(fā)布和接收 HTML頁面的方法,通過 HTTP或者 HTTPS協(xié)議請求的資源由統(tǒng)一資源標識符(Uniform Resource Identifiers,URI)來標識。
以上是HTTP協(xié)議的簡介,如想深入了解該協(xié)議,請參考mozilla網(wǎng)站上的介紹: HTTP 概述 - HTTP | MDN
2 HTTP協(xié)議特點
基于請求-響應模型:客戶端發(fā)起請求,服務器處理后返回響應。例如,用戶在瀏覽器輸入網(wǎng)址時,瀏覽器會向?qū)掌靼l(fā)送HTTP請求,服務器返回網(wǎng)頁內(nèi)容。
無狀態(tài)性:HTTP本身不保存請求之間的狀態(tài),每次請求獨立。但可以通過Cookie、Session等機制實現(xiàn)狀態(tài)保持。
無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求并收到客戶的應答后,便立即斷開連接。
3 HTTP Server應用場景
W55MH32使用HTTP Server模式可以進行以下幾種應用:
設備配置和管理:通過瀏覽器訪問W55MH32提供的WEB界面,實現(xiàn)網(wǎng)絡配置,系統(tǒng)參數(shù)調(diào)整,固件升級等操作。
實時監(jiān)控和數(shù)據(jù)展示:通過瀏覽器訪問W55MH32提供的WEB頁面,實時監(jiān)控傳感器數(shù)據(jù),狀態(tài)信息,以及查看工作日志等。
遠程控制:通過瀏覽器訪問W55MH32提供的WEB頁面進行遠程控制設備,如開關等。
4 HTTP協(xié)議的基本工作流程
HTTP的請求-響應模型通常由以下幾個步驟組成
建立連接:客戶端與服務器之間基于TCP/IP協(xié)議建立連接。
發(fā)送請求:客戶端向服務器發(fā)送請求,請求中包含要訪問的資源的 URL、請求方法(GET、POST、PUT、DELETE等)、請求頭(例如,Accept、User-Agent)以及可選的請求體(對于 POST 或 PUT請求)。
處理請求:服務器接收到請求后,根據(jù)請求中的信息找到相應的資源,執(zhí)行對應的處理操作。這可能涉及從數(shù)據(jù)庫中檢索數(shù)據(jù)、生成動態(tài)內(nèi)容或者簡單地返回靜態(tài)文件。
發(fā)送響應:服務器將處理后的結(jié)果封裝在響應中,并將其發(fā)送回客戶端。響應包含狀態(tài)碼(用于指示請求的成功或失敗)、響應頭(例如,Content-Type、Content-Length)以及可選的響應體(例如,HTML頁面、圖像數(shù)據(jù))。
關閉連接:在完成請求-響應周期后,客戶端和服務器之間的連接將被關閉,除非使用了持久連接(如 HTTP/1.1中的 keep-alive)。
5 HTTP請求方法
在HTTP協(xié)議中,GET和POST是兩種常用的請求方法,用于客戶端向服務器發(fā)送數(shù)據(jù)和獲取資源。
GET方法
GET方法通常用于從服務器獲取資源。它有以下特點:
參數(shù)傳遞:請求參數(shù)通過URL中的查詢字符串傳遞,形如?key1=value1&key2=value2。
數(shù)據(jù)大小限制:由于參數(shù)附加在URL后,長度可能受URL長度限制(取決于瀏覽器和服務器設置)。
安全性:數(shù)據(jù)在URL中明文顯示,不適合傳遞敏感信息。
請求格式:
GET HTTP/
Request-URI:表示目標資源的路徑,可能包含參數(shù)。
Version:HTTP協(xié)議版本。
Headers:包含元信息,例如客戶端的屬性、支持的格式等。
Blank Line:空行。
POST方法
POST方法通常用于向服務器提交數(shù)據(jù)。它有以下特點:
參數(shù)傳遞:數(shù)據(jù)放在請求體中,而不是URL中。
數(shù)據(jù)大小限制:POST請求的體積沒有明顯限制,可以傳遞大量數(shù)據(jù)。
安全性:數(shù)據(jù)在請求體中傳輸,相對來說更安全。
請求格式:
POST HTTP/
Request-URI:目標資源的路徑,通常是API的端點。
Headers:元信息,例如內(nèi)容類型和長度。
Blank Line:空行,區(qū)分頭和主體。
Body:數(shù)據(jù)的主體,包含客戶端發(fā)送到服務器的長度。
6 HTTP協(xié)議響應內(nèi)容
HTTP協(xié)議響應內(nèi)容包含狀態(tài)行、響應頭以及響應體三個部分。
狀態(tài)行
HTTP狀態(tài)行包含HTTP協(xié)議版本、狀態(tài)碼以及狀態(tài)描述。
狀態(tài)碼由三個十進制數(shù)字組成,第一個十進制數(shù)字定義了狀態(tài)碼的類型。
狀態(tài)碼分為五類:
1xx(信息性狀態(tài)碼):表示接收的請求正在處理。
2xx(成功狀態(tài)碼):表示請求正常處理完畢。
3xx(重定向狀態(tài)碼):需要后續(xù)操作才能完成這一請求。
4xx(客戶端錯誤狀態(tài)碼):表示請求包含語法錯誤或無法完成。
5xx(服務器錯誤狀態(tài)碼):服務器在處理請求的過程中發(fā)生了錯誤。
示例:
HTTP/1.1 200 OK
響應頭
響應頭則會包含內(nèi)容類型、長度、編碼等信息。
常見的響應頭字段有:
Content-Type:響應內(nèi)容的MIME類型,例如 text/html、application/json。
Content-Length:響應內(nèi)容的字節(jié)長度。
Server:服務器信息。
Set-Cookie:設置客戶端的Cookie。
示例:
Content-Type: text/html; charset=UTF-8 Content-Length: 3495 Server: Apache/2.4.41 (Ubuntu)
響應體
響應體包含實際的數(shù)據(jù)內(nèi)容,具體形式取決于響應的類型和請求內(nèi)容。例如:HTML頁面內(nèi)容,JSON數(shù)據(jù),文件的二進制數(shù)據(jù)等。
如果是狀態(tài)碼為204 No Content或 304 Not Modified的響應,則通常沒有正文。
注意:響應體和響應頭之間會添加一個空行來分隔內(nèi)容。
7 Web頁面的基本構(gòu)成
HTML(超文本標記語言)
、、。
作用:定義網(wǎng)頁的結(jié)構(gòu)和內(nèi)容。
內(nèi)容:
結(jié)構(gòu)標簽:如
內(nèi)容標簽:如
、
、、。
表單標簽:如 、、。
CSS(層疊樣式表)
作用:控制網(wǎng)頁的樣式和布局。
內(nèi)容:
字體設置:如 font-family、font-size。
顏色設置:如 color、background-color。
布局設計:如 margin、padding、display、flex。
響應式設計:如媒體查詢(@media)。
JavaScript(腳本語言)
作用:增加網(wǎng)頁的交互性和動態(tài)功能。
應用:
表單驗證。
動畫效果。
與服務器交互(如通過 AJAX請求)。
處理用戶事件(如點擊、懸停)。
Meta信息
中。
作用:提供頁面的元數(shù)據(jù),通常包含在
內(nèi)容:
網(wǎng)頁標題:
字符集:。
SEO信息:如 。
設備適配:如 。
示例:
!DOCTYPE html?>
Simple Page/title?>
body { font-family: Arial, sans-serif; text-align: center; padding: 20px; }
button { padding: 10px 20px; cursor: pointer; }
/style?>
/head?>
Hello, Web!/h1?> Click the button for a surprise./p?> Click Me/button?> /body?> /html?>
8 Web頁面交互
Web頁面實現(xiàn)HTTP請求的方式:
HTTP請求頁面
描述:客戶端通過 HTTP協(xié)議向服務器發(fā)送請求,服務器處理后返回響應。
特點:
最基礎的交互方式。
包括常見的 HTTP方法:GET、POST、PUT、DELETE等。
示例:
GET請求:瀏覽器訪問網(wǎng)頁,獲取靜態(tài)資源(HTML、CSS、JavaScript等)。
POST請求:提交表單數(shù)據(jù)。
表單提交
描述:通過 HTML表單向服務器提交數(shù)據(jù)。
特點:
表單數(shù)據(jù)會被編碼后隨請求發(fā)送。
可使用 GET或 POST方法。
示例:
Submit/button?>
/form?>
AJAX(Asynchronous JavaScript and XML)
描述:使用 JavaScript在后臺與服務器通信,更新部分頁面內(nèi)容而無需刷新整個頁面。
特點:
提高用戶體驗,減少頁面加載時間。
現(xiàn)代開發(fā)中多用 JSON代替 XML。
示例:
fetch('/api/data', {
method: 'GET'
})
.then(response => response.json())
.then(data => console.log(data));
Web服務器響應處理
直接響應
定義:服務器直接處理請求,返回靜態(tài)資源或簡單的動態(tài)內(nèi)容,而不調(diào)用外部腳本或程序。
特點
高效:直接處理請求,無需額外調(diào)用外部程序,適合靜態(tài)內(nèi)容。
適用場景:
靜態(tài)資源(HTML、CSS、JavaScript、圖像等)的分發(fā)。
輕量級動態(tài)內(nèi)容生成。
工作流程
客戶端發(fā)送 HTTP請求。
服務器解析請求 URL,查找相應的資源(如文件路徑)。
直接讀取資源內(nèi)容并返回給客戶端,附加適當?shù)?HTTP響應頭。
CGI響應
定義:服務器通過 CGI(Common Gateway Interface)調(diào)用外部程序或腳本,處理客戶端請求并生成動態(tài)響應內(nèi)容。
特點
靈活性:可以動態(tài)生成內(nèi)容,支持復雜邏輯。
適用場景:
動態(tài)內(nèi)容生成(如用戶登錄、數(shù)據(jù)查詢)。
與數(shù)據(jù)庫交互或其他后臺服務的復雜邏輯處理。
工作流程
客戶端發(fā)送 HTTP請求。
服務器解析請求并將請求數(shù)據(jù)(如 URL參數(shù)或表單數(shù)據(jù))傳遞給 CGI程序。
CGI程序處理請求,生成響應內(nèi)容并返回給服務器。
服務器將 CGI程序生成的內(nèi)容包裝為 HTTP響應發(fā)送給客戶端。
9實現(xiàn)過程
接下來,我們看看如何通過瀏覽器修改W55MH32的網(wǎng)絡配置。
注意:測試實例需要PC端和W55MH32處于同一網(wǎng)段。
首先需要編寫網(wǎng)頁內(nèi)容,這里我們寫了一個網(wǎng)頁配置頁面的內(nèi)容以及提交后等待重啟頁面的內(nèi)容,如下所示:
#define index_page "n"
"n"
" W55MH32 Configuration Page/title?>n"
" n"
" body { font-family: Arial, sans-serif; margin: 20px; padding: 20px; background-color: #f4f4f9; }n"
" h1 { text-align: center; color: #333; }n"
" form { max-width: 400px; margin: auto; background: #ffffff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }n"
" label { display: block; margin-bottom: 8px; font-weight: bold; }n"
" input[type=text], input[type=submit] { width: 400px; padding: 8px; margin-bottom: 12px; border: 1px solid #ccc; border-radius: 4px; }n"
" input[type=submit] { background-color: #4CAF50; color: white; border: none; cursor: pointer; }n"
" input[type=submit]:hover { background-color: #45a049; }n"
" input[readonly] { background-color: #e9ecef; color: #6c757d; border: 1px solid #ced4da; cursor: not-allowed; }n"
" .error { color: red; font-size: 12px; margin-top: -10px; margin-bottom: 10px; }n"
" input::placeholder { color: #aaa; font-style: italic; }n"
" /style?>n"
" n"
" function validateForm(event) {n"
" const ipPattern = /^(\d{1,3}\.){3}\d{1,3}$/;n"
" let isValid = true;n"
" document.querySelectorAll('.error').forEach(e => e.textContent = '');n"
" const fields = ['ip', 'subnet', 'gateway', 'dns'];n"
" fields.forEach(field => {n"
" const input = document.forms[0][field];n"
" if (input.value.trim() === '') {n"
" input.placeholder = 'e.g., 192.168.1.1';n"
" document.getElementById(field + '-error').textContent = 'This field is required.';n"
" isValid = false;n"
" } else if (!ipPattern.test(input.value)) {n"
" document.getElementById(field + '-error').textContent = 'Invalid IP address format.';n"
" isValid = false;n"
" }n"
" });n"
" if (!isValid) {n"
" event.preventDefault();n"
" }n"
" }n"
" /script?>n"
"/head?>n"
"
n" " W55MH32 Configuration Page/h1?>n" " n" " MAC Address: /label?> n" " IP Address: /label?>
n" " Subnet Mask: /label?>
n" " Default Gateway: /label?>
n" " DNS Server: /label?>
n" " n" " /form?>n" "/body?>n" "/html?>n"
這里,我們提交網(wǎng)絡地址信息的方式為POST,提交的地址為config.cgi:
#define CONFIG_SUCCESS_PAGE
"!DOCTYPE html?>n"
"n"
"n"
" n"
" n"
" Configuration Modification Succeeded/title?>n"
" n"
" body {n"
" font-family: Arial, sans-serif;n"
" text-align: center;n"
" padding-top: 100px;n"
" background-color: #f0f0f0; n"
" }n"
" h1 {n"
" color: green;n"
" animation: fadeInOut 2s infinite;n"
" }n"
" #countdown {n"
" font-size: 24px;n"
" margin-top: 20px;n"
" opacity: 0; n"
" animation: fadeIn 1s forwards;n"
" animation-delay: 1s; n"
" }n"
" @keyframes fadeIn {n"
" from {n"
" opacity: 0;n"
" }n"
" to {n"
" opacity: 1;n"
" }n"
" }n"
" /style?>n"
"/head?>n"
"
n" " Configuration Modification Succeeded!/h1?>n" " Will redirect in 10 seconds. Please wait.../p?>n" "n" " let seconds = 10;n" " const countdownElement = document.getElementById('countdown');n" " const countdownInterval = setInterval(() => {n" " seconds--;n" " countdownElement.textContent = `Will redirect in ${seconds} seconds. Please wait...`;n" " if (seconds === 0) {n" " clearInterval(countdownInterval);n" " window.location.href = 'http://%d.%d.%d.%d/';n" " }n" " }, 1000);n" "/script?>n" "/body?>n" "/html?>"
步驟一:從EEPROM中讀取網(wǎng)絡地址信息并配置
check_eeprom_network_info(&default_net_info); network_init(ethernet_buf, &default_net_info);
check_eeprom_network_info()函數(shù)的作用是檢查EEPROM中是否有網(wǎng)絡地址信息,如果有則賦值給default_net_info結(jié)構(gòu)體。函數(shù)內(nèi)容如下:
uint8_t check_eeprom_network_info(wiz_NetInfo *net_info)
{
wiz_NetInfo eeprom_net_info = {0};
/*-----------------------------------------------------------------------------------*/
if (ee_CheckDevice(EEPROM_DEV_ADDR) == 1)
{
/* No EEPROM detected */
printf("No serial EEPROM detected!rn");
return 0;
}
ee_ReadBytes((uint8_t *)&eeprom_net_info, 0, sizeof(eeprom_net_info));
if (eeprom_net_info.mac[0] == 0x00 && eeprom_net_info.mac[1] == 0x08 && eeprom_net_info.mac[2] == 0xdc)
{
memcpy(net_info, &eeprom_net_info, sizeof(wiz_NetInfo));
return 1;
}
return 0;
}
步驟二:注冊網(wǎng)頁內(nèi)容及HTTP Server初始化
printf("Please enter% d.% d.% d.% d in your browser to access the %s HTTP serverrn", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3], _WIZCHIP_ID_);
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", net_info.mac[0], net_info.mac[1], net_info.mac[2], net_info.mac[3], net_info.mac[4], net_info.mac[5]);
sprintf(ip, "%d.%d.%d.%d", net_info.ip[0], net_info.ip[1], net_info.ip[2], net_info.ip[3]);
sprintf(sn, "%d.%d.%d.%d", net_info.sn[0], net_info.sn[1], net_info.sn[2], net_info.sn[3]);
sprintf(gw, "%d.%d.%d.%d", net_info.gw[0], net_info.gw[1], net_info.gw[2], net_info.gw[3]);
sprintf(dns, "%d.%d.%d.%d", net_info.dns[0], net_info.dns[1], net_info.dns[2], net_info.dns[3]);
sprintf(page, (char *)index_page, mac, ip, sn, gw, dns);
reg_httpServer_webContent((uint8_t *)"index.html", (uint8_t *)page); // Build HTTP server web pages
httpServer_init(http_tx_ethernet_buf, http_rx_ethernet_buf, 1, socknumlist); // Initializing the HTTP server
reg_httpServer_webContent()函數(shù)的作用是注冊web內(nèi)容,這里可以是頁面,也可以是JavaScript代碼。
httpServer_init的作用是初始化HTTP Server參數(shù),四個參數(shù)分別是HTTP發(fā)送緩存、HTTP接收緩存、使用的SOCKET數(shù)量以及對應的SOCKET列表。
步驟三:注冊HTTP超時中斷程序
/**
* @brief 1ms timer IRQ Handler
* @param none
* @return none
*/
void TIM3_IRQHandler(void)
{
static uint32_t tim3_1ms_count = 0;
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
tim3_1ms_count++;
if (tim3_1ms_count >= 1000)
{
DHCP_time_handler();
httpServer_time_handler();
tim3_1ms_count = 0;
}
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
}
步驟四:運行HTTP Server程序
while (1)
{
httpServer_run(SOCKET_ID);
}
httpServer_run()函數(shù)的邏輯跟TCP Server基本一致,也是運行了一個狀態(tài)機,根據(jù)SOCKET不同狀態(tài),執(zhí)行相應的HTTP Server部分的處理,內(nèi)容如下:
void httpServer_run(uint8_t seqnum)
{
uint8_t s; // socket number
uint16_t len;
uint32_t gettime = 0;
#ifdef _HTTPSERVER_DEBUG_
uint8_t destip[4] = {
0,
};
uint16_t destport = 0;
#endif
http_request = (st_http_request *)pHTTP_RX; // Structure of HTTP Request
parsed_http_request = (st_http_request *)pHTTP_TX;
// Get the H/W socket number
s = getHTTPSocketNum(seqnum);
/* HTTP Service Start */
switch (getSn_SR(s))
{
case SOCK_ESTABLISHED:
// Interrupt clear
if (getSn_IR(s) & Sn_IR_CON)
{
setSn_IR(s, Sn_IR_CON);
}
// HTTP Process states
switch (HTTPSock_Status[seqnum].sock_status)
{
case STATE_HTTP_IDLE:
if ((len = getSn_RX_RSR(s)) > 0)
{
if (len > DATA_BUF_SIZE) len = DATA_BUF_SIZE;
len = recv(s, (uint8_t *)http_request, len);
*(((uint8_t *)http_request) + len) = '';
parse_http_request(parsed_http_request, (uint8_t *)http_request);
#ifdef _HTTPSERVER_DEBUG_
getSn_DIPR(s, destip);
destport = getSn_DPORT(s);
printf("rn");
printf("> HTTPSocket[%d] : HTTP Request received ", s);
printf("from %d.%d.%d.%d : %drn", destip[0], destip[1], destip[2], destip[3], destport);
#endif
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONErn", s);
#endif
// HTTP 'response' handler; includes send_http_response_header / body function
http_process_handler(s, parsed_http_request);
gettime = get_httpServer_timecount();
// Check the TX socket buffer for End of HTTP response sends
while (getSn_TX_FSR(s) != (getSn_TxMAX(s)))
{
if ((get_httpServer_timecount() - gettime) > 3)
{
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE: TX Buffer clear timeoutrn", s);
#endif
break;
}
}
if (HTTPSock_Status[seqnum].file_len > 0)
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_INPROC;
else
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE; // Send the 'HTTP response' end
}
break;
case STATE_HTTP_RES_INPROC:
/* Repeat: Send the remain parts of HTTP responses */
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_INPROCrn", s);
#endif
// Repeatedly send remaining data to client
send_http_response_body(s, 0, http_response, 0, 0);
if (HTTPSock_Status[seqnum].file_len == 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
break;
case STATE_HTTP_RES_DONE:
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_DONErn", s);
#endif
// Socket file info structure re-initialize
HTTPSock_Status[seqnum].file_len = 0;
HTTPSock_Status[seqnum].file_offset = 0;
HTTPSock_Status[seqnum].file_start = 0;
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_IDLE;
//#ifdef _USE_SDCARD_
// f_close(&fs);
//#endif
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
http_disconnect(s);
break;
default:
break;
}
break;
case SOCK_CLOSE_WAIT:
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : ClOSE_WAITrn", s); // if a peer requests to close the current connection
#endif
disconnect(s);
break;
case SOCK_CLOSED:
if (reboot_flag)
{
NVIC_SystemReset();
}
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : CLOSEDrn", s);
#endif
if (socket(s, Sn_MR_TCP, HTTP_SERVER_PORT, 0x00) == s) /* Reinitialize the socket */
{
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : OPENrn", s);
#endif
}
break;
case SOCK_INIT:
listen(s);
break;
case SOCK_LISTEN:
break;
default:
break;
} // end of switch
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
}
步驟五:請求內(nèi)容處理
POST方式的CGI請求處理,在httpUtil.c文件的predefined_set_cgi_processor()函數(shù)中處理。
GET方式的CGI請求處理,在httpUtil.c文件的predefined_get_cgi_processor()函數(shù)中處理。
uint8_t predefined_set_cgi_processor(uint8_t *uri_name, uint8_t *uri, uint8_t *buf, uint16_t *len)
{
if (strcmp((const char *)uri_name, "config.cgi") == 0)
{
uint8_t *param;
wiz_NetInfo new_net_info = {0};
wizchip_getnetinfo(&new_net_info);
param = get_http_param_value((char *)uri, "ip"); //獲取IP地址
parse_ip((char *)param, new_net_info.ip); //更新IP地址
param = get_http_param_value((char *)uri, "subnet"); //獲取子網(wǎng)掩碼
parse_ip((char *)param, new_net_info.sn); //更新子網(wǎng)掩碼
param = get_http_param_value((char *)uri, "gateway"); //獲取默認網(wǎng)關
parse_ip((char *)param, new_net_info.gw); //更新默認網(wǎng)關
param = get_http_param_value((char *)uri, "dns"); //獲取DNS地址
parse_ip((char *)param, new_net_info.dns); //更新DNS地址
步驟六:重啟設備
在httpServer_run()函數(shù)中,當SOCKET處于SOCK_CLOSED狀態(tài)時(即上次請求已經(jīng)處理完畢),再進行復位操作,避免出現(xiàn)客戶端請求后,W55MH32未響應就重啟導致客戶端請求超時的情況。
case SOCK_CLOSED:
if (reboot_flag)
{
NVIC_SystemReset();
}
10運行結(jié)果
燒錄例程運行后,首先進行了PHY鏈路檢測,然后是通過DHCP獲取網(wǎng)絡地址并打印網(wǎng)絡地址信息,最后HTTP Server程序開始監(jiān)聽客戶端的請求并處理響應,如下圖所示:

接著我們打開瀏覽器,輸入W55MH32的IP地址進行訪問。

然后我們將IP地址改為192.168.1.33,DNS服務器地址改為114.114.114.114,并點擊Submit按鈕。
等待W55MH32重啟后,瀏覽器會自動跳轉(zhuǎn)至新地址。

11總結(jié)
本文介紹了在 W55MH32芯片上實現(xiàn) HTTP Server功能,并通過瀏覽器修改其網(wǎng)絡地址信息的方法。闡述了 HTTP協(xié)議的概念、特點、應用場景、工作流程、請求方法、響應內(nèi)容,以及 Web頁面構(gòu)成和交互方式。展示了在W55MH32上實現(xiàn)的過程。
下一篇將講解在該芯片上實現(xiàn) SNTP授時功能,介紹從 SNTP服務器獲取準確時間的原理和實現(xiàn)步驟。敬請期待!
WIZnet是一家無晶圓廠半導體公司,成立于 1998年。產(chǎn)品包括互聯(lián)網(wǎng)處理器 iMCU?,它采用 TOE(TCP/IP卸載引擎)技術(shù),基于獨特的專利全硬連線 TCP/IP。iMCU?面向各種應用中的嵌入式互聯(lián)網(wǎng)設備。
WIZnet在全球擁有 70多家分銷商,在香港、韓國、美國設有辦事處,提供技術(shù)支持和產(chǎn)品營銷。
香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。
審核編輯 黃宇
-
嵌入式
+關注
關注
5192文章
20271瀏覽量
331645
發(fā)布評論請先 登錄
第三十章 W55MH32 HTTP_Server&NetBIOS示例
第二十九章 W55MH32 Modbus_TCP_Server示例
第二十六章 W55MH32?上位機搜索和配置示例
第十八章 W55MH32 FTP_Server示例
第十七章 W55MH32 ARP示例
第十六章 W55MH32 PING示例
第十五章 W55MH32 SNMP示例
第十四章 W55MH32 TFTP示例
第十二章 W55MH32 NetBIOS示例
第十章 W55MH32 SNTP示例
第六章 W55MH32 UDP?Multicast示例
第五章 W55MH32 UDP示例
第三章 W55MH32 TCP Client示例
第二章 W55MH32 DHCP示例
W55MH32高性能以太網(wǎng)單片機教程 第九章 窗口看門狗(WWDG)
第九章 W55MH32 HTTP Server示例
評論