設置 | 登錄 | 註冊

作者共發了7篇帖子。

【教程】給lwip添加計算機名(NetBIOS名稱)

1樓 巨大八爪鱼 2017-4-1 18:25

原始工程:https://zh.arslanbar.net/post.php?t=24584

【最終效果】

1.能夠在PC端通過設定的計算機名ping通網卡。

2.能在PC端通過「http://計算機名」訪問單片機上的Web伺服器。

【注意】

路由器DHCP頁面顯示的設備名不屬於計算機名,而是發送請求時hostname欄位的名稱。兩者可以不相同。

2樓 巨大八爪鱼 2017-4-1 18:40

【步驟】
1. 首先找到之前下載的lwip-2.0.2壓縮包裡面的src/apps/netbiosns/netbiosns.c文件,將其複製到「工程根目錄/Library/lwip/apps/netbiosns」文件夾中。複製前需要先創建apps和netbiosns文件夾。
2. 打開工程,把剛才複製的c文件添加到lwip組下。
3. 打開main.c文件,添加包含頭文件的語句:
#include "lwip/apps/netbiosns.h"
這個頭文件位於「工程根目錄/Library/lwip/include/lwip/apps」文件夾下,之前已經複製過來了。
然後找到main函數,在dhcp_start函數前添加以下兩句代碼:
netbiosns_set_name("ENC28J60"); // 指定計算機名
netbiosns_init();


注意,原工程中下面這句話設置的是路由器中顯示的設備名,跟這裡的計算機名沒有關係。這個名稱是在申請DHCP動態IP位址時發送給路由器的。
enc28j60.hostname = "ENC28J60_Device";

3樓 巨大八爪鱼 2017-4-1 18:43

4. 允許網卡接收所有的廣播數據包。
打開ENC28J60.c文件,在網卡初始化函數ENC28J60_Init中找到下面這句話:
ENC28J60_Write(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);
將其改為:
ENC28J60_Write(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | 0x01);
其中0x01為ERXFCON_BCEN(可在頭文件ENC28J60.h中定義)


設置後,網卡就能接收到PC端的ping命令發送的NetBIOS請求數據包。

4樓 巨大八爪鱼 2017-4-1 18:51

5. 最後我們需要解決Keil MDK編譯器本身的問題。
首先看下面的代碼:
struct test {
    uint8_t id;
    uint32_t value;
};

void fun(void)
{
    printf("sizeof(struct test)=%d\n", sizeof(struct test));
    printf("offset of test.id=%d\n", (uint32_t)&((struct test *)0)->id);
    printf("offset of test.value=%d\n", (uint32_t)&((struct test *)0)->value);
}

在單片機上運行該程序後,輸出如下:
sizeof(struct test)=8
offset of test.id=0
offset of test.value=4

我們會發現,本來成員變量id只有1個字節,編譯器卻分配了4個字節,導致整個結構體的大小為8位元組而不是4+1=5位元組,value的位置也跑到了第4位元組處。
雖然這可以方便32位單片機的操作,畢竟操作4位元組對齊後的成員變量只需要執行一次訪存操作。但是這卻會干擾lwip的正常功能,破壞數據包內容的正確性。
解決辦法是在定義結構體時在struct前加__packed:
__packed struct test {
    uint8_t id;
    uint32_t value;
};

這樣一來我們就可以得到正確的輸出:
sizeof(struct test)=5
offset of test.id=0
offset of test.value=1

5樓 巨大八爪鱼 2017-4-1 18:55
為了給所有的lwip結構體添加__packed關鍵字,打開之前創建的空白的cc.h文件,添加下面一句話:
#define PACK_STRUCT_BEGIN __packed
然後打開lwipopts.h文件,把之前定義的LWIP_SKIP_PACKING_CHECK宏刪掉,也就是刪除下面三句話:
// 這個必須要定義, 否則在執行lwip_init函數時會在串口中提示:
// Assertion "Struct packing not implemented correctly. Check your lwIP port." failed at line 345 in Library\lwip\core\init.c
#define LWIP_SKIP_PACKING_CHECK
6樓 巨大八爪鱼 2017-4-1 19:00

6. 編譯並下載程序。
程序運行後,我們會發現串口中沒有出現之前所說的Assertion警告,而是提示DHCP分配IP位址成功:
DHCP分配成功!
IP位址: 192.168.1.116
子網掩碼: 255.255.255.0
網關: 192.168.1.1


打開PC端的命令提示符cmd,輸入「ping ENC28J60」,檢查是否可以ping通我們設置的計算機名:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
C:\Users\Octopus>ping ENC28J60
Pinging ENC28J60 [192.168.1.116] with 32 bytes of data:
Reply from 192.168.1.116: bytes=32 time=2ms TTL=255
Reply from 192.168.1.116: bytes=32 time=27ms TTL=255
Reply from 192.168.1.116: bytes=32 time=1ms TTL=255
Reply from 192.168.1.116: bytes=32 time=1ms TTL=255
Ping statistics for 192.168.1.116:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 27ms, Average = 7ms
C:\Users\Octopus>


然後打開瀏覽器,在地址欄輸入「http://enc28j60」,看是否能打開網頁。

7樓 巨大八爪鱼 2017-4-1 19:00

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。