作者共發了7篇帖子。 內容轉換:不轉換▼
 
點擊 回復
1273 6
【教程】给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

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
(快捷鍵:Ctrl+Enter)
 

本帖信息

點擊數:1273 回複數:6
評論數: ?
作者:巨大八爪鱼
最後回復:巨大八爪鱼
最後回復時間:2017-4-1 19:00
 
©2010-2024 Arslanbar Ver2.0
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。