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文件,内容如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 1500 100 101 /* ---------- TCP options ---------- */ 102 #define LWIP_TCP 1 103 #define TCP_TTL 255 104 105 /* Controls if TCP should queue segments that arrive out of 106 order. Define to 0 if your device is low on memory. */ 107 #define TCP_QUEUE_OOSEQ 0 108 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_MSS 118 119 /* TCP receive window. */ 120 #define TCP_WND (2 * TCP_MSS) 121 122 /* ---------- ICMP options ---------- */ 123 #define LWIP_ICMP 1 124 125 /* ---------- DHCP options ---------- */ 126 /* Define LWIP_DHCP to 1 if you want DHCP configuration of 127 interfaces. DHCP is not implemented in lwIP 0.5.1, however, so 128 turning this on does currently not work. */ 129 #define LWIP_DHCP 0 130 131 /* ---------- UDP options ---------- */ 132 #define LWIP_UDP 1 133 #define UDP_TTL 255 134 135 /* ---------- Statistics options ---------- */ 136 #define LWIP_STATS 0 137 #define LWIP_PROVIDE_ERRNO 1 138 139 // LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c) 140 #define LWIP_NETCONN 0 141 142 // LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) 143 #define LWIP_SOCKET 0 144 145 // 这个必须要定义, 否则在执行lwip_init函数时会在串口中提示: 146 // Assertion "Struct packing not implemented correctly. Check your lwIP port." failed at line 345 in Library\lwip\core\init.c 147 #define PACK_STRUCT_BEGIN __packed 148 /*******************************************************************************************************************/ 149 #define LWIP_DEBUG 1 150 #define LWIP_DBG_TYPES_ON LWIP_DBG_OFF 151 152 /** 153 * ETHARP_DEBUG: Enable debugging in etharp.c. 154 */ 155 #define ETHARP_DEBUG LWIP_DBG_OFF 156 157 /** 158 * NETIF_DEBUG: Enable debugging in netif.c. 159 */ 160 #define NETIF_DEBUG LWIP_DBG_OFF 161 162 /** 163 * PBUF_DEBUG: Enable debugging in pbuf.c. 164 */ 165 #define PBUF_DEBUG LWIP_DBG_OFF 166 167 /** 168 * API_LIB_DEBUG: Enable debugging in api_lib.c. 169 */ 170 #define API_LIB_DEBUG LWIP_DBG_OFF 171 172 /** 173 * API_MSG_DEBUG: Enable debugging in api_msg.c. 174 */ 175 #define API_MSG_DEBUG LWIP_DBG_OFF 176 177 /** 178 * SOCKETS_DEBUG: Enable debugging in sockets.c. 179 */ 180 #define SOCKETS_DEBUG LWIP_DBG_OFF 181 182 /** 183 * ICMP_DEBUG: Enable debugging in icmp.c. 184 */ 185 #define ICMP_DEBUG LWIP_DBG_OFF 186 187 /** 188 * IGMP_DEBUG: Enable debugging in igmp.c. 189 */ 190 #define IGMP_DEBUG LWIP_DBG_OFF 191 192 /** 193 * INET_DEBUG: Enable debugging in inet.c. 194 */ 195 #define INET_DEBUG LWIP_DBG_OFF 196 197 /** 198 * IP_DEBUG: Enable debugging for IP. 199 */ 200 #define IP_DEBUG LWIP_DBG_OFF 201 202 /** 203 * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. 204 */ 205 #define IP_REASS_DEBUG LWIP_DBG_OFF 206 /** 207 * RAW_DEBUG: Enable debugging in raw.c. 208 */ 209 #define RAW_DEBUG LWIP_DBG_OFF 210 211 /** 212 * MEM_DEBUG: Enable debugging in mem.c. 213 */ 214 #define MEM_DEBUG LWIP_DBG_OFF 215 216 /** 217 * MEMP_DEBUG: Enable debugging in memp.c. 218 */ 219 #define MEMP_DEBUG LWIP_DBG_OFF 220 221 /** 222 * SYS_DEBUG: Enable debugging in sys.c. 223 */ 224 #define SYS_DEBUG LWIP_DBG_OFF 225 226 /** 227 * TCP_DEBUG: Enable debugging for TCP. 228 */ 229 #define TCP_DEBUG LWIP_DBG_OFF 230 231 /** 232 * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. 233 */ 234 #define TCP_INPUT_DEBUG LWIP_DBG_OFF 235 /** 236 * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. 237 */ 238 #define TCP_FR_DEBUG LWIP_DBG_OFF 239 240 /** 241 * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit 242 * timeout. 243 */ 244 #define TCP_RTO_DEBUG LWIP_DBG_OFF 245 246 /** 247 * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. 248 */ 249 #define TCP_CWND_DEBUG LWIP_DBG_OFF 250 251 /** 252 * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. 253 */ 254 #define TCP_WND_DEBUG LWIP_DBG_OFF 255 256 /** 257 * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. 258 */ 259 #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 260 /** 261 * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. 262 */ 263 #define TCP_RST_DEBUG LWIP_DBG_OFF 264 265 /** 266 * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. 267 */ 268 #define TCP_QLEN_DEBUG LWIP_DBG_OFF 269 270 /** 271 * UDP_DEBUG: Enable debugging in UDP. 272 */ 273 #define UDP_DEBUG LWIP_DBG_OFF 274 275 /** 276 * TCPIP_DEBUG: Enable debugging in tcpip.c. 277 */ 278 #define TCPIP_DEBUG LWIP_DBG_OFF 279 280 /** 281 * PPP_DEBUG: Enable debugging for PPP. 282 */ 283 #define PPP_DEBUG LWIP_DBG_OFF 284 285 /** 286 * SLIP_DEBUG: Enable debugging in slipif.c. 287 */ 288 #define SLIP_DEBUG LWIP_DBG_OFF 289 290 /** 291 * DHCP_DEBUG: Enable debugging in dhcp.c. 292 */ 293 #define DHCP_DEBUG LWIP_DBG_OFF 294 295 /** 296 * AUTOIP_DEBUG: Enable debugging in autoip.c. 297 */ 298 #define AUTOIP_DEBUG LWIP_DBG_OFF 299 300 /** 301 * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. 302 */ 303 #define SNMP_MSG_DEBUG LWIP_DBG_OFF 304 305 /** 306 * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. 307 */ 308 #define SNMP_MIB_DEBUG LWIP_DBG_OFF 309 310 /** 311 * DNS_DEBUG: Enable debugging for DNS. 312 */ 313 #define DNS_DEBUG LWIP_DBG_OFF 314 #endif /* __LWIPOPTS_H__ */
4.在LWIP\include根目录下新建一个lwipopts.h文件,内容如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 0 102 103 // 这个必须要定义, 否则在执行lwip_init函数时会在串口中提示: 104 // Assertion "Struct packing not implemented correctly. Check your lwIP port." failed at line 345 in Library\lwip\core\init.c 105 #define PACK_STRUCT_BEGIN __packed 106 /*******************************************************************************************************************/ 107 #define LWIP_DEBUG 1 108 #define LWIP_DBG_TYPES_ON LWIP_DBG_OFF 109 110 /** 111 * ETHARP_DEBUG: Enable debugging in etharp.c. 112 */ 113 #define ETHARP_DEBUG LWIP_DBG_OFF 114 115 /** 116 * NETIF_DEBUG: Enable debugging in netif.c. 117 */ 118 #define NETIF_DEBUG LWIP_DBG_OFF 119 120 /** 121 * PBUF_DEBUG: Enable debugging in pbuf.c. 122 */ 123 #define PBUF_DEBUG LWIP_DBG_OFF 124 125 /** 126 * API_LIB_DEBUG: Enable debugging in api_lib.c. 127 */ 128 #define API_LIB_DEBUG LWIP_DBG_OFF 129 130 /** 131 * API_MSG_DEBUG: Enable debugging in api_msg.c. 132 */ 133 #define API_MSG_DEBUG LWIP_DBG_OFF 134 135 /** 136 * SOCKETS_DEBUG: Enable debugging in sockets.c. 137 */ 138 #define SOCKETS_DEBUG LWIP_DBG_OFF 139 140 /** 141 * ICMP_DEBUG: Enable debugging in icmp.c. 142 */ 143 #define ICMP_DEBUG LWIP_DBG_OFF 144 145 /** 146 * IGMP_DEBUG: Enable debugging in igmp.c. 147 */ 148 #define IGMP_DEBUG LWIP_DBG_OFF 149 150 /** 151 * INET_DEBUG: Enable debugging in inet.c. 152 */ 153 #define INET_DEBUG LWIP_DBG_OFF 154 155 /** 156 * IP_DEBUG: Enable debugging for IP. 157 */ 158 #define IP_DEBUG LWIP_DBG_OFF 159 160 /** 161 * IP_REASS_DEBUG: Enable debugging in ip_frag.c for both frag & reass. 162 */ 163 #define IP_REASS_DEBUG LWIP_DBG_OFF 164 /** 165 * RAW_DEBUG: Enable debugging in raw.c. 166 */ 167 #define RAW_DEBUG LWIP_DBG_OFF 168 169 /** 170 * MEM_DEBUG: Enable debugging in mem.c. 171 */ 172 #define MEM_DEBUG LWIP_DBG_OFF 173 174 /** 175 * MEMP_DEBUG: Enable debugging in memp.c. 176 */ 177 #define MEMP_DEBUG LWIP_DBG_OFF 178 179 /** 180 * SYS_DEBUG: Enable debugging in sys.c. 181 */ 182 #define SYS_DEBUG LWIP_DBG_OFF 183 184 /** 185 * TCP_DEBUG: Enable debugging for TCP. 186 */ 187 #define TCP_DEBUG LWIP_DBG_OFF 188 189 /** 190 * TCP_INPUT_DEBUG: Enable debugging in tcp_in.c for incoming debug. 191 */ 192 #define TCP_INPUT_DEBUG LWIP_DBG_OFF 193 /** 194 * TCP_FR_DEBUG: Enable debugging in tcp_in.c for fast retransmit. 195 */ 196 #define TCP_FR_DEBUG LWIP_DBG_OFF 197 198 /** 199 * TCP_RTO_DEBUG: Enable debugging in TCP for retransmit 200 * timeout. 201 */ 202 #define TCP_RTO_DEBUG LWIP_DBG_OFF 203 204 /** 205 * TCP_CWND_DEBUG: Enable debugging for TCP congestion window. 206 */ 207 #define TCP_CWND_DEBUG LWIP_DBG_OFF 208 209 /** 210 * TCP_WND_DEBUG: Enable debugging in tcp_in.c for window updating. 211 */ 212 #define TCP_WND_DEBUG LWIP_DBG_OFF 213 214 /** 215 * TCP_OUTPUT_DEBUG: Enable debugging in tcp_out.c output functions. 216 */ 217 #define TCP_OUTPUT_DEBUG LWIP_DBG_OFF 218 /** 219 * TCP_RST_DEBUG: Enable debugging for TCP with the RST message. 220 */ 221 #define TCP_RST_DEBUG LWIP_DBG_OFF 222 223 /** 224 * TCP_QLEN_DEBUG: Enable debugging for TCP queue lengths. 225 */ 226 #define TCP_QLEN_DEBUG LWIP_DBG_OFF 227 228 /** 229 * UDP_DEBUG: Enable debugging in UDP. 230 */ 231 #define UDP_DEBUG LWIP_DBG_OFF 232 233 /** 234 * TCPIP_DEBUG: Enable debugging in tcpip.c. 235 */ 236 #define TCPIP_DEBUG LWIP_DBG_OFF 237 238 /** 239 * PPP_DEBUG: Enable debugging for PPP. 240 */ 241 #define PPP_DEBUG LWIP_DBG_OFF 242 243 /** 244 * SLIP_DEBUG: Enable debugging in slipif.c. 245 */ 246 #define SLIP_DEBUG LWIP_DBG_OFF 247 248 /** 249 * DHCP_DEBUG: Enable debugging in dhcp.c. 250 */ 251 #define DHCP_DEBUG LWIP_DBG_OFF 252 253 /** 254 * AUTOIP_DEBUG: Enable debugging in autoip.c. 255 */ 256 #define AUTOIP_DEBUG LWIP_DBG_OFF 257 258 /** 259 * SNMP_MSG_DEBUG: Enable debugging for SNMP messages. 260 */ 261 #define SNMP_MSG_DEBUG LWIP_DBG_OFF 262 263 /** 264 * SNMP_MIB_DEBUG: Enable debugging for SNMP MIBs. 265 */ 266 #define SNMP_MIB_DEBUG LWIP_DBG_OFF 267 268 /** 269 * DNS_DEBUG: Enable debugging for DNS. 270 */ 271 #define DNS_DEBUG LWIP_DBG_OFF 272 #endif /* __LWIPOPTS_H__ */
5.修改\LWIP\netif目录下的ethernetif.c文件,按中文提示修改:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 Dunkels <adam@sics.se> 36 * 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_MLD 115 /* 116 * For hardware/netifs that implement MAC filtering. 117 * All-nodes link-local is handled by default, so we must let the hardware know 118 * 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); //初始化enc28j60 129 } 130 131 /** 132 * This function should do the actual transmission of the packet. The packet is 133 * contained in the pbuf that is passed to the function. This pbuf 134 * might be chained. 135 * 136 * @param netif the lwip network interface structure for this ethernetif 137 * @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 sent 139 * an err_t value if the packet couldn't be sent 140 * 141 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to 142 * strange results. You might consider waiting for space in the DMA queue 143 * to become available since the stack doesn't retry to send a packet 144 * dropped because of memory failure (except for the TCP timers). 145 */ 146 147 static err_t 148 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_SIZE 156 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 157 #endif 158 159 for (q = p; q != NULL; q = q->next) { 160 /* Send the data from the pbuf to the interface, one pbuf at a 161 time. The size of the data in each pbuf is kept in the ->len 162 variable. */ 163 //send data from(q->payload, q->len); 164 //将待发送数据包copy到发送Buff 165 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_SIZE 182 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 183 #endif 184 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 incoming 192 * packet from the interface into the pbuf. 193 * 194 * @param netif the lwip network interface structure for this ethernetif 195 * @return a pbuf filled with the received packet (including MAC header) 196 * NULL on memory error 197 */ 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_SIZE 210 len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ 211 #endif 212 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_SIZE 219 pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ 220 #endif 221 222 /* We iterate over the pbuf chain until we have read the entire 223 * packet into the pbuf. */ 224 for (q = p; q != NULL; q = q->next) { 225 /* Read enough bytes to fill this pbuf in the chain. The 226 * available data in the pbuf is given by the q->len 227 * variable. 228 * This does not necessarily have to be a memcpy, you can also preallocate 229 * pbufs for a DMA-enabled MAC and after receiving truncate it to the 230 * actually received size. In this case, ensure the tot_len member of the 231 * 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_SIZE 254 pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ 255 #endif 256 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 read 270 * from the interface. It uses the function low_level_input() that 271 * should handle the actual reception of bytes from the network 272 * interface. Then the type of the received packet is determined and 273 * the appropriate input function is called. 274 * 275 * @param netif the lwip network interface structure for this ethernetif 276 */ 277 //去掉静态定义 278 /*static*/ void 279 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 the 302 * network interface. It calls the function low_level_init() to do the 303 * 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 ethernetif 308 * @return ERR_OK if the loopif is initialized 309 * ERR_MEM if private data couldn't be allocated 310 * any other err_t on error 311 */ 312 err_t 313 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_HOSTNAME 326 /* 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 units 333 * 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 link 343 * is available...) */ 344 netif->output = etharp_output; 345 #if LWIP_IPV6 346 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驱动程序加入工程中,以下文件为网上借鉴,亲测可用:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 * º¯ÊýÃû£ºenc28j60SetBank 107 * ÃèÊö £ºÑ¡¶¨½«Òª²Ù×÷µÄbank 108 * ÊäÈë £º´øÓÐ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 bank 117 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 * º¯ÊýÃû£ºenc28j60Read 125 * ÃèÊö £º¶ÁÈ¡¿ØÖƼĴæÆ÷µÄÄÚÈÝ 126 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ· 127 * Êä³ö £ºÎÞ 128 */ 129 u8 enc28j60Read(u8 address) 130 { 131 // set the bank 132 enc28j60SetBank(address); 133 // do the read 134 return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address); 135 } 136 137 138 /* 139 * º¯ÊýÃû£ºenc28j60Write 140 * ÃèÊö £ºÐ´ÈëÊý¾Ýµ½¿ØÖƼĴæÆ÷ 141 * ÊäÈë £º¿ØÖƼĴæÆ÷µÄµØÖ·£¬ÃüÁî 142 * Êä³ö £ºÎÞ 143 */ 144 void enc28j60Write(u8 address, u8 data) 145 { 146 // set the bank 147 enc28j60SetBank(address); 148 // do the write 149 enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data); 150 } 151 152 /* 153 * º¯ÊýÃû£ºenc28j60PhyWrite 154 * ÃèÊö £ºÏòphyдÈë¿ØÖƲÎÊý 155 * ÊäÈë £º¼Ä´æÆ÷µÄµØÖ·£¬ÃüÁî 156 * Êä³ö £ºÎÞ 157 */ 158 void enc28j60PhyWrite(u8 address, u16 data) 159 { 160 // set the PHY register address 161 enc28j60Write(MIREGADR, address); 162 // write the PHY data 163 enc28j60Write(MIWRL, data); 164 enc28j60Write(MIWRH, data >> 8); 165 // wait until the PHY write completes 166 while (enc28j60Read(MISTAT) & MISTAT_BUSY) 167 { 168 //Del_10us(1); 169 //_nop_(); 170 } 171 } 172 173 /* 174 * º¯ÊýÃû£ºenc28j60clkout 175 * ÃèÊö £ºÉèÖÃÊä³öʱÖÓ 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 * º¯ÊýÃû£ºenc28j60Init 187 * ÃèÊö £º³õʼ»¯ÒÔÌ«Íø¿ØÖÆÆ÷ 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 complete 199 // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. 200 //while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY)); 201 // do bank 0 stuff 202 // initialize receive buffer 203 // 16-bit transfers, must write low byte first 204 // set receive buffer start address 205 NextPacketPtr = RXSTART_INIT; 206 // Rx start 207 enc28j60Write(ERXSTL, RXSTART_INIT & 0xFF); 208 enc28j60Write(ERXSTH, RXSTART_INIT >> 8); 209 // set receive pointer address 210 enc28j60Write(ERXRDPTL, RXSTART_INIT & 0xFF); 211 enc28j60Write(ERXRDPTH, RXSTART_INIT >> 8); 212 // RX end 213 enc28j60Write(ERXNDL, RXSTOP_INIT & 0xFF); 214 enc28j60Write(ERXNDH, RXSTOP_INIT >> 8); 215 // TX start 216 enc28j60Write(ETXSTL, TXSTART_INIT & 0xFF); 217 enc28j60Write(ETXSTH, TXSTART_INIT >> 8); 218 // TX end 219 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 packtets 223 // All other packets should be unicast only for our mac (MAADR) 224 // 225 // The pattern to match on is therefore 226 // Type ETH.DST 227 // ARP BROADCAST 228 // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 229 // in binary these poitions are:11 0000 0011 1111 230 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 231 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 stuff 239 // enable MAC receive 240 enc28j60Write(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); 241 // bring MAC out of reset 242 enc28j60Write(MACON2, 0x00); 243 // enable automatic padding to 60bytes and CRC operations 244 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX );//MACON3_HFRMLEN 245 // 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 accept 251 // Do not send packets longer than MAX_FRAMELEN: 252 enc28j60Write(MAMXFLL, MAX_FRAMELEN & 0xFF); 253 enc28j60Write(MAMXFLH, MAX_FRAMELEN >> 8); 254 // do bank 3 stuff 255 // write MAC address 256 // NOTE: MAC address in ENC28J60 is byte-backward 257 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 frames 270 enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); 271 // switch to bank 0 272 enc28j60SetBank(ECON1); 273 // enable interrutps 274 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); 275 // enable packet reception 276 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 * º¯ÊýÃû£ºenc28j60PacketSend 288 * ÃèÊö £º·¢ËÍÒ»¸öÊý¾Ý°ü 289 * ÊäÈë £ºÊý¾Ý°ü³¤¶È£¬Ö¸ÏòÊý¾Ý°üµÄÖ¸Õë 290 * Êä³ö £ºÎÞ 291 */ 292 void enc28j60PacketSend(u16 len, u8* packet) 293 { 294 // Set the write pointer to start of transmit buffer area 295 enc28j60Write(EWRPTL, TXSTART_INIT & 0xFF); 296 enc28j60Write(EWRPTH, TXSTART_INIT >> 8); 297 298 // Set the TXND pointer to correspond to the packet size given 299 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 buffer 306 enc28j60WriteBuffer(len, packet); 307 308 // send the contents of the transmit buffer onto the network 309 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 buffered 331 //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 packet 339 enc28j60Write(ERDPTL, (NextPacketPtr)); 340 enc28j60Write(ERDPTH, (NextPacketPtr) >> 8); 341 342 // read the next packet pointer 343 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 count 351 // 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 length 355 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 not 362 // need to check this. 363 if ((rxstat & 0x80) == 0) 364 { 365 // invalid 366 len = 0; 367 } 368 else 369 { 370 // copy the packet from the receive buffer 371 enc28j60ReadBuffer(len, packet); 372 } 373 // Move the RX read pointer to the start of the next received packet 374 // This frees the memory we just read out 375 enc28j60Write(ERXRDPTL, (NextPacketPtr)); 376 enc28j60Write(ERXRDPTH, (NextPacketPtr) >> 8); 377 378 // decrement the packet counter indicate we are done with this packet 379 enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); 380 return(len); 381 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <stm32f4xx.h> 2 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 registers 109 #define PHCON1 0x00 110 #define PHSTAT1 0x01 111 #define PHHID1 0x02 112 #define PHHID2 0x03 113 #define PHCON2 0x10 114 #define PHSTAT2 0x11 115 #define PHIE 0x12 116 #define PHIR 0x13 117 #define PHLCON 0x14 118 119 // ENC28J60 ERXFCON Register Bit Definitions 120 #define ERXFCON_UCEN 0x80 121 #define ERXFCON_ANDOR 0x40 122 #define ERXFCON_CRCEN 0x20 123 #define ERXFCON_PMEN 0x10 124 #define ERXFCON_MPEN 0x08 125 #define ERXFCON_HTEN 0x04 126 #define ERXFCON_MCEN 0x02 127 #define ERXFCON_BCEN 0x01 128 // ENC28J60 EIE Register Bit Definitions 129 #define EIE_INTIE 0x80 130 #define EIE_PKTIE 0x40 131 #define EIE_DMAIE 0x20 132 #define EIE_LINKIE 0x10 133 #define EIE_TXIE 0x08 134 #define EIE_WOLIE 0x04 135 #define EIE_TXERIE 0x02 136 #define EIE_RXERIE 0x01 137 // ENC28J60 EIR Register Bit Definitions 138 #define EIR_PKTIF 0x40 139 #define EIR_DMAIF 0x20 140 #define EIR_LINKIF 0x10 141 #define EIR_TXIF 0x08 142 #define EIR_WOLIF 0x04 143 #define EIR_TXERIF 0x02 144 #define EIR_RXERIF 0x01 145 // ENC28J60 ESTAT Register Bit Definitions 146 #define ESTAT_INT 0x80 147 #define ESTAT_LATECOL 0x10 148 #define ESTAT_RXBUSY 0x04 149 #define ESTAT_TXABRT 0x02 150 #define ESTAT_CLKRDY 0x01 151 // ENC28J60 ECON2 Register Bit Definitions 152 #define ECON2_AUTOINC 0x80 153 #define ECON2_PKTDEC 0x40 154 #define ECON2_PWRSV 0x20 155 #define ECON2_VRPS 0x08 156 // ENC28J60 ECON1 Register Bit Definitions 157 #define ECON1_TXRST 0x80 158 #define ECON1_RXRST 0x40 159 #define ECON1_DMAST 0x20 160 #define ECON1_CSUMEN 0x10 161 #define ECON1_TXRTS 0x08 162 #define ECON1_RXEN 0x04 163 #define ECON1_BSEL1 0x02 164 #define ECON1_BSEL0 0x01 165 // ENC28J60 MACON1 Register Bit Definitions 166 #define MACON1_LOOPBK 0x10 167 #define MACON1_TXPAUS 0x08 168 #define MACON1_RXPAUS 0x04 169 #define MACON1_PASSALL 0x02 170 #define MACON1_MARXEN 0x01 171 // ENC28J60 MACON2 Register Bit Definitions 172 #define MACON2_MARST 0x80 173 #define MACON2_RNDRST 0x40 174 #define MACON2_MARXRST 0x08 175 #define MACON2_RFUNRST 0x04 176 #define MACON2_MATXRST 0x02 177 #define MACON2_TFUNRST 0x01 178 // ENC28J60 MACON3 Register Bit Definitions 179 #define MACON3_PADCFG2 0x80 180 #define MACON3_PADCFG1 0x40 181 #define MACON3_PADCFG0 0x20 182 #define MACON3_TXCRCEN 0x10 183 #define MACON3_PHDRLEN 0x08 184 #define MACON3_HFRMLEN 0x04 185 #define MACON3_FRMLNEN 0x02 186 #define MACON3_FULDPX 0x01 187 // ENC28J60 MICMD Register Bit Definitions 188 #define MICMD_MIISCAN 0x02 189 #define MICMD_MIIRD 0x01 190 // ENC28J60 MISTAT Register Bit Definitions 191 #define MISTAT_NVALID 0x04 192 #define MISTAT_SCAN 0x02 193 #define MISTAT_BUSY 0x01 194 // ENC28J60 PHY PHCON1 Register Bit Definitions 195 #define PHCON1_PRST 0x8000 196 #define PHCON1_PLOOPBK 0x4000 197 #define PHCON1_PPWRSV 0x0800 198 #define PHCON1_PDPXMD 0x0100 199 // ENC28J60 PHY PHSTAT1 Register Bit Definitions 200 #define PHSTAT1_PFDPX 0x1000 201 #define PHSTAT1_PHDPX 0x0800 202 #define PHSTAT1_LLSTAT 0x0004 203 #define PHSTAT1_JBSTAT 0x0002 204 // ENC28J60 PHY PHCON2 Register Bit Definitions 205 #define PHCON2_FRCLINK 0x4000 206 #define PHCON2_TXDIS 0x2000 207 #define PHCON2_JABBER 0x0400 208 #define PHCON2_HDLDIS 0x0100 209 210 // ENC28J60 Packet Control Byte Bit Definitions 211 #define PKTCTRL_PHUGEEN 0x08 212 #define PKTCTRL_PPADEN 0x04 213 #define PKTCTRL_PCRCEN 0x02 214 #define PKTCTRL_POVERRIDE 0x01 215 216 // SPI operation codes 217 #define ENC28J60_READ_CTRL_REG 0x00 218 #define ENC28J60_READ_BUF_MEM 0x3A 219 #define ENC28J60_WRITE_CTRL_REG 0x40 220 #define ENC28J60_WRITE_BUF_MEM 0x7A 221 #define ENC28J60_BIT_FIELD_SET 0x80 222 #define ENC28J60_BIT_FIELD_CLR 0xA0 223 #define ENC28J60_SOFT_RESET 0xFF 224 225 // The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata 226 // buffer boundaries applied to internal 8K ram 227 // the entire available packet buffer space is allocated 228 // 229 // start with recbuf at 0/ 230 #define RXSTART_INIT 0x0 231 // receive buffer end 232 #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 mem 236 #define TXSTOP_INIT 0x1FFF 237 // 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 600 241 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接口,需根据实际端口修改,以下仅供参考:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #ifndef __SPI_H 2 #define __SPI_H 3 4 #include <stm32f4xx.h> 5 6 #define ENC28J60_CSL() (GPIOB->ODR &= ~(1<<12)) 7 #define ENC28J60_CSH() (GPIOB->ODR |= 1<<12) 8 9 10 #define ENC_SPI_ReadWrite SPI2_ReadWrite 11 #define ENC_SPI_Init SPI2_Init 12 13 void SPI2_Init(void); 14 uint8_t SPI2_ReadWrite(uint8_t writedat); 15 16 17 #endif
— —随笔,备忘!