目前共有12篇帖子。 內容轉換:不轉換▼
 
點擊 回復
2252 11
【步骤】lwip-2.0.2在STM32F103RC+ENC28J60网卡上无操作系统移植(不使用STM32库函数)
一派護法 十九級
1樓 發表于:2017-3-19 17:43
【1】去lwip的官方网站下载最新的lwip-2.0.2.zip
【2】新建空白STM32工程,建工程时一定要在Manage Run-Time Environment对话框里勾选启动文件
【3】新建一个main.c文件,文件内容如下:
#include <stdio.h>
#include <stm32f10x.h>
#include "lwip/etharp.h" // etharp_tmr函数所在的头文件
#include "lwip/init.h" // lwip_init函数所在的头文件
#include "lwip/priv/tcp_priv.h" // tcp_tmr函数所在的头文件
#include "netif/ethernet.h" // ethernet_input函数所在头文件
#include "ENC28J60.h"

// 这两个函数位于ethernetif.c中, 但没有头文件声明
err_t ethernetif_init(struct netif *netif);
void ethernetif_input(struct netif *netif);

// 声明httptest.c中的函数
void init_http(void);

// printf串口输出
// 必须要在项目属性里勾选Use MicroLIB后才能使用
int fputc(int ch, FILE *fp)
{
    if (fp == &__stdout)
    {
        USART1->DR = ch;
        while ((USART1->SR & USART_SR_TXE) == 0);
    }
    return ch;
}

int main(void)
{
    struct ip4_addr ipaddr, netmask, gw;
    struct netif enc28j60;
    uint8_t cnt = 0;
   
    // 配置PA口
    RCC->APB2ENR = RCC_APB2ENR_IOPAEN;
    GPIOA->CRH = 0x000004b3; // PA8为开发板上的一个LED灯
    GPIOA->CRL = 0xb4bb0080;
    GPIOA->BSRR = GPIO_BSRR_BS1; // PA1为网卡中断输出
   
    // 配置SPI
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
    SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1; // 主机模式, 时钟至少需要8分频(BR=010), 也就是72MHz/8=9MHz
    SPI1->CR2 = SPI_CR2_SSOE; // 开CS片选输出
   
    // 配置串口
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
    USART1->BRR = 0x271; // 波特率: 115200
    USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
    printf("Hello World!\r\n");
   
    // 配置定时器
    RCC->APB1ENR = RCC_APB1ENR_TIM6EN;
    TIM6->ARR = 2499; // 共2500个数, 2500*0.1ms=250ms
    TIM6->PSC = 7199; // 72MHz/7200=10kHz -> 0.1ms
    TIM6->CR1 = TIM_CR1_URS; // 防止UG=1时UIF置位
    TIM6->EGR = TIM_EGR_UG; // 应用上述设置
    TIM6->CR1 |= TIM_CR1_CEN; // 开定时器
   
    lwip_init();
    IP4_ADDR(&ipaddr, 192, 168, 0, 2); // IP地址
    IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
    IP4_ADDR(&gw, 192, 168, 0, 1); // 网关
   
    netif_add(&enc28j60, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input);
    netif_set_default(&enc28j60); // 设为默认网卡
    netif_set_up(&enc28j60);
   
    printf("进入主循环...\r\n");
    init_http(); // 初始化HTTP服务
    while (1)
    {
        if (ENC28J60_GetPacketNum() != 0)
        {
            GPIOA->ODR ^= GPIO_ODR_ODR8; // PA8上的LED灯闪烁表明系统正常工作
            ethernetif_input(&enc28j60);
        }
       
        // 若定时器溢出
        if (TIM6->SR & TIM_SR_UIF)
        {
            // 250ms
            TIM6->SR &= ~TIM_SR_UIF; // 清除溢出标志
            cnt++;
            if (cnt >= 20)
            {
                // 250ms * 20 = 5s
                GPIOA->ODR ^= GPIO_ODR_ODR8; // LED灯每5秒钟改变一次状态
                cnt = 0;
                etharp_tmr(); // ARP定时处理
            }
            tcp_tmr(); // TCP定时处理
        }
    }
}
一派護法 十九級
2樓 發表于:2017-3-19 17:48
【4】创建ENC28J60的驱动程序文件ENC28J60.h和ENC28J60.c,放到工程的根目录中,文件内容见:
https://zh.arslanbar.net/post.php?t=24570
【5】在工程的根目录下创建Library/lwip文件夹,把下载下来的lwip压缩包中的src文件夹里的core、include和netif三个文件夹解压到里面
【6】创建Library/lwip/include/arch/cc.h文件,内容为空
【7】创建Library/lwip/include/lwipopts.h文件,内容如下:
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

/**
 * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
 * critical regions during buffer allocation, deallocation and memory
 * allocation and deallocation.
 */
#define SYS_LIGHTWEIGHT_PROT 0

/**
 * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
 * use lwIP facilities.
 */
#define NO_SYS 1 // 无操作系统
/**
 * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1
 * Mainly for compatibility to old versions.
 */
#define NO_SYS_NO_TIMERS 1  // 这样就不需要定义sys_now函数

/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
   lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
   byte alignment -> define MEM_ALIGNMENT to 2. */
#define MEM_ALIGNMENT 4

/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE (5 * 1024)

/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
   sends a lot of data out of ROM (or other static memory), this
   should be set high. */
#define MEMP_NUM_PBUF 10
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
   per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 6
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
   connections. */
#define MEMP_NUM_TCP_PCB 10
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
   connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 6
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
   segments. */
#define MEMP_NUM_TCP_SEG 12
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
   timeouts. */
#define MEMP_NUM_SYS_TIMEOUT 3

/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 10

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 1500

/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255

/* Controls if TCP should queue segments that arrive out of
   order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 0

/* TCP Maximum segment size. */
#define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */

/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF (2 * TCP_MSS)

/* TCP sender buffer space (pbufs). This must be at least = 2 *
   TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN (6 * TCP_SND_BUF) / TCP_MSS

/* TCP receive window. */
#define TCP_WND (2 * TCP_MSS)

/* ---------- ICMP options ---------- */
#define LWIP_ICMP 1

/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
   interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
   turning this on does currently not work. */
#define LWIP_DHCP 0

/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define UDP_TTL 255

/* ---------- Statistics options ---------- */
#define LWIP_STATS 0
#define LWIP_PROVIDE_ERRNO 1

// LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
#define LWIP_NETCONN 0

// LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
#define LWIP_SOCKET 0

// 这个必须要定义, 否则在执行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

#endif /* __LWIPOPTS_H__ */
一派護法 十九級
3樓 發表于:2017-3-19 17:52
【8】打开Library/lwip/netif/ethernetif.c文件,按照下面的中文部分的提示更改文件内容:
/**
 * @file
 * Ethernet Interface Skeleton
 *
 */

/*
 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 *
 * This file is part of the lwIP TCP/IP stack.
 *
 * Author: Adam Dunkels <adam@sics.se>
 *
 */

/*
 * This file is a skeleton for developing Ethernet network interface
 * drivers for lwIP. Add code to the low_level functions and do a
 * search-and-replace for the word "ethernetif" to replace it with
 * something that better describes your network interface.
 */

#include "lwip/opt.h"

//#if 0 /* don't build, this is only a skeleton, see previous comment */
#if 1 // 允许编译器编译该文件

#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "lwip/ethip6.h"
#include "lwip/etharp.h"
#include "netif/ppp/pppoe.h"

/* Define those to better describe your network interface. */
#define IFNAME0 'e'
#define IFNAME1 'n'

#include "ENC28J60.h" // 网卡驱动头文件

/**
 * Helper struct to hold private data used to operate your ethernet interface.
 * Keeping the ethernet address of the MAC in this struct is not necessary
 * as it is already kept in the struct netif.
 * But this is only an example, anyway...
 */
struct ethernetif {
  struct eth_addr *ethaddr;
  /* Add whatever per-interface state that is needed here. */
};

/* Forward declarations. */
// 这里必须去掉static
/*static */void  ethernetif_input(struct netif *netif);

/**
 * In this function, the hardware should be initialized.
 * Called from ethernetif_init().
 *
 * @param netif the already initialized lwip network interface structure
 *        for this ethernetif
 */
static void
low_level_init(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;

  /* set MAC hardware address length */
  netif->hwaddr_len = ETHARP_HWADDR_LEN;

  /* set MAC hardware address */
  // 设置MAC地址
  netif->hwaddr[0] = 'A';
  netif->hwaddr[1] = 'R';
  netif->hwaddr[2] = 'M';
  netif->hwaddr[3] = 'N';
  netif->hwaddr[4] = 'E';
  netif->hwaddr[5] = 'T';

  /* maximum transfer unit */
  netif->mtu = 1500;

  /* device capabilities */
  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
  netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;

#if LWIP_IPV6 && LWIP_IPV6_MLD
  /*
   * For hardware/netifs that implement MAC filtering.
   * All-nodes link-local is handled by default, so we must let the hardware know
   * to allow multicast packets in.
   * Should set mld_mac_filter previously. */
  if (netif->mld_mac_filter != NULL) {
    ip6_addr_t ip6_allnodes_ll;
    ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
    netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
  }
#endif /* LWIP_IPV6 && LWIP_IPV6_MLD */

  /* Do whatever else is needed to initialize interface. */
  ENC28J60_Init(netif->hwaddr); // 初始化网卡
}

/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *         an err_t value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *       strange results. You might consider waiting for space in the DMA queue
 *       to become available since the stack doesn't retry to send a packet
 *       dropped because of memory failure (except for the TCP timers).
 */

static err_t
low_level_output(struct netif *netif, struct pbuf *p)
{
  struct ethernetif *ethernetif = netif->state;
  struct pbuf *q;

  //initiate transfer();
  ENC28J60_InitSend(p->tot_len); // 初始化

#if ETH_PAD_SIZE
  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif

  for (q = p; q != NULL; q = q->next) {
    /* Send the data from the pbuf to the interface, one pbuf at a
       time. The size of the data in each pbuf is kept in the ->len
       variable. */
    //send data from(q->payload, q->len);
    ENC28J60_WriteBuf(q->payload, q->len); // 把内容放入缓冲区
  }

  //signal that packet should be sent();
  ENC28J60_BeginSend(); // 开始发送

  MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
  if (((u8_t*)p->payload)[0] & 1) {
    /* broadcast or multicast packet*/
    MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
  } else {
    /* unicast packet */
    MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
  }
  /* increase ifoutdiscards or ifouterrors on error */

#if ETH_PAD_SIZE
  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif

  LINK_STATS_INC(link.xmit);

  return ERR_OK;
}

/**
 * Should allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error
 */
static struct pbuf *
low_level_input(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;
  struct pbuf *p, *q;
  u16_t len;

  /* Obtain the size of the packet and put it into the "len"
     variable. */
  len = ENC28J60_GetPacketLength(); // 获取数据包长度

#if ETH_PAD_SIZE
  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif

  /* We allocate a pbuf chain of pbufs from the pool. */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

  if (p != NULL) {

#if ETH_PAD_SIZE
    pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif

    /* We iterate over the pbuf chain until we have read the entire
     * packet into the pbuf. */
    for (q = p; q != NULL; q = q->next) {
      /* Read enough bytes to fill this pbuf in the chain. The
       * available data in the pbuf is given by the q->len
       * variable.
       * This does not necessarily have to be a memcpy, you can also preallocate
       * pbufs for a DMA-enabled MAC and after receiving truncate it to the
       * actually received size. In this case, ensure the tot_len member of the
       * pbuf is the sum of the chained pbuf len members.
       */
      //read data into(q->payload, q->len);
      ENC28J60_ReadBuf(q->payload, q->len); // 读取缓冲区中的内容
    }
    //acknowledge that packet has been read();
    ENC28J60_EndReceive(); // 接收完成

    MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    if (((u8_t*)p->payload)[0] & 1) {
      /* broadcast or multicast packet*/
      MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
    } else {
      /* unicast packet*/
      MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
    }
#if ETH_PAD_SIZE
    pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif

    LINK_STATS_INC(link.recv);
  } else {
    //drop packet();
    ENC28J60_EndReceive(); // 丢弃数据包
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    MIB2_STATS_NETIF_INC(netif, ifindiscards);
  }

  return p;
}

/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 *
 * @param netif the lwip network interface structure for this ethernetif
 */
// 必须把static去掉, 让其他文件可以调用该函数
/*static */void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  /* move received packet into a new pbuf */
  p = low_level_input(netif);
  /* if no packet could be read, silently ignore this */
  if (p != NULL) {
    /* pass all packets to ethernet_input, which decides what packets it supports */
    if (netif->input(p, netif) != ERR_OK) {
      LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
      pbuf_free(p);
      p = NULL;
    }
  }
}

/**
 * Should be called at the beginning of the program to set up the
 * network interface. It calls the function low_level_init() to do the
 * actual setup of the hardware.
 *
 * This function should be passed as a parameter to netif_add().
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return ERR_OK if the loopif is initialized
 *         ERR_MEM if private data couldn't be allocated
 *         any other err_t on error
 */
err_t
ethernetif_init(struct netif *netif)
{
  struct ethernetif *ethernetif;

  LWIP_ASSERT("netif != NULL", (netif != NULL));

  ethernetif = mem_malloc(sizeof(struct ethernetif));
  if (ethernetif == NULL) {
    LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
    return ERR_MEM;
  }

#if LWIP_NETIF_HOSTNAME
  /* Initialize interface hostname */
  netif->hostname = "lwip";
#endif /* LWIP_NETIF_HOSTNAME */

  /*
   * Initialize the snmp variables and counters inside the struct netif.
   * The last argument should be replaced with your link speed, in units
   * of bits per second.
   */
  MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);

  netif->state = ethernetif;
  netif->name[0] = IFNAME0;
  netif->name[1] = IFNAME1;
  /* We directly use etharp_output() here to save a function call.
   * You can instead declare your own function an call etharp_output()
   * from it if you have to do some checks before sending (e.g. if link
   * is available...) */
  netif->output = etharp_output;
#if LWIP_IPV6
  netif->output_ip6 = ethip6_output;
#endif /* LWIP_IPV6 */
  netif->linkoutput = low_level_output;

  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);

  /* initialize the hardware */
  low_level_init(netif);

  return ERR_OK;
}

#endif /* 0 */
一派護法 十九級
4樓 發表于:2017-3-19 17:56
【9】在项目根目录下创建httptest.c文件(一个简单的测试文件),内容如下:
#include <string.h>
#include "lwip/tcp.h" // 一般情况下需要包含的头文件

#define STR_AND_SIZE(str) (str), strlen(str)

err_t http_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    char len[10]; // 存放HTML内容的长度
    char str[200]; // 存放HTML内容
   
    char name[100];
    char *pstr;
    uint8_t i = 0;
    if (p != NULL)
    {
        // 提取页面名称
        pstr = (char *)p->payload;
        while (*pstr++ != ' ');
        while (*pstr != ' ')
            name[i++] = *pstr++;
        name[i] = '\0'; // 不要忘了结束name字符串
        tcp_recved(tpcb, p->tot_len);
       
        // 生成HTML内容
        sprintf(str, "<meta charset=\"gb2312\"><title>获取网页名称</title><div style=\"font-family:Arial\"><b>请求的网页文件名称是: </b>%s</div>", name);
       
        sprintf(len, "%d", strlen(str)); // HTML内容的长度
        tcp_write(tpcb, STR_AND_SIZE("HTTP/1.1 200 OK\r\nContent-Length: "), TCP_WRITE_FLAG_MORE);
        tcp_write(tpcb, STR_AND_SIZE(len), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
        tcp_write(tpcb, STR_AND_SIZE("\r\nKeep-Alive: timeout=5, max=100\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"), TCP_WRITE_FLAG_MORE);
        tcp_write(tpcb, STR_AND_SIZE(str), TCP_WRITE_FLAG_COPY); // 发送HTML内容
        pbuf_free(p);
    }
    return ERR_OK;
}

err_t http_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    tcp_recv(newpcb, http_recv);
    return ERR_OK;
}

void init_http(void)
{
    struct tcp_pcb *tpcb = tcp_new();
    tcp_bind(tpcb, IP_ADDR_ANY, 80);
    tpcb = tcp_listen(tpcb);
    tcp_accept(tpcb, http_accept);
}
一派護法 十九級
5樓 發表于:2017-3-19 18:02
【10】将根目录下的c文件,以及以下文件夹中的文件(不含子目录)添加到工程中:
Library/lwip/core/
Library/lwip/core/ipv4/
还有两个单独的文件:
Library/lwip/netif/ethernet.c
Library/lwip/netif/ethernetif.c
一派護法 十九級
6樓 發表于:2017-3-19 18:06
【11】打开项目属性
(1) 在Target选项卡中勾选Use MicroLIB复选框(这样就可以执行printf函数)
(2) 在C/C++选项卡下的Include Paths文本框中输入C语言头文件的包含路径:
.\Library\lwip\include;.\
(3) 如果使用JLink下载程序,则应该在Debug选项卡的设置中勾选Reset and Run复选框,这样下载程序后程序就会自动运行
一派護法 十九級
7樓 發表于:2017-3-19 18:09
【12】把网线直接插到电脑的网卡上,电脑网卡的IP地址和网关设为192.168.0.1,子网掩码保持默认。
下载并运行程序,用浏览器访问http://192.168.0.2/或在控制台中执行ping 192.168.0.2。
一派護法 十九級
8樓 發表于:2017-3-19 18:16
一派護法 十九級
9樓 發表于:2017-3-29 21:02

可以将ENC28J60网卡通过一根网线连接到无线路由器上,然后Android手机无线连接路由器,经测试可以用浏览器访问单片机上的网站。

下面是截图:

一派護法 十九級
10樓 發表于:2017-3-29 21:04
笔记本电脑通过无线网卡连接无线路由器后,也能访问单片机上的网站。
电脑和手机的IP都是DHCP自动分配的,路由器的IP是192.168.1.1,单片机的IP在程序中静态指定:
IP4_ADDR(&ipaddr, 192, 168, 1, 53); // IP地址
IP4_ADDR(&netmask, 255, 255, 255, 0); // 子网掩码
IP4_ADDR(&gw, 192, 168, 1, 1); // 网关(路由器的地址)
一派護法 十九級
11樓 發表于:2017-3-29 21:10

如果把ENC28J60插到路由器上后电脑不能访问其网页,那么肯定就是这个路由器的问题(有可能是路由器的设置不正确),换一个路由器就可以了。
本人在测试的时候就是插在工作室里的路由器上无法访问,也ping不通(详见https://zh.arslanbar.net/post.php?t=24583),但插在寝室的路由器上就可以。

ENC28J60的数据包虽然发送成功,但只要到了工作室的路由器上就立刻被丢弃了,就连查询路由器MAC地址的ARP数据包也会被丢弃,到目前为止都还没找到原因。

一派護法 十九級
12樓 發表于:2017-3-31 13:59

之前的路由器无法识别ARMNET这个MAC地址,所以拒收了所有的数据包。换一个MAC地址问题就完全解决了:

netif->hwaddr[0] = 0;
netif->hwaddr[1] = 0x12;
netif->hwaddr[2] = 0x34;
netif->hwaddr[3] = 0x56;
netif->hwaddr[4] = 0x78;
netif->hwaddr[5] = 0x90;

回復帖子

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

本帖信息

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