407自带以太网mac模块,一般外挂一个PHY芯片就可以实现以太网物理层;以下是stm32f407VE+enc28j60+lwip2.0.2实现最基本的以太网通信功能。
1. 新建工程,此处省略1000字。。。
2. 在工程目录下新建一个LWIP文件夹,将lwip-2.0.2.zip解压,将src文件夹里面的core、include、netif文件夹放到LWIP文件夹下。 在LWIP目录下新建一个arch文件夹待用。3. 在\LWIP\arch根目录下新建cc.h文件,内容如下:1 #include "stdio.h" 2 3 typedef unsigned char u8_t; 4 typedef signed char s8_t; 5 typedef unsigned short u16_t; 6 typedef signed short s16_t; 7 typedef unsigned long u32_t; 8 typedef signed long s32_t; 9 10 typedef u32_t mem_ptr_t; 11 12 /*************CPU存放数据定义为小段模式******************/ 13 #ifndef BYTE_ORDER 14 #define BYTE_ORDER LITTLE_ENDIAN 15 #endif 16 17 /**********使用KEIL/RVMDK开发工具时的宏定义**************/ 18 //#if defined(__arm__) && defined(__ARMCC_VERSION) 19 #define PACK_STRUCT_BEGIN __packed 20 #define PACK_STRUCT_STRUCT 21 #define PACK_STRUCT_END 22 #define PACK_STRUCT_FIELD(x) x 23 /*---define (sn)printf formatters for these lwip types, for lwip DEBUG/STATS--*/ 24 25 #define U16_F "4d" 26 #define S16_F "4d" 27 #define X16_F "4x" 28 #define U32_F "8ld" 29 #define S32_F "8ld" 30 #define X32_F "8lx" 31 32 #ifndef LWIP_PLATFORM_ASSERT 33 #define LWIP_PLATFORM_ASSERT(x) \ 34 do \ 35 { printf("Assertion \"%s\" failed at line %d in %s\n", x, __LINE__, __FILE__); \ 36 } while(0) 37 #endif 38 39 #ifndef LWIP_PLATFORM_DIAG 40 #define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0) 41 #endif 42 4.在LWIP\include根目录下新建一个lwipopts.h文件,内容如下: 43 #ifndef __LWIPOPTS_H__ 44 #define __LWIPOPTS_H__ 45 46 /** 47 * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain 48 * critical regions during buffer allocation, deallocation and memory 49 * allocation and deallocation. 50 */ 51 #define SYS_LIGHTWEIGHT_PROT 0 52 53 /** 54 * NO_SYS==1: Provides VERY minimal functionality. Otherwise, 55 * use lwIP facilities. 56 */ 57 #define NO_SYS 1 // 无操作系统 58 /** 59 * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 60 * Mainly for compatibility to old versions. 61 */ 62 #define NO_SYS_NO_TIMERS 1 // 这样就不需要定义sys_now函数 63 64 /* ---------- Memory options ---------- */ 65 /* MEM_ALIGNMENT: should be set to the alignment of the CPU for which 66 lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 67 byte alignment -> define MEM_ALIGNMENT to 2. */ 68 #define MEM_ALIGNMENT 4 69 70 /* MEM_SIZE: the size of the heap memory. If the application will send 71 a lot of data that needs to be copied, this should be set high. */ 72 #define MEM_SIZE (5 * 1024) 73 74 /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application 75 sends a lot of data out of ROM (or other static memory), this 76 should be set high. */ 77 #define MEMP_NUM_PBUF 10 78 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One 79 per active UDP "connection". */ 80 #define MEMP_NUM_UDP_PCB 6 81 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP 82 connections. */ 83 #define MEMP_NUM_TCP_PCB 10 84 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP 85 connections. */ 86 #define MEMP_NUM_TCP_PCB_LISTEN 6 87 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP 88 segments. */ 89 #define MEMP_NUM_TCP_SEG 12 90 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active 91 timeouts. */ 92 #define MEMP_NUM_SYS_TIMEOUT 3 93 94 /* ---------- Pbuf options ---------- */ 95 /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ 96 #define PBUF_POOL_SIZE 10 97 98 /* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ 99 #define PBUF_POOL_BUFSIZE 1500100 101 /* ---------- TCP options ---------- */102 #define LWIP_TCP 1103 #define TCP_TTL 255104 105 /* Controls if TCP should queue segments that arrive out of106 order. Define to 0 if your device is low on memory. */107 #define TCP_QUEUE_OOSEQ 0108 109 /* TCP Maximum segment size. */110 #define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */111 112 /* TCP sender buffer space (bytes). */113 #define TCP_SND_BUF (2 * TCP_MSS)114 115 /* TCP sender buffer space (pbufs). This must be at least = 2 *116 TCP_SND_BUF/TCP_MSS for things to work. */117 #define TCP_SND_QUEUELEN (6 * TCP_SND_BUF) / TCP_MSS118 119 /* TCP receive window. */120 #define TCP_WND (2 * TCP_MSS)121 122 /* ---------- ICMP options ---------- */123 #define LWIP_ICMP 1124 125 /* ---------- DHCP options ---------- */126 /* Define LWIP_DHCP to 1 if you want DHCP configuration of127 interfaces. DHCP is not implemented in lwIP 0.5.1, however, so128 turning this on does currently not work. */129 #define LWIP_DHCP 0130 131 /* ---------- UDP options ---------- */132 #define LWIP_UDP 1133 #define UDP_TTL 255134 135 /* ---------- Statistics options ---------- */136 #define LWIP_STATS 0137 #define LWIP_PROVIDE_ERRNO 1138 139 // LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)140 #define LWIP_NETCONN 0141 142 // LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)143 #define LWIP_SOCKET 0144 145 // 这个必须要定义, 否则在执行lwip_init函数时会在串口中提示:146 // Assertion "Struct packing not implemented correctly. Check your lwIP port." failed at line 345 in Library\lwip\core\init.c147 #define PACK_STRUCT_BEGIN __packed148 /*******************************************************************************************************************/149 #define LWIP_DEBUG 1150 #define LWIP_DBG_TYPES_ON LWIP_DBG_OFF151 152 /**153 * ETHARP_DEBUG: Enable debugging in etharp.c.154 */155 #define ETHARP_DEBUG LWIP_DBG_OFF156 157 /**158 * NETIF_DEBUG: Enable debugging in netif.c.159 */160 #define NETIF_DEBUG LWIP_DBG_OFF161 162 /**163 * PBUF_DEBUG: Enable debugging in pbuf.c.164 */165 #define PBUF_DEBUG LWIP_DBG_OFF166 167 /**168 * API_LIB_DEBUG: Enable debugging in api_lib.c.169 */170 #define API_LIB_DEBUG LWIP_DBG_OFF171 172 /**173 * API_MSG_DEBUG: Enable debugging in api_msg.c.174 */175 #define API_MSG_DEBUG LWIP_DBG_OFF176 177 /**178 * SOCKETS_DEBUG: Enable debugging in sockets.c.179 */180 #define SOCKETS_DEBUG LWIP_DBG_OFF181 182 /**183 * ICMP_DEBUG: Enable debugging in icmp.c.184 */185 #define ICMP_DEBUG LWIP_DBG_OFF186 187 /**188 * IGMP_DEBUG: Enable debugging in igmp.c.189 */190 #define IGMP_DEBUG LWIP_DBG_OFF191 192 /**193 * INET_DEBUG: Enable debugging in inet.c.194 */195 #define INET_DEBUG LWIP_DBG_OFF196 197 /**198 * IP_DEBUG: Enable debugging for IP.199 */200 #define IP_DEBUG LWIP_DBG_OFF201 202 /**203 * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass.204 */205 #define IP_REASS_DEBUG LWIP_DBG_OFF206 /**207 * RAW_DEBUG: Enable debugging in raw.c.208 */209 #define RAW_DEBUG LWIP_DBG_OFF210 211 /**212 * MEM_DEBUG: Enable debugging in mem.c.213 */214 #define MEM_DEBUG LWIP_DBG_OFF215 216 /**217 * MEMP_DEBUG: Enable debugging in memp.c.218 */219 #define MEMP_DEBUG LWIP_DBG_OFF220 221 /**222 * SYS_DEBUG: Enable debugging in sys.c.223 */224 #define SYS_DEBUG LWIP_DBG_OFF225 226 /**227 * TCP_DEBUG: Enable debugging for TCP.228 */229 #define TCP_DEBUG LWIP_DBG_OFF230 231 /**232 * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug.233 */234 #define TCP_INPUT_DEBUG LWIP_DBG_OFF235 /**236 * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit.237 */238 #define TCP_FR_DEBUG LWIP_DBG_OFF239 240 /**241 * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit242 * timeout.243 */244 #define TCP_RTO_DEBUG LWIP_DBG_OFF245 246 /**247 * TCP_CWND_DEBUG: Enable debugging for TCP congestion window.248 */249 #define TCP_CWND_DEBUG LWIP_DBG_OFF250 251 /**252 * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating.253 */254 #define TCP_WND_DEBUG LWIP_DBG_OFF255 256 /**257 * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions.258 */259 #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF260 /**261 * TCP_RST_DEBUG: Enable debugging for TCP with the RST message.262 */263 #define TCP_RST_DEBUG LWIP_DBG_OFF264 265 /**266 * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths.267 */268 #define TCP_QLEN_DEBUG LWIP_DBG_OFF269 270 /**271 * UDP_DEBUG: Enable debugging in UDP.272 */273 #define UDP_DEBUG LWIP_DBG_OFF274 275 /**276 * TCPIP_DEBUG: Enable debugging in tcpip.c.277 */278 #define TCPIP_DEBUG LWIP_DBG_OFF279 280 /**281 * PPP_DEBUG: Enable debugging for PPP.282 */283 #define PPP_DEBUG LWIP_DBG_OFF284 285 /**286 * SLIP_DEBUG: Enable debugging in slipif.c.287 */288 #define SLIP_DEBUG LWIP_DBG_OFF289 290 /**291 * DHCP_DEBUG: Enable debugging in dhcp.c.292 */293 #define DHCP_DEBUG LWIP_DBG_OFF294 295 /**296 * AUTOIP_DEBUG: Enable debugging in autoip.c.297 */298 #define AUTOIP_DEBUG LWIP_DBG_OFF299 300 /**301 * SNMP_MSG_DEBUG: Enable debugging for SNMP messages.302 */303 #define SNMP_MSG_DEBUG LWIP_DBG_OFF304 305 /**306 * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs.307 */308 #define SNMP_MIB_DEBUG LWIP_DBG_OFF309 310 /**311 * DNS_DEBUG: Enable debugging for DNS.312 */313 #define DNS_DEBUG LWIP_DBG_OFF314 #endif /* __LWIPOPTS_H__ */
4.在LWIP\include根目录下新建一个lwipopts.h文件,内容如下:
1 #ifndef __LWIPOPTS_H__ 2 #define __LWIPOPTS_H__ 3 4 /** 5 * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain 6 * critical regions during buffer allocation, deallocation and memory 7 * allocation and deallocation. 8 */ 9 #define SYS_LIGHTWEIGHT_PROT 0 10 11 /** 12 * NO_SYS==1: Provides VERY minimal functionality. Otherwise, 13 * use lwIP facilities. 14 */ 15 #define NO_SYS 1 // 无操作系统 16 /** 17 * NO_SYS_NO_TIMERS==1: Drop support for sys_timeout when NO_SYS==1 18 * Mainly for compatibility to old versions. 19 */ 20 #define NO_SYS_NO_TIMERS 1 // 这样就不需要定义sys_now函数 21 22 /* ---------- Memory options ---------- */ 23 /* MEM_ALIGNMENT: should be set to the alignment of the CPU for which 24 lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2 25 byte alignment -> define MEM_ALIGNMENT to 2. */ 26 #define MEM_ALIGNMENT 4 27 28 /* MEM_SIZE: the size of the heap memory. If the application will send 29 a lot of data that needs to be copied, this should be set high. */ 30 #define MEM_SIZE (5 * 1024) 31 32 /* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application 33 sends a lot of data out of ROM (or other static memory), this 34 should be set high. */ 35 #define MEMP_NUM_PBUF 10 36 /* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One 37 per active UDP "connection". */ 38 #define MEMP_NUM_UDP_PCB 6 39 /* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP 40 connections. */ 41 #define MEMP_NUM_TCP_PCB 10 42 /* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP 43 connections. */ 44 #define MEMP_NUM_TCP_PCB_LISTEN 6 45 /* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP 46 segments. */ 47 #define MEMP_NUM_TCP_SEG 12 48 /* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active 49 timeouts. */ 50 #define MEMP_NUM_SYS_TIMEOUT 3 51 52 /* ---------- Pbuf options ---------- */ 53 /* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ 54 #define PBUF_POOL_SIZE 10 55 56 /* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ 57 #define PBUF_POOL_BUFSIZE 1500 58 59 /* ---------- TCP options ---------- */ 60 #define LWIP_TCP 1 61 #define TCP_TTL 255 62 63 /* Controls if TCP should queue segments that arrive out of 64 order. Define to 0 if your device is low on memory. */ 65 #define TCP_QUEUE_OOSEQ 0 66 67 /* TCP Maximum segment size. */ 68 #define TCP_MSS (1500 - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */ 69 70 /* TCP sender buffer space (bytes). */ 71 #define TCP_SND_BUF (2 * TCP_MSS) 72 73 /* TCP sender buffer space (pbufs). This must be at least = 2 * 74 TCP_SND_BUF/TCP_MSS for things to work. */ 75 #define TCP_SND_QUEUELEN (6 * TCP_SND_BUF) / TCP_MSS 76 77 /* TCP receive window. */ 78 #define TCP_WND (2 * TCP_MSS) 79 80 /* ---------- ICMP options ---------- */ 81 #define LWIP_ICMP 1 82 83 /* ---------- DHCP options ---------- */ 84 /* Define LWIP_DHCP to 1 if you want DHCP configuration of 85 interfaces. DHCP is not implemented in lwIP 0.5.1, however, so 86 turning this on does currently not work. */ 87 #define LWIP_DHCP 0 88 89 /* ---------- UDP options ---------- */ 90 #define LWIP_UDP 1 91 #define UDP_TTL 255 92 93 /* ---------- Statistics options ---------- */ 94 #define LWIP_STATS 0 95 #define LWIP_PROVIDE_ERRNO 1 96 97 // LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) 98 #define LWIP_NETCONN 0 99 100 // LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)101 #define LWIP_SOCKET 0102 103 // 这个必须要定义, 否则在执行lwip_init函数时会在串口中提示:104 // Assertion "Struct packing not implemented correctly. Check your lwIP port." failed at line 345 in Library\lwip\core\init.c105 #define PACK_STRUCT_BEGIN __packed106 /*******************************************************************************************************************/107 #define LWIP_DEBUG 1108 #define LWIP_DBG_TYPES_ON LWIP_DBG_OFF109 110 /**111 * ETHARP_DEBUG: Enable debugging in etharp.c.112 */113 #define ETHARP_DEBUG LWIP_DBG_OFF114 115 /**116 * NETIF_DEBUG: Enable debugging in netif.c.117 */118 #define NETIF_DEBUG LWIP_DBG_OFF119 120 /**121 * PBUF_DEBUG: Enable debugging in pbuf.c.122 */123 #define PBUF_DEBUG LWIP_DBG_OFF124 125 /**126 * API_LIB_DEBUG: Enable debugging in api_lib.c.127 */128 #define API_LIB_DEBUG LWIP_DBG_OFF129 130 /**131 * API_MSG_DEBUG: Enable debugging in api_msg.c.132 */133 #define API_MSG_DEBUG LWIP_DBG_OFF134 135 /**136 * SOCKETS_DEBUG: Enable debugging in sockets.c.137 */138 #define SOCKETS_DEBUG LWIP_DBG_OFF139 140 /**141 * ICMP_DEBUG: Enable debugging in icmp.c.142 */143 #define ICMP_DEBUG LWIP_DBG_OFF144 145 /**146 * IGMP_DEBUG: Enable debugging in igmp.c.147 */148 #define IGMP_DEBUG LWIP_DBG_OFF149 150 /**151 * INET_DEBUG: Enable debugging in inet.c.152 */153 #define INET_DEBUG LWIP_DBG_OFF154 155 /**156 * IP_DEBUG: Enable debugging for IP.157 */158 #define IP_DEBUG LWIP_DBG_OFF159 160 /**161 * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass.162 */163 #define IP_REASS_DEBUG LWIP_DBG_OFF164 /**165 * RAW_DEBUG: Enable debugging in raw.c.166 */167 #define RAW_DEBUG LWIP_DBG_OFF168 169 /**170 * MEM_DEBUG: Enable debugging in mem.c.171 */172 #define MEM_DEBUG LWIP_DBG_OFF173 174 /**175 * MEMP_DEBUG: Enable debugging in memp.c.176 */177 #define MEMP_DEBUG LWIP_DBG_OFF178 179 /**180 * SYS_DEBUG: Enable debugging in sys.c.181 */182 #define SYS_DEBUG LWIP_DBG_OFF183 184 /**185 * TCP_DEBUG: Enable debugging for TCP.186 */187 #define TCP_DEBUG LWIP_DBG_OFF188 189 /**190 * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug.191 */192 #define TCP_INPUT_DEBUG LWIP_DBG_OFF193 /**194 * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit.195 */196 #define TCP_FR_DEBUG LWIP_DBG_OFF197 198 /**199 * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit200 * timeout.201 */202 #define TCP_RTO_DEBUG LWIP_DBG_OFF203 204 /**205 * TCP_CWND_DEBUG: Enable debugging for TCP congestion window.206 */207 #define TCP_CWND_DEBUG LWIP_DBG_OFF208 209 /**210 * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating.211 */212 #define TCP_WND_DEBUG LWIP_DBG_OFF213 214 /**215 * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions.216 */217 #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF218 /**219 * TCP_RST_DEBUG: Enable debugging for TCP with the RST message.220 */221 #define TCP_RST_DEBUG LWIP_DBG_OFF222 223 /**224 * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths.225 */226 #define TCP_QLEN_DEBUG LWIP_DBG_OFF227 228 /**229 * UDP_DEBUG: Enable debugging in UDP.230 */231 #define UDP_DEBUG LWIP_DBG_OFF232 233 /**234 * TCPIP_DEBUG: Enable debugging in tcpip.c.235 */236 #define TCPIP_DEBUG LWIP_DBG_OFF237 238 /**239 * PPP_DEBUG: Enable debugging for PPP.240 */241 #define PPP_DEBUG LWIP_DBG_OFF242 243 /**244 * SLIP_DEBUG: Enable debugging in slipif.c.245 */246 #define SLIP_DEBUG LWIP_DBG_OFF247 248 /**249 * DHCP_DEBUG: Enable debugging in dhcp.c.250 */251 #define DHCP_DEBUG LWIP_DBG_OFF252 253 /**254 * AUTOIP_DEBUG: Enable debugging in autoip.c.255 */256 #define AUTOIP_DEBUG LWIP_DBG_OFF257 258 /**259 * SNMP_MSG_DEBUG: Enable debugging for SNMP messages.260 */261 #define SNMP_MSG_DEBUG LWIP_DBG_OFF262 263 /**264 * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs.265 */266 #define SNMP_MIB_DEBUG LWIP_DBG_OFF267 268 /**269 * DNS_DEBUG: Enable debugging for DNS.270 */271 #define DNS_DEBUG LWIP_DBG_OFF272 #endif /* __LWIPOPTS_H__ */
5.修改\LWIP\netif目录下的ethernetif.c文件,按中文提示修改:
1 /** 2 * @file 3 * Ethernet Interface Skeleton 4 * 5 */ 6 7 /* 8 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without modification, 12 * are permitted provided that the following conditions are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright notice, 15 * this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright notice, 17 * this list of conditions and the following disclaimer in the documentation 18 * and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 25 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 27 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 31 * OF SUCH DAMAGE. 32 * 33 * This file is part of the lwIP TCP/IP stack. 34 * 35 * Author: Adam Dunkels36 * 37 */ 38 39 /* 40 * This file is a skeleton for developing Ethernet network interface 41 * drivers for lwIP. Add code to the low_level functions and do a 42 * search-and-replace for the word "ethernetif" to replace it with 43 * something that better describes your network interface. 44 */ 45 46 #include "lwip/opt.h" 47 48 /*#if 0*/ /* don't build, this is only a skeleton, see previous comment */ 49 #if 1 //允许编译该文件 50 51 #include "lwip/def.h" 52 #include "lwip/mem.h" 53 #include "lwip/pbuf.h" 54 #include "lwip/stats.h" 55 #include "lwip/snmp.h" 56 #include "lwip/ethip6.h" 57 #include "lwip/etharp.h" 58 #include "netif/ppp/pppoe.h" 59 60 /* Define those to better describe your network interface. */ 61 #include "enc28j60.h" //包含enc28j60驱动 62 #define IFNAME0 'e' 63 #define IFNAME1 'n' 64 //定义接收发送Buff 65 unsigned char Rx_Data_Buff[1520*2+1]; 66 unsigned char Tx_Data_Buff[1520*2]; 67 68 /** 69 * Helper struct to hold private data used to operate your ethernet interface. 70 * Keeping the ethernet address of the MAC in this struct is not necessary 71 * as it is already kept in the struct netif. 72 * But this is only an example, anyway... 73 */ 74 struct ethernetif { 75 struct eth_addr *ethaddr; 76 /* Add whatever per-interface state that is needed here. */ 77 }; 78 79 /* Forward declarations. */ 80 //去掉静态定义 81 /*static*/ void ethernetif_input(struct netif *netif); 82 83 /** 84 * In this function, the hardware should be initialized. 85 * Called from ethernetif_init(). 86 * 87 * @param netif the already initialized lwip network interface structure 88 * for this ethernetif 89 */ 90 static void 91 low_level_init(struct netif *netif) 92 { 93 struct ethernetif *ethernetif = netif->state; 94 95 /* set MAC hardware address length */ 96 netif->hwaddr_len = ETHARP_HWADDR_LEN; 97 98 /* set MAC hardware address */ 99 //设置硬件MAC地址,只有不与同网络内的其他设备同名就好100 netif->hwaddr[0] = 0x00;101 netif->hwaddr[1] = 'D';102 netif->hwaddr[2] = 'M';103 netif->hwaddr[3] = 'N';104 netif->hwaddr[4] = 'E';105 netif->hwaddr[5] = 'T';106 107 /* maximum transfer unit */108 netif->mtu = 1500;109 110 /* device capabilities */111 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */112 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP|NETIF_FLAG_UP;113 114 #if LWIP_IPV6 && LWIP_IPV6_MLD115 /*116 * For hardware/netifs that implement MAC filtering.117 * All-nodes link-local is handled by default, so we must let the hardware know118 * to allow multicast packets in.119 * Should set mld_mac_filter previously. */120 if (netif->mld_mac_filter != NULL) {121 ip6_addr_t ip6_allnodes_ll;122 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);123 netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);124 }125 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */126 127 /* Do whatever else is needed to initialize interface. */128 enc28j60Init(netif->hwaddr); //初始化enc28j60129 }130 131 /**132 * This function should do the actual transmission of the packet. The packet is133 * contained in the pbuf that is passed to the function. This pbuf134 * might be chained.135 *136 * @param netif the lwip network interface structure for this ethernetif137 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)138 * @return ERR_OK if the packet could be sent139 * an err_t value if the packet couldn't be sent140 *141 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to142 * strange results. You might consider waiting for space in the DMA queue143 * to become available since the stack doesn't retry to send a packet144 * dropped because of memory failure (except for the TCP timers).145 */146 147 static err_t148 low_level_output(struct netif *netif, struct pbuf *p)149 {150 struct ethernetif *ethernetif = netif->state;151 struct pbuf *q;152 int i = 0;153 // initiate transfer(); //屏蔽154 155 #if ETH_PAD_SIZE156 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */157 #endif158 159 for (q = p; q != NULL; q = q->next) {160 /* Send the data from the pbuf to the interface, one pbuf at a161 time. The size of the data in each pbuf is kept in the ->len162 variable. */163 //send data from(q->payload, q->len);164 //将待发送数据包copy到发送Buff165 memcpy(&Tx_Data_Buff[i],q->payload,q->len);166 i = i+q->len;167 }168 169 // signal that packet should be sent();170 enc28j60PacketSend(i,Tx_Data_Buff); //调用底层驱动,发送数据包171 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);172 if (((u8_t*)p->payload)[0] & 1) {173 /* broadcast or multicast packet*/174 MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);175 } else {176 /* unicast packet */177 MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);178 }179 /* increase ifoutdiscards or ifouterrors on error */180 181 #if ETH_PAD_SIZE182 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */183 #endif184 185 LINK_STATS_INC(link.xmit);186 187 return ERR_OK;188 }189 190 /**191 * Should allocate a pbuf and transfer the bytes of the incoming192 * packet from the interface into the pbuf.193 *194 * @param netif the lwip network interface structure for this ethernetif195 * @return a pbuf filled with the received packet (including MAC header)196 * NULL on memory error197 */198 static struct pbuf *199 low_level_input(struct netif *netif)200 {201 struct ethernetif *ethernetif = netif->state;202 struct pbuf *p, *q;203 u16_t len;204 int i = 0;205 /* Obtain the size of the packet and put it into the "len"206 variable. */207 len = enc28j60PacketReceive(1520*2,Rx_Data_Buff); //返回接收数据长度208 209 #if ETH_PAD_SIZE210 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */211 #endif212 213 /* We allocate a pbuf chain of pbufs from the pool. */214 p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);215 216 if (p != NULL) {217 218 #if ETH_PAD_SIZE219 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */220 #endif221 222 /* We iterate over the pbuf chain until we have read the entire223 * packet into the pbuf. */224 for (q = p; q != NULL; q = q->next) {225 /* Read enough bytes to fill this pbuf in the chain. The226 * available data in the pbuf is given by the q->len227 * variable.228 * This does not necessarily have to be a memcpy, you can also preallocate229 * pbufs for a DMA-enabled MAC and after receiving truncate it to the230 * actually received size. In this case, ensure the tot_len member of the231 * pbuf is the sum of the chained pbuf len members.232 */233 // read data into(q->payload, q->len); //屏蔽234 //将接收到的数据复制到pbuf的数据区235 memcpy((u8_t*)q->payload,(u8_t*)&Rx_Data_Buff[i],q->len);236 i = i+q->len;237 }238 // acknowledge that packet has been read();//屏蔽239 //相等时表明到了数据尾240 if(i != p->tot_len)241 {242 LWIP_DEBUGF(NETIF_DEBUG,("ethernetif_input:recv ERROR"));243 return 0;244 }245 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);246 if (((u8_t*)p->payload)[0] & 1) {247 /* broadcast or multicast packet*/248 MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);249 } else {250 /* unicast packet*/251 MIB2_STATS_NETIF_INC(netif, ifinucastpkts);252 }253 #if ETH_PAD_SIZE254 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */255 #endif256 257 LINK_STATS_INC(link.recv);258 } else {259 // drop packet(); 屏蔽260 LINK_STATS_INC(link.memerr);261 LINK_STATS_INC(link.drop);262 MIB2_STATS_NETIF_INC(netif, ifindiscards);263 }264 265 return p;266 }267 268 /**269 * This function should be called when a packet is ready to be read270 * from the interface. It uses the function low_level_input() that271 * should handle the actual reception of bytes from the network272 * interface. Then the type of the received packet is determined and273 * the appropriate input function is called.274 *275 * @param netif the lwip network interface structure for this ethernetif276 */277 //去掉静态定义278 /*static*/ void279 ethernetif_input(struct netif *netif)280 {281 struct ethernetif *ethernetif;282 struct eth_hdr *ethhdr;283 struct pbuf *p;284 285 ethernetif = netif->state;286 287 /* move received packet into a new pbuf */288 p = low_level_input(netif);289 /* if no packet could be read, silently ignore this */290 if (p != NULL) {291 /* pass all packets to ethernet_input, which decides what packets it supports */292 if (netif->input(p, netif) != ERR_OK) {293 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));294 pbuf_free(p);295 p = NULL;296 }297 }298 }299 300 /**301 * Should be called at the beginning of the program to set up the302 * network interface. It calls the function low_level_init() to do the303 * actual setup of the hardware.304 *305 * This function should be passed as a parameter to netif_add().306 *307 * @param netif the lwip network interface structure for this ethernetif308 * @return ERR_OK if the loopif is initialized309 * ERR_MEM if private data couldn't be allocated310 * any other err_t on error311 */312 err_t313 ethernetif_init(struct netif *netif)314 {315 struct ethernetif *ethernetif;316 317 LWIP_ASSERT("netif != NULL", (netif != NULL));318 319 ethernetif = mem_malloc(sizeof(struct ethernetif));320 if (ethernetif == NULL) {321 LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));322 return ERR_MEM;323 }324 325 #if LWIP_NETIF_HOSTNAME326 /* Initialize interface hostname */327 netif->hostname = "lwip";328 #endif /* LWIP_NETIF_HOSTNAME */329 330 /*331 * Initialize the snmp variables and counters inside the struct netif.332 * The last argument should be replaced with your link speed, in units333 * of bits per second.334 */335 MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);336 337 netif->state = ethernetif;338 netif->name[0] = IFNAME0;339 netif->name[1] = IFNAME1;340 /* We directly use etharp_output() here to save a function call.341 * You can instead declare your own function an call etharp_output()342 * from it if you have to do some checks before sending (e.g. if link343 * is available...) */344 netif->output = etharp_output;345 #if LWIP_IPV6346 netif->output_ip6 = ethip6_output;347 #endif /* LWIP_IPV6 */348 netif->linkoutput = low_level_output;349 350 ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);351 352 /* initialize the hardware */353 low_level_init(netif);354 355 return ERR_OK;356 }357 #endif /* 0 */
6.将\LWIP\include\lwip目录下的arch.h文件中的#define LWIP_NO_STDINT_H 改成1,不然会与cc.h文件中的类型定义重复,编译出错
7.将enc28j60驱动程序加入工程中,以下文件为网上借鉴,亲测可用:
1 /****************************************************************************** 2 * vim:sw=8:ts=8:si:et 3 * To use the above modeline in vim you must have "set modeline" in your .vimrc 4 * Author: Guido Socher 5 * Copyright: GPL V2 6 * http://www.gnu.org/licenses/gpl.html 7 * 8 * Based on the enc28j60.c file from the AVRlib library by Pascal Stang. 9 * For AVRlib See http://www.procyonengineering.com/ 10 * Used with explicit permission of Pascal Stang. 11 * 12 * Title: Microchip ENC28J60 Ethernet Interface Driver 13 * Chip type : ATMEGA88 with ENC28J60 14 *******************************************************************************/ 15 16 #include "ENC28J60.H" 17 #include "SPI.H" 18 19 static u8 Enc28j60Bank; 20 static u16 NextPacketPtr; 21 22 /* 23 * º¯ÊýÃû£ºenc28j60ReadOp 24 * ÃèÊö £º¶Á¿ØÖƼĴæÆ÷ 25 * ÊäÈë £º¶ÁÖ¸ÁµØÖ· 26 * Êä³ö £º¼Ä´æÆ÷ÄÚÈÝ 27 */ 28 u8 enc28j60ReadOp(u8 op, u8 address) 29 { 30 u8 dat = 0; 31 32 ENC28J60_CSL(); 33 34 dat = op | (address & ADDR_MASK); 35 ENC_SPI_ReadWrite(dat); 36 dat = ENC_SPI_ReadWrite(0xFF); 37 // do dummy read if needed (for mac and mii, see datasheet page 29) 38 if (address & 0x80) 39 { 40 dat = ENC_SPI_ReadWrite(0xFF); 41 } 42 // release CS 43 ENC28J60_CSH(); 44 return dat; 45 } 46 47 /* 48 * º¯ÊýÃû£ºenc28j60WriteOp 49 * ÃèÊö £ºÏòÒÔÌ«Íø¿ØÖÆÆ÷дÈëÃüÁî 50 * ÊäÈë £ºÎÞ 51 * Êä³ö £ºÎÞ 52 */ 53 void enc28j60WriteOp(u8 op, u8 address, u8 data) 54 { 55 u8 dat = 0; 56 57 ENC28J60_CSL(); 58 // issue write command 59 dat = op | (address & ADDR_MASK); 60 ENC_SPI_ReadWrite(dat); 61 // write data 62 dat = data; 63 ENC_SPI_ReadWrite(dat); 64 ENC28J60_CSH(); 65 } 66 67 /* 68 * º¯ÊýÃû£ºenc28j60ReadBuffer 69 * ÃèÊö £º¶ÁÈ¡bufferµÄÊý¾Ý 70 * ÊäÈë £ºÊý¾Ý³¤¶È£¬´æ·ÅÊý¾ÝµÄÖ¸Õë 71 * Êä³ö £ºÎÞ 72 */ 73 void enc28j60ReadBuffer(u16 len, u8* data) 74 { 75 ENC28J60_CSL(); 76 // issue read command 77 ENC_SPI_ReadWrite(ENC28J60_READ_BUF_MEM); 78 while (len--) 79 { 80 *data++ = (u8) ENC_SPI_ReadWrite(0); 81 } 82 *data = '\0'; 83 ENC28J60_CSH(); 84 } 85 86 /* 87 * º¯ÊýÃû£ºenc28j60WriteBuffer 88 * ÃèÊö £ºÏòbufferдÈëÊý¾Ý 89 * ÊäÈë £ºÊý¾Ý³¤¶È£¬´æ·ÅÊý¾ÝµÄÖ¸Õë 90 * Êä³ö £ºÎÞ 91 */ 92 void enc28j60WriteBuffer(u16 len, u8* data) 93 { 94 ENC28J60_CSL(); 95 // issue write command 96 ENC_SPI_ReadWrite(ENC28J60_WRITE_BUF_MEM); 97 98 while (len--) 99 {100 ENC_SPI_ReadWrite(*data++);101 }102 ENC28J60_CSH();103 }104 105 /*106 * º¯ÊýÃû£ºenc28j60SetBank107 * ÃèÊö £ºÑ¡¶¨½«Òª²Ù×÷µÄbank108 * ÊäÈë £º´øÓÐbankÆÁ±ÎÓòµÄ²ÎÊý109 * Êä³ö £ºÎÞ 110 */111 void enc28j60SetBank(u8 address)112 {113 // set the bank (if needed)114 if ((address & BANK_MASK) != Enc28j60Bank)115 {116 // set the bank117 enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0));118 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5);119 Enc28j60Bank = (address & BANK_MASK);120 }121 }122 123 /*124 * º¯ÊýÃû£ºenc28j60Read125 * ÃèÊö £º¶ÁÈ¡¿ØÖƼĴæÆ÷µÄÄÚÈÝ126 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ·127 * Êä³ö £ºÎÞ 128 */129 u8 enc28j60Read(u8 address)130 {131 // set the bank132 enc28j60SetBank(address);133 // do the read134 return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address);135 }136 137 138 /*139 * º¯ÊýÃû£ºenc28j60Write140 * ÃèÊö £ºÐ´ÈëÊý¾Ýµ½¿ØÖƼĴæÆ÷141 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ·£¬ÃüÁî142 * Êä³ö £ºÎÞ 143 */144 void enc28j60Write(u8 address, u8 data)145 {146 // set the bank147 enc28j60SetBank(address);148 // do the write149 enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data);150 }151 152 /*153 * º¯ÊýÃû£ºenc28j60PhyWrite154 * ÃèÊö £ºÏòphyдÈë¿ØÖƲÎÊý155 * ÊäÈë £º¼Ä´æÆ÷µÄµØÖ·£¬ÃüÁî156 * Êä³ö £ºÎÞ 157 */158 void enc28j60PhyWrite(u8 address, u16 data)159 {160 // set the PHY register address161 enc28j60Write(MIREGADR, address);162 // write the PHY data163 enc28j60Write(MIWRL, data);164 enc28j60Write(MIWRH, data >> 8);165 // wait until the PHY write completes166 while (enc28j60Read(MISTAT) & MISTAT_BUSY)167 {168 //Del_10us(1);169 //_nop_();170 }171 }172 173 /*174 * º¯ÊýÃû£ºenc28j60clkout175 * ÃèÊö £ºÉèÖÃÊä³öʱÖÓ176 * ÊäÈë £ºÊ±ÖÓ²ÎÊý177 * Êä³ö £ºÎÞ 178 */179 void enc28j60clkout(u8 clk)180 {181 //setup clkout: 2 is 12.5MHz:182 enc28j60Write(ECOCON, clk & 0x7);183 }184 185 /*186 * º¯ÊýÃû£ºenc28j60Init187 * ÃèÊö £º³õʼ»¯ÒÔÌ«Íø¿ØÖÆÆ÷188 * ÊäÈë £ºÎÞ189 * Êä³ö £ºÎÞ 190 */191 void enc28j60Init(u8 * macaddr)192 {193 194 ENC28J60_RSTH();195 ENC28J60_CSH();196 enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);197 // Del_1ms(250);198 // check CLKRDY bit to see if reset is complete199 // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait.200 //while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY));201 // do bank 0 stuff202 // initialize receive buffer203 // 16-bit transfers, must write low byte first204 // set receive buffer start address205 NextPacketPtr = RXSTART_INIT;206 // Rx start207 enc28j60Write(ERXSTL, RXSTART_INIT & 0xFF);208 enc28j60Write(ERXSTH, RXSTART_INIT >> 8);209 // set receive pointer address210 enc28j60Write(ERXRDPTL, RXSTART_INIT & 0xFF);211 enc28j60Write(ERXRDPTH, RXSTART_INIT >> 8);212 // RX end213 enc28j60Write(ERXNDL, RXSTOP_INIT & 0xFF);214 enc28j60Write(ERXNDH, RXSTOP_INIT >> 8);215 // TX start216 enc28j60Write(ETXSTL, TXSTART_INIT & 0xFF);217 enc28j60Write(ETXSTH, TXSTART_INIT >> 8);218 // TX end219 enc28j60Write(ETXNDL, TXSTOP_INIT & 0xFF);220 enc28j60Write(ETXNDH, TXSTOP_INIT >> 8);221 // do bank 1 stuff, packet filter:222 // For broadcast packets we allow only ARP packtets223 // All other packets should be unicast only for our mac (MAADR)224 //225 // The pattern to match on is therefore226 // Type ETH.DST227 // ARP BROADCAST228 // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9229 // in binary these poitions are:11 0000 0011 1111230 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30231 enc28j60Write(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN);232 enc28j60Write(EPMM0, 0x3f);233 enc28j60Write(EPMM1, 0x30);234 enc28j60Write(EPMCSL, 0xf9);235 enc28j60Write(EPMCSH, 0xf7);236 //237 //238 // do bank 2 stuff239 // enable MAC receive240 enc28j60Write(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS);241 // bring MAC out of reset242 enc28j60Write(MACON2, 0x00);243 // enable automatic padding to 60bytes and CRC operations244 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX );//MACON3_HFRMLEN245 // set inter-frame gap (non-back-to-back)246 enc28j60Write(MAIPGL, 0x12);247 enc28j60Write(MAIPGH, 0x0C);248 // set inter-frame gap (back-to-back)249 enc28j60Write(MABBIPG, 0x12);250 // Set the maximum packet size which the controller will accept251 // Do not send packets longer than MAX_FRAMELEN:252 enc28j60Write(MAMXFLL, MAX_FRAMELEN & 0xFF); 253 enc28j60Write(MAMXFLH, MAX_FRAMELEN >> 8);254 // do bank 3 stuff255 // write MAC address256 // NOTE: MAC address in ENC28J60 is byte-backward257 enc28j60Write(MAADR5, macaddr[0]); 258 enc28j60Write(MAADR4, macaddr[1]);259 enc28j60Write(MAADR3, macaddr[2]);260 enc28j60Write(MAADR2, macaddr[3]);261 enc28j60Write(MAADR1, macaddr[4]);262 enc28j60Write(MAADR0, macaddr[5]);263 264 265 266 enc28j60PhyWrite(PHCON1, PHCON1_PDPXMD);267 268 269 // no loopback of transmitted frames270 enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS);271 // switch to bank 0272 enc28j60SetBank(ECON1);273 // enable interrutps274 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE);275 // enable packet reception276 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);277 }278 279 // read the revision of the chip:280 281 u8 enc28j60getrev(void)282 {283 return(enc28j60Read(EREVID));284 }285 286 /*287 * º¯ÊýÃû£ºenc28j60PacketSend288 * ÃèÊö £º·¢ËÍÒ»¸öÊý¾Ý°ü289 * ÊäÈë £ºÊý¾Ý°ü³¤¶È£¬Ö¸ÏòÊý¾Ý°üµÄÖ¸Õë290 * Êä³ö £ºÎÞ 291 */292 void enc28j60PacketSend(u16 len, u8* packet)293 {294 // Set the write pointer to start of transmit buffer area295 enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF);296 enc28j60Write(EWRPTH, TXSTART_INIT >> 8);297 298 // Set the TXND pointer to correspond to the packet size given299 enc28j60Write(ETXNDL, (TXSTART_INIT + len) & 0xFF);300 enc28j60Write(ETXNDH, (TXSTART_INIT + len) >> 8);301 302 // write per-packet control byte (0x00 means use macon3 settings)303 enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00);304 305 // copy the packet into the transmit buffer306 enc28j60WriteBuffer(len, packet);307 308 // send the contents of the transmit buffer onto the network309 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS);310 311 // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12.312 if ((enc28j60Read(EIR) & EIR_TXERIF))313 {314 enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS);315 }316 }317 318 /*-----------------------------------------------------------------319 Gets a packet from the network receive buffer, if one is available.320 The packet will by headed by an ethernet header.321 maxlen The maximum acceptable length of a retrieved packet.322 packet Pointer where packet data should be stored.323 Returns: Packet length in bytes if a packet was retrieved, zero otherwise.324 -------------------------------------------------------------------*/325 u16 enc28j60PacketReceive(u16 maxlen, u8* packet)326 {327 u16 rxstat;328 u16 len;329 330 // check if a packet has been received and buffered331 //if( !(enc28j60Read(EIR) & EIR_PKTIF) ){332 // The above does not work. See Rev. B4 Silicon Errata point 6.333 if (enc28j60Read(EPKTCNT) == 0)334 {335 return(0);336 }337 338 // Set the read pointer to the start of the received packet339 enc28j60Write(ERDPTL, (NextPacketPtr));340 enc28j60Write(ERDPTH, (NextPacketPtr) >> 8);341 342 // read the next packet pointer343 NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);344 NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;345 346 // read the packet length (see datasheet page 43)347 len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);348 len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;349 350 len -= 4; //remove the CRC count351 // read the receive status (see datasheet page 43)352 rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0);353 rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0) << 8;354 // limit retrieve length355 if (len > maxlen - 1)356 {357 len = maxlen - 1;358 }359 360 // check CRC and symbol errors (see datasheet page 44, table 7-3):361 // The ERXFCON.CRCEN is set by default. Normally we should not362 // need to check this.363 if ((rxstat & 0x80) == 0)364 {365 // invalid366 len = 0;367 }368 else369 {370 // copy the packet from the receive buffer371 enc28j60ReadBuffer(len, packet);372 }373 // Move the RX read pointer to the start of the next received packet374 // This frees the memory we just read out375 enc28j60Write(ERXRDPTL, (NextPacketPtr));376 enc28j60Write(ERXRDPTH, (NextPacketPtr) >> 8);377 378 // decrement the packet counter indicate we are done with this packet379 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC);380 return(len);381 }
1 #include2 3 #ifndef __ENC28J60_H 4 #define __ENC28J60_H 5 6 // ENC28J60 Control Registers 7 // Control register definitions are a combination of address, 8 // bank number, and Ethernet/MAC/PHY indicator bits. 9 // - Register address (bits 0-4) 10 // - Bank number (bits 5-6) 11 // - MAC/PHY indicator (bit 7) 12 #define ADDR_MASK 0x1F 13 #define BANK_MASK 0x60 14 #define SPRD_MASK 0x80 15 // All-bank registers 16 #define EIE 0x1B 17 #define EIR 0x1C 18 #define ESTAT 0x1D 19 #define ECON2 0x1E 20 #define ECON1 0x1F 21 // Bank 0 registers 22 #define ERDPTL (0x00|0x00) 23 #define ERDPTH (0x01|0x00) 24 #define EWRPTL (0x02|0x00) 25 #define EWRPTH (0x03|0x00) 26 #define ETXSTL (0x04|0x00) 27 #define ETXSTH (0x05|0x00) 28 #define ETXNDL (0x06|0x00) 29 #define ETXNDH (0x07|0x00) 30 #define ERXSTL (0x08|0x00) 31 #define ERXSTH (0x09|0x00) 32 #define ERXNDL (0x0A|0x00) 33 #define ERXNDH (0x0B|0x00) 34 #define ERXRDPTL (0x0C|0x00) 35 #define ERXRDPTH (0x0D|0x00) 36 #define ERXWRPTL (0x0E|0x00) 37 #define ERXWRPTH (0x0F|0x00) 38 #define EDMASTL (0x10|0x00) 39 #define EDMASTH (0x11|0x00) 40 #define EDMANDL (0x12|0x00) 41 #define EDMANDH (0x13|0x00) 42 #define EDMADSTL (0x14|0x00) 43 #define EDMADSTH (0x15|0x00) 44 #define EDMACSL (0x16|0x00) 45 #define EDMACSH (0x17|0x00) 46 // Bank 1 registers 47 #define EHT0 (0x00|0x20) 48 #define EHT1 (0x01|0x20) 49 #define EHT2 (0x02|0x20) 50 #define EHT3 (0x03|0x20) 51 #define EHT4 (0x04|0x20) 52 #define EHT5 (0x05|0x20) 53 #define EHT6 (0x06|0x20) 54 #define EHT7 (0x07|0x20) 55 #define EPMM0 (0x08|0x20) 56 #define EPMM1 (0x09|0x20) 57 #define EPMM2 (0x0A|0x20) 58 #define EPMM3 (0x0B|0x20) 59 #define EPMM4 (0x0C|0x20) 60 #define EPMM5 (0x0D|0x20) 61 #define EPMM6 (0x0E|0x20) 62 #define EPMM7 (0x0F|0x20) 63 #define EPMCSL (0x10|0x20) 64 #define EPMCSH (0x11|0x20) 65 #define EPMOL (0x14|0x20) 66 #define EPMOH (0x15|0x20) 67 #define EWOLIE (0x16|0x20) 68 #define EWOLIR (0x17|0x20) 69 #define ERXFCON (0x18|0x20) 70 #define EPKTCNT (0x19|0x20) 71 // Bank 2 registers 72 #define MACON1 (0x00|0x40|0x80) 73 #define MACON2 (0x01|0x40|0x80) 74 #define MACON3 (0x02|0x40|0x80) 75 #define MACON4 (0x03|0x40|0x80) 76 #define MABBIPG (0x04|0x40|0x80) 77 #define MAIPGL (0x06|0x40|0x80) 78 #define MAIPGH (0x07|0x40|0x80) 79 #define MACLCON1 (0x08|0x40|0x80) 80 #define MACLCON2 (0x09|0x40|0x80) 81 #define MAMXFLL (0x0A|0x40|0x80) 82 #define MAMXFLH (0x0B|0x40|0x80) 83 #define MAPHSUP (0x0D|0x40|0x80) 84 #define MICON (0x11|0x40|0x80) 85 #define MICMD (0x12|0x40|0x80) 86 #define MIREGADR (0x14|0x40|0x80) 87 #define MIWRL (0x16|0x40|0x80) 88 #define MIWRH (0x17|0x40|0x80) 89 #define MIRDL (0x18|0x40|0x80) 90 #define MIRDH (0x19|0x40|0x80) 91 // Bank 3 registers 92 #define MAADR1 (0x00|0x60|0x80) 93 #define MAADR0 (0x01|0x60|0x80) 94 #define MAADR3 (0x02|0x60|0x80) 95 #define MAADR2 (0x03|0x60|0x80) 96 #define MAADR5 (0x04|0x60|0x80) 97 #define MAADR4 (0x05|0x60|0x80) 98 #define EBSTSD (0x06|0x60) 99 #define EBSTCON (0x07|0x60)100 #define EBSTCSL (0x08|0x60)101 #define EBSTCSH (0x09|0x60)102 #define MISTAT (0x0A|0x60|0x80)103 #define EREVID (0x12|0x60)104 #define ECOCON (0x15|0x60)105 #define EFLOCON (0x17|0x60)106 #define EPAUSL (0x18|0x60)107 #define EPAUSH (0x19|0x60)108 // PHY registers109 #define PHCON1 0x00110 #define PHSTAT1 0x01111 #define PHHID1 0x02112 #define PHHID2 0x03113 #define PHCON2 0x10114 #define PHSTAT2 0x11115 #define PHIE 0x12116 #define PHIR 0x13117 #define PHLCON 0x14118 119 // ENC28J60 ERXFCON Register Bit Definitions120 #define ERXFCON_UCEN 0x80121 #define ERXFCON_ANDOR 0x40122 #define ERXFCON_CRCEN 0x20123 #define ERXFCON_PMEN 0x10124 #define ERXFCON_MPEN 0x08125 #define ERXFCON_HTEN 0x04126 #define ERXFCON_MCEN 0x02127 #define ERXFCON_BCEN 0x01128 // ENC28J60 EIE Register Bit Definitions129 #define EIE_INTIE 0x80130 #define EIE_PKTIE 0x40131 #define EIE_DMAIE 0x20132 #define EIE_LINKIE 0x10133 #define EIE_TXIE 0x08134 #define EIE_WOLIE 0x04135 #define EIE_TXERIE 0x02136 #define EIE_RXERIE 0x01137 // ENC28J60 EIR Register Bit Definitions138 #define EIR_PKTIF 0x40139 #define EIR_DMAIF 0x20140 #define EIR_LINKIF 0x10141 #define EIR_TXIF 0x08142 #define EIR_WOLIF 0x04143 #define EIR_TXERIF 0x02144 #define EIR_RXERIF 0x01145 // ENC28J60 ESTAT Register Bit Definitions146 #define ESTAT_INT 0x80147 #define ESTAT_LATECOL 0x10148 #define ESTAT_RXBUSY 0x04149 #define ESTAT_TXABRT 0x02150 #define ESTAT_CLKRDY 0x01151 // ENC28J60 ECON2 Register Bit Definitions152 #define ECON2_AUTOINC 0x80153 #define ECON2_PKTDEC 0x40154 #define ECON2_PWRSV 0x20155 #define ECON2_VRPS 0x08156 // ENC28J60 ECON1 Register Bit Definitions157 #define ECON1_TXRST 0x80158 #define ECON1_RXRST 0x40159 #define ECON1_DMAST 0x20160 #define ECON1_CSUMEN 0x10161 #define ECON1_TXRTS 0x08162 #define ECON1_RXEN 0x04163 #define ECON1_BSEL1 0x02164 #define ECON1_BSEL0 0x01165 // ENC28J60 MACON1 Register Bit Definitions166 #define MACON1_LOOPBK 0x10167 #define MACON1_TXPAUS 0x08168 #define MACON1_RXPAUS 0x04169 #define MACON1_PASSALL 0x02170 #define MACON1_MARXEN 0x01171 // ENC28J60 MACON2 Register Bit Definitions172 #define MACON2_MARST 0x80173 #define MACON2_RNDRST 0x40174 #define MACON2_MARXRST 0x08175 #define MACON2_RFUNRST 0x04176 #define MACON2_MATXRST 0x02177 #define MACON2_TFUNRST 0x01178 // ENC28J60 MACON3 Register Bit Definitions179 #define MACON3_PADCFG2 0x80180 #define MACON3_PADCFG1 0x40181 #define MACON3_PADCFG0 0x20182 #define MACON3_TXCRCEN 0x10183 #define MACON3_PHDRLEN 0x08184 #define MACON3_HFRMLEN 0x04185 #define MACON3_FRMLNEN 0x02186 #define MACON3_FULDPX 0x01187 // ENC28J60 MICMD Register Bit Definitions188 #define MICMD_MIISCAN 0x02189 #define MICMD_MIIRD 0x01190 // ENC28J60 MISTAT Register Bit Definitions191 #define MISTAT_NVALID 0x04192 #define MISTAT_SCAN 0x02193 #define MISTAT_BUSY 0x01194 // ENC28J60 PHY PHCON1 Register Bit Definitions195 #define PHCON1_PRST 0x8000196 #define PHCON1_PLOOPBK 0x4000197 #define PHCON1_PPWRSV 0x0800198 #define PHCON1_PDPXMD 0x0100199 // ENC28J60 PHY PHSTAT1 Register Bit Definitions200 #define PHSTAT1_PFDPX 0x1000201 #define PHSTAT1_PHDPX 0x0800202 #define PHSTAT1_LLSTAT 0x0004203 #define PHSTAT1_JBSTAT 0x0002204 // ENC28J60 PHY PHCON2 Register Bit Definitions205 #define PHCON2_FRCLINK 0x4000206 #define PHCON2_TXDIS 0x2000207 #define PHCON2_JABBER 0x0400208 #define PHCON2_HDLDIS 0x0100209 210 // ENC28J60 Packet Control Byte Bit Definitions211 #define PKTCTRL_PHUGEEN 0x08212 #define PKTCTRL_PPADEN 0x04213 #define PKTCTRL_PCRCEN 0x02214 #define PKTCTRL_POVERRIDE 0x01215 216 // SPI operation codes217 #define ENC28J60_READ_CTRL_REG 0x00218 #define ENC28J60_READ_BUF_MEM 0x3A219 #define ENC28J60_WRITE_CTRL_REG 0x40220 #define ENC28J60_WRITE_BUF_MEM 0x7A221 #define ENC28J60_BIT_FIELD_SET 0x80222 #define ENC28J60_BIT_FIELD_CLR 0xA0223 #define ENC28J60_SOFT_RESET 0xFF224 225 // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata226 // buffer boundaries applied to internal 8K ram227 // the entire available packet buffer space is allocated228 //229 // start with recbuf at 0/230 #define RXSTART_INIT 0x0231 // receive buffer end232 #define RXSTOP_INIT (0x1FFF-0x0600-1)233 // start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (~1500 bytes)234 #define TXSTART_INIT (0x1FFF-0x0600)235 // stp TX buffer at end of mem236 #define TXSTOP_INIT 0x1FFF237 //238 // max frame length which the conroller will accept:239 #define MAX_FRAMELEN 1500 // (note: maximum ethernet frame length would be 1518)240 //#define MAX_FRAMELEN 600241 242 243 244 245 246 247 248 249 u8 enc28j60ReadOp(u8 op, u8 address);250 void enc28j60WriteOp(u8 op, u8 address, u8 data);251 void enc28j60ReadBuffer(u16 len, u8* data);252 void enc28j60WriteBuffer(u16 len, u8* data);253 void enc28j60SetBank(u8 address);254 u8 enc28j60Read(u8 address);255 void enc28j60Write(u8 address, u8 data);256 void enc28j60PhyWrite(u8 address, u16 data);257 void enc28j60clkout(u8 clk);258 void enc28j60Init(u8* macaddr);259 u8 enc28j60getrev(void);260 void enc28j60PacketSend(u16 len, u8* packet);261 u16 enc28j60PacketReceive(u16 maxlen, u8* packet);262 263 264 #endif
8.enc28j60使用SPI接口,需根据实际端口修改,以下仅供参考:
1 #include "SPI.h" 2 3 4 void SPI2_Init(void) 5 { 6 SPI_InitTypeDef SPI_InitStructure; 7 GPIO_InitTypeDef GPIO_InitStructure; 8 9 /* Enable SPI2 and GPIOB clocks */10 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);11 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);12 13 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;14 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;15 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 16 GPIO_Init(GPIOB, &GPIO_InitStructure); 17 18 /* Configure SPI2 pins: NSS, SCK, MISO and MOSI */19 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;20 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;21 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 22 GPIO_Init(GPIOB, &GPIO_InitStructure);23 24 /* PC6:ENC28J60_INT */ // 25 26 /* PC7:ENC28J60_RST*/ // ¸27 28 /* SPI2 configuration */ 29 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;30 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;31 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;32 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;33 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;34 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;35 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;36 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;37 SPI_InitStructure.SPI_CRCPolynomial = 7;38 SPI_Init(SPI2, &SPI_InitStructure);39 40 /* Enable SPI2 */41 SPI_Cmd(SPI2, ENABLE);42 }43 44 45 uint8_t SPI2_ReadWrite(uint8_t dat)46 {47 /* Loop while DR register in not emplty */48 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);49 50 /* Send byte through the SPI2 peripheral */51 SPI_I2S_SendData(SPI2, dat);52 53 /* Wait to receive a byte */54 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);55 56 /* Return the byte read from the SPI bus */57 return SPI_I2S_ReceiveData(SPI2);58 }
1 #ifndef __SPI_H 2 #define __SPI_H 3 4 #include5 6 #define ENC28J60_CSL() (GPIOB->ODR &= ~(1<<12)) 7 #define ENC28J60_CSH() (GPIOB->ODR |= 1<<12) 8 9 10 #define ENC_SPI_ReadWrite SPI2_ReadWrite11 #define ENC_SPI_Init SPI2_Init12 13 void SPI2_Init(void);14 uint8_t SPI2_ReadWrite(uint8_t writedat);15 16 17 #endif
— —随笔,备忘!