当前位置:网站首页>Example of implementing web server with stm32+enc28j60+uip protocol stack
Example of implementing web server with stm32+enc28j60+uip protocol stack
2022-07-06 18:34:00 【Hua Weiyun】
One 、 Introduction to the environment
MCU: STM32F103ZET6
network card : ENC28J60
Protocol stack : UIP
Development software : Keil5
Two 、 Function is introduced
STM32 control ENC28J60+UIP Protocol stack creation TCP The server (WEB The server ), Support browser access to complete data transmission . The browser can display the temperature in real time 、 Time 、 Can be controlled STM32 On the development board LED The lamp 、 Buzzer .
edit
edit
edit
edit
edit
edit
3、 ... and 、 ENC28J60 Chip introduction
ENC28J60 Serial peripheral interface with industry standard (Serial Peripheral Interface,SPI) Independent Ethernet controller . It can be used as any equipped with SPI Ethernet interface of controller .ENC28J60 accord with IEEE 802.3 All specifications of , A series of packet filtering mechanisms are adopted to restrict incoming packets . It also provides an internal DMA modular , To achieve fast data throughput and hardware support IP Check and calculate . Communication with the main controller is through two interrupt pins and SPI Realization , The data transmission rate is as high as 10 Mb/s. Two dedicated pins are used for connection LED, Indication of network activity status .ENC28J60 There's only... In all 28 foot , Provide QFN/TF.
ENC28J60 The main features are as follows :
- compatible IEEE802.3 Ethernet controller based on Protocol
- Integrate MAC and 10 BASE-T The physical layer
- Full duplex and half duplex modes are supported
- Programmable automatic retransmission in case of data conflict
- SPI Interface speed up to 10Mbps
- 8K Data receiving and sending dual ports RAM
- Internal for fast data movement DMA controller
- Configurable receive and send buffer size
- Two programmable LED Output
- belt 7 Two interrupt pins of an interrupt source
- TTL Level input
- Multiple packages available :SOIC/SSOP/SPDIP/QFN etc. .
ENC28J60 It consists of seven main functional modules :
1) SPI Interface , Act as master controller and ENC28J60 The communication channel between them .
2) Control register , For control and monitoring ENC28J60.
3) Dual port RAM Buffer , Used to receive and send packets .
4) Optimizer , When DMA、 When the sending and receiving module sends a request RAM Buffer access control .
5) Bus interface , Yes SPI The received data and commands are parsed .
6) MAC(Medium Access Control) modular , Achieve compliance IEEE 802.3 The standard MAC Logic .
7) PHY( The physical layer ) modular , Encode and decode the analog data on the twisted pair .
ENC28J60 Other support modules are also included , Such as oscillator 、 On chip regulator 、 Level converter ( Provide acceptable 5V Of voltage I/O Pin ) And system control logic .
edit
edit
Four 、UIP brief introduction
uIP By the Swedish Academy of Computer Science ( Network embedded systems group ) Of Adam Dunkels Development . Its source code is from C language Speech compilation , And completely open ,uIP The latest version of is 1.0 edition . uIP The protocol stack removes the complete TCP/IP Functions not commonly used in , Simplify the communication process , But network communication is preserved Protocols that must be used , The design focuses on IP/TCP/ICMP/UDP/ARP These network layer and transport layer protocols , Guarantee The versatility of its code and the stability of its structure .
Official website :https://github.com/adamdunkels/uip
because uIP The protocol stack is specially designed for embedded systems , Therefore, it also has the following superior functions :
1) Very little code , Its protocol stack code is less than 6K, Easy to read and transplant .
2) The amount of memory used is very small ,RAM Occupy only a few hundred bytes .
3) Its hardware processing layer 、 The protocol stack layer and the application layer share a global cache , There is no copy of data , And send And receive depend on this cache , It greatly saves space and time .
4) Support multiple active connections and passive connections concurrently .
5) Its source code provides a set of example programs :web The server ,web client , Email sender (SMTP customer Home end ),Telnet The server , DNS Host name resolver, etc . Strong commonality , Transplantation can pass without modification .
6) The data processing adopts the round robin mechanism , No operating system support . because uIP Less need for resources and easy transplantation , Most of 8 Bit microcontrollers have been used uIP Protocol stack , And many famous embedded products and projects ( Like a satellite ,Cisco Router , Wireless sensor networks ) It's all in use uIP Protocol stack . uIP Equivalent to a code base , Through a series of functions to achieve communication with the underlying hardware and high-level applications , about For the whole system, its internal protocol group is transparent , Thus, the universality of the protocol is increased .
uIP The interface functions provided are :
1. initialization uIP Protocol stack :uip_init()
2. Process input packages :uip_input()
3. Handle cycle timing events :uip_periodic()
4. Start listening to port :uip_listen()
5. Connect to remote host :uip_connect()
6. Connection request received :uip_connected()
7. Active close connection :uip_close()
8. The connection is closed :uip_closed()
9. The sent data is answered :uip_acked()
10. Send data on the current connection :uip_send()
11. New data received on the current connection :uip_newdata()
12. Tell the other party to stop connecting :uip_stop()
13. The connection was terminated unexpectedly :uip_aborted()
edit
5、 ... and 、 Core code
5.1 main.c
#include "stm32f10x.h"#include "led.h"#include "delay.h"#include "key.h"#include "usart.h"#include <string.h>#include <stdio.h>#include "enc28j60.h"#include "time.h"#include "uip.h"#include "uip_arp.h"#include "tapdev.h"#include "timer.h"#include "uip-conf.h"#include "httpd.h"#include "ds18b20.h"#include "rtc.h"void uip_EventPoll(void); // Event handler #define UIP_BUF ((struct uip_eth_hdr *)&uip_buf[0])/* When Uip Received Uip Receive the data transmitted to the bottom , Call the received data http_appcall(), Pass to Webserver Handle , Re pass handle_connection() Call it successively handle_input() Functions and handle_output() function handle_input() The main function is to analyze http Data flow : Get the requested path 、 Resolve the requested file name . And then call the function. handle_output Search the corresponding file , Send to browser , To complete the interaction . Be careful : Google browser is the best browser , Otherwise, the access will fail !*/int main(){ u8 key; u32 tcnt=0; uip_ipaddr_t ipaddr; // preservation IP Address information BeepInit(); // Buzzer initialization LedInit(); //LED Lamp initialization UsartInit(USART1,72,115200); KeyInit(); // Key initialization TimerInit(TIM6,72,10000); // Timer initialization , DS18B20_Init(); RTC_Init(); SET_RTC_TIME(2019,5,24,10,58,20); printf(" The serial port works normally !\r\n"); while(tapdev_init()) // initialization ENC28J60 error { printf("ENC28J60 Init Error!\r\n"); Delay72M_Ms(500); } printf("ENC28J60 Successful initialization !\r\n"); uip_init(); //uIP initialization uip_ipaddr(ipaddr, 192,168,1,89); // Fill the development board IP Address uip_sethostaddr(ipaddr); // Set up the development board IP Address uip_ipaddr(ipaddr, 192,168,1,1); // Fill in the gateway address of the development board uip_setdraddr(ipaddr); // Setting development board gateway IP Address ( It's actually your router IP Address ) uip_ipaddr(ipaddr, 255,255,255,0); // Fill in the development board netmask uip_setnetmask(ipaddr); // Fill in the development board netmask httpd_init(); // establish WEB The server , Set listening port while(1) { uip_EventPoll(); // Polling processing network data }}/* The functionality :uip Event handler , You need to insert this function into the user main loop , Cycle call */void uip_EventPoll(void){ u8 i; static struct timer arp_timer; // Define timer static u8 timer_ok=0; if(timer_ok==0)// Initialize only once { timer_ok = 1; timer_set(&arp_timer,CLOCK_SECOND*10); // establish 1 individual 10 Second timer } uip_len=tapdev_read(); // Read a from the network device IP package , Get the data length .uip_len stay uip.c In the definition of if(uip_len>0) // There's data { // Handle IP Data packets ( Only those who pass the verification IP Packets will be received ) if(UIP_BUF->type == htons(UIP_ETHTYPE_IP))// Whether it is IP package ? { uip_arp_ipin(); // Remove the Ethernet head structure , to update ARP surface uip_input(); //IP Package processing // When the above function is executed , If you need to send data , Then global variables uip_len > 0 // The data to be sent is uip_buf, The length is uip_len ( This is a 2 Global variables ) if(uip_len>0)// Need to respond to data { uip_arp_out();// Add Ethernet head structure , It may be necessary to construct ARP request tapdev_send();// Send data to Ethernet } } else if (UIP_BUF->type==htons(UIP_ETHTYPE_ARP))// Handle arp message , Whether it is ARP Request package ? { uip_arp_arpin(); // When the above function is executed , If you need to send data , Then global variables uip_len>0 // The data to be sent is uip_buf, The length is uip_len( This is a 2 Global variables ) if(uip_len>0)tapdev_send();// You need to send data , Through tapdev_send send out } } // Take turns dealing with each TCP Connect , UIP_CONNS The default is 40 individual for(i=0; i<UIP_CONNS; i++) { uip_periodic(i); // Handle TCP Communication event // When the above function is executed , If you need to send data , Then global variables uip_len>0 // The data to be sent is uip_buf, The length is uip_len ( This is a 2 Global variables ) if(uip_len>0) { uip_arp_out();// Add Ethernet head structure , It may be necessary to construct ARP request tapdev_send();// Send data to Ethernet } } // every other 10 Second call 1 Time ARP Timer Functions For periodic ARP Handle ,ARP surface 10 Seconds to update , Old entries will be discarded if(timer_expired(&arp_timer)) { timer_reset(&arp_timer); uip_arp_timer(); }}
5.2 enc28j60.c
#include "delay.h"#include <stdio.h>#include "enc28j60.h" /* Here are ENC28J60 Driver migration interface :MISO--->PA6---- Host input MOSI--->PA7---- Host output SCLK--->PA5---- Clock signal CS----->PA4---- Chip selection RESET-->PG15--- Reset */#define ENC28J60_CS PAout(4) //ENC28J60 Piece of optional signal #define ENC28J60_RST PGout(15) //ENC28J60 Reset signal #define ENC28J60_MOSI PAout(7) // Output #define ENC28J60_MISO PAin(6) // Input #define ENC28J60_SCLK PAout(5) // Clock line static u8 ENC28J60BANK;static u32 NextPacketPtr;/* The functionality : Bottom SPI The interface sends and receives a byte saying bright : simulation SPI sequential ,ENC28J60 The idle level of the clock line is low , Collect data on the first falling edge */u8 ENC28J60_SPI_ReadWriteOneByte(u8 tx_data){ u16 cnt=0; while((SPI1->SR&1<<1)==0) // The waiting area is empty -- Waiting to send buffer is empty { cnt++; if(cnt>=65530)return 0; // Timeout exit u16=2 Bytes } SPI1->DR=tx_data; // Send a byte cnt=0; while((SPI1->SR&1<<0)==0) // Waiting for one to be received byte { cnt++; if(cnt>=65530)return 0; // Timeout exit } return SPI1->DR; // Return the received data }/* The functionality : Reset ENC28J60, Include SPI initialization /IO Initialization etc. MISO--->PA6---- Host input MOSI--->PA7---- Host output SCLK--->PA5---- Clock signal CS----->PA4---- Chip selection RESET-->PG15--- Reset */void ENC28J60_Reset(void){/* Turn on the clock */ RCC->APB2ENR|=1<<12; // Turn on SPI1 The clock RCC->APB2ENR|=1<<2; //PA GPIOA->CRL&=0X0000FFFF; // Clear register GPIOA->CRL|=0XB8B30000; GPIOA->ODR|=0XF<<4; // Pull up -- Output high level GPIOA->ODR&=~(1<<5); RCC->APB2ENR|=1<<8; //2 3 4 5 6 7 8 GPIOG->CRH&=0x0FFFFFFF; GPIOG->CRH|=0x30000000; /*SPI2 Basic configuration */ SPI1->CR1=0X0; // Clear register SPI1->CR1|=0<<15; // choice “ Two line, two-way ” Pattern SPI1->CR1|=0<<11; // Use 8 Send in bit data frame format / receive ; SPI1->CR1|=0<<10; // full duplex ( Send and receive ); SPI1->CR1|=1<<9; // Enable software slave device management SPI1->CR1|=1<<8; //NSS SPI1->CR1|=0<<7; // The frame format , Send the high bit first SPI1->CR1|=0x1<<3;// When the bus frequency is 36MHZ when ,SPI Speed is 18MHZ, High speed . SPI1->CR1|=1<<2; // Configure the master device SPI1->CR1|=1<<1; // When idle , SCK Keep it high . SPI1->CR1|=1<<0; // Data sampling starts from the edge of the second clock . SPI1->CR1|=1<<6; // Turn on SPI equipment . // in the light of ENC28J60 Characteristics (SCK Idle is low ) modify SPI Set up SPI1->CR1&=~(1<<6); //SPI Equipment failure SPI1->CR1&=~(1<<1); // In idle mode SCK by 0 CPOL=0 SPI1->CR1&=~(1<<0); // Data sampling from 1 Start at the edge of time ,CPHA=0 SPI1->CR1|=1<<6; //SPI Equipment enabling ENC28J60_RST=0; // Reset ENC28J60 DelayMs(10); ENC28J60_RST=1; // Reset end DelayMs(10); }/* The functionality : Read ENC28J60 register ( With opcode ) ginseng Count :op: opcode addr: Register address / Parameters return return value : Data read */u8 ENC28J60_Read_Op(u8 op,u8 addr){ u8 dat=0; ENC28J60_CS=0; dat=op|(addr&ADDR_MASK); ENC28J60_SPI_ReadWriteOneByte(dat); dat=ENC28J60_SPI_ReadWriteOneByte(0xFF); // If it's read MAC/MII register , Then the data read for the second time is correct , See manual 29 page if(addr&0x80)dat=ENC28J60_SPI_ReadWriteOneByte(0xFF); ENC28J60_CS=1; return dat;}/* The functionality : Read ENC28J60 register ( With opcode ) ginseng Count : op: opcode addr: Register address data: Parameters */void ENC28J60_Write_Op(u8 op,u8 addr,u8 data){ u8 dat = 0; ENC28J60_CS=0; dat=op|(addr&ADDR_MASK); ENC28J60_SPI_ReadWriteOneByte(dat); ENC28J60_SPI_ReadWriteOneByte(data); ENC28J60_CS=1;}/* The functionality : Read ENC28J60 Receive cached data parameters Count : len: The length of data to read data: Output data buffer ( Automatically add terminator at the end )*/void ENC28J60_Read_Buf(u32 len,u8* data){ ENC28J60_CS=0; ENC28J60_SPI_ReadWriteOneByte(ENC28J60_READ_BUF_MEM); while(len) { len--; *data=(u8)ENC28J60_SPI_ReadWriteOneByte(0); data++; } *data='\0'; ENC28J60_CS=1;}/* The functionality : towards ENC28J60 Write send cache data parameters Count : len: The length of data to write data: Data cache */void ENC28J60_Write_Buf(u32 len,u8* data){ ENC28J60_CS=0; ENC28J60_SPI_ReadWriteOneByte(ENC28J60_WRITE_BUF_MEM); while(len) { len--; ENC28J60_SPI_ReadWriteOneByte(*data); data++; } ENC28J60_CS=1;}/* The functionality : Set up ENC28J60 register Bank ginseng Count : ban: To set up bank*/void ENC28J60_Set_Bank(u8 bank){ if((bank&BANK_MASK)!=ENC28J60BANK)// And the current bank When they disagree , Only set { ENC28J60_Write_Op(ENC28J60_BIT_FIELD_CLR,ECON1,(ECON1_BSEL1|ECON1_BSEL0)); ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,(bank&BANK_MASK)>>5); ENC28J60BANK=(bank&BANK_MASK); }}/* The functionality : Read ENC28J60 Specify register parameters Count :addr: Register address returns return value : Data read */u8 ENC28J60_Read(u8 addr){ ENC28J60_Set_Bank(addr);// Set up BANK return ENC28J60_Read_Op(ENC28J60_READ_CTRL_REG,addr);}/* The functionality : towards ENC28J60 Specify register write data parameters Count : addr: Register address data: The data to be written */void ENC28J60_Write(u8 addr,u8 data){ ENC28J60_Set_Bank(addr); ENC28J60_Write_Op(ENC28J60_WRITE_CTRL_REG,addr,data);}/* The functionality : towards ENC28J60 Of PHY Register writes data parameters Count : addr: Register address data: The data to be written */void ENC28J60_PHY_Write(u8 addr,u32 data){ u16 retry=0; ENC28J60_Write(MIREGADR,addr); // Set up PHY Register address ENC28J60_Write(MIWRL,data); // Write data ENC28J60_Write(MIWRH,data>>8); while((ENC28J60_Read(MISTAT)&MISTAT_BUSY)&&retry<0XFFF)retry++;// Waiting to write PHY end }/* The functionality : initialization ENC28J60 ginseng Count :macaddr:MAC Address return return value : 0, Successful initialization ; 1, initialization failed ;*/u8 ENC28J60_Init(u8* macaddr){ u16 retry=0; ENC28J60_Reset(); // Reset the underlying pin interface ENC28J60_Write_Op(ENC28J60_SOFT_RESET,0,ENC28J60_SOFT_RESET);// Software reset while(!(ENC28J60_Read(ESTAT)&ESTAT_CLKRDY)&&retry<500)// Wait for the clock to stabilize { retry++; DelayMs(1); }; if(retry>=500)return 1;//ENC28J60 initialization failed // do bank 0 stuff // initialize receive buffer // 16-bit transfers,must write low byte first // set receive buffer start address Set receive buffer address 8K Byte capacity NextPacketPtr=RXSTART_INIT; // Rx start // The receive buffer is a loop managed by hardware FIFO Buffer composition . // Register pair ERXSTH:ERXSTL and ERXNDH:ERXNDL do // For the pointer , Defines the capacity of the buffer and its location in memory . //ERXST and ERXND The bytes pointed to are contained in FIFO In buffer . // When receiving data bytes from the Ethernet interface , These bytes are written sequentially // Receive buffer . But when written by ERXND Point to the storage unit // after , The hardware will automatically write the next byte received to ERXST Point to // The storage unit of . Therefore, the receiving hardware will not write FIFO Orders other than // element . // Set receive start byte ENC28J60_Write(ERXSTL,RXSTART_INIT&0xFF); ENC28J60_Write(ERXSTH,RXSTART_INIT>>8); //ERXWRPTH:ERXWRPTL Register definition hardware FIFO in // Where does the receive byte write . The pointer is read-only , Zai Cheng // After receiving a packet , The hardware automatically updates the pointer . The pointer can // Used to judge FIFO Size of remaining space in 8K-1500. // Set receive read pointer byte ENC28J60_Write(ERXRDPTL,RXSTART_INIT&0xFF); ENC28J60_Write(ERXRDPTH,RXSTART_INIT>>8); // Set receive end byte ENC28J60_Write(ERXNDL,RXSTOP_INIT&0xFF); ENC28J60_Write(ERXNDH,RXSTOP_INIT>>8); // Set send start byte ENC28J60_Write(ETXSTL,TXSTART_INIT&0xFF); ENC28J60_Write(ETXSTH,TXSTART_INIT>>8); // Set send end byte ENC28J60_Write(ETXNDL,TXSTOP_INIT&0xFF); ENC28J60_Write(ETXNDH,TXSTOP_INIT>>8); // do bank 1 stuff,packet filter: // For broadcast packets we allow only ARP packtets // All other packets should be unicast only for our mac (MAADR) // // The pattern to match on is therefore // Type ETH.DST // ARP BROADCAST // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 // in binary these poitions are:11 0000 0011 1111 // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 // Receive filter //UCEN: Unicast filter enable bit // When ANDOR = 1 when : //1 = Destination address and local address MAC Packets with mismatched addresses will be discarded //0 = Prohibit filter // When ANDOR = 0 when : //1 = Destination address and local address MAC Packets with matching addresses will be accepted //0 = Prohibit filter //CRCEN: Rear filter CRC Check enable bit //1 = all CRC Invalid packets will be discarded //0 = Don't consider CRC Whether it works //PMEN: Format matching filter enable bit // When ANDOR = 1 when : //1 = The packet must meet the format matching criteria , Otherwise it will be discarded //0 = Prohibit filter // When ANDOR = 0 when : //1 = Packets that meet the format matching criteria will be accepted //0 = Prohibit filter ENC28J60_Write(ERXFCON,ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN); ENC28J60_Write(EPMM0,0x3f); ENC28J60_Write(EPMM1,0x30); ENC28J60_Write(EPMCSL,0xf9); ENC28J60_Write(EPMCSH,0xf7); // do bank 2 stuff // enable MAC receive //bit 0 MARXEN:MAC Receive enable bit //1 = allow MAC Receive packets //0 = Prohibit packet reception //bit 3 TXPAUS: Pause control frame transmission enable bit //1 = allow MAC Send pause control frame ( Used for flow control in full duplex mode ) //0 = Prohibit pause frame transmission //bit 2 RXPAUS: Pause control frame reception enable bit //1 = When a pause control frame is received , Prohibit sending ( Normal operation ) //0 = Ignore the received pause control frame ENC28J60_Write(MACON1,MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); // bring MAC out of reset // take MACON2 Medium MARST A reset , send MAC Exit reset state . ENC28J60_Write(MACON2,0x00); // enable automatic padding to 60bytes and CRC operations //bit 7-5 PADCFG2:PACDFG0: Auto fill and CRC Configuration bit //111 = use 0 Fill all short frames to 64 Byte length , And add a valid CRC //110 = Do not automatically fill short frames //101 = MAC Automatic detection with 8100h Of the type field VLAN Protocol frame , And automatically fill in 64 Byte length . If you don't // yes VLAN frame , Fill to 60 Byte length . After filling, a valid is added CRC //100 = Do not automatically fill short frames //011 = use 0 Fill all short frames to 64 Byte length , And add a valid CRC //010 = Do not automatically fill short frames //001 = use 0 Fill all short frames to 60 Byte length , And add a valid CRC //000 = Do not automatically fill short frames //bit 4 TXCRCEN: send out CRC Enable bit //1 = No matter PADCFG how ,MAC A valid will be appended at the end of the transmitted frame CRC. If PADCFG Required // Append valid CRC, You have to TXCRCEN Set up 1. //0 = MAC No append CRC. Check at the end 4 Bytes , If not valid CRC Report to send status vector . //bit 0 FULDPX:MAC Full duplex enable bit //1 = MAC Working in full duplex mode . PHCON1.PDPXMD Bit must be set to 1. //0 = MAC Working in half duplex mode . PHCON1.PDPXMD Bit must be cleared . ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,MACON3,MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN|MACON3_FULDPX); // set inter-frame gap (non-back-to-back) // Configure the low byte of the non back to back inter knapsack interval register //MAIPGL. Most applications use 12h Program the register . // If half duplex mode is used , The spacing between non back to back backpacks shall be programmed // High byte of register MAIPGH. Most applications use 0Ch // Program the register . ENC28J60_Write(MAIPGL,0x12); ENC28J60_Write(MAIPGH,0x0C); // set inter-frame gap (back-to-back) // Configure the back-to-back interval register MABBIPG. When using // In full duplex mode , Most applications use 15h Program the register // device , When half duplex mode is used 12h Programming . ENC28J60_Write(MABBIPG,0x15); // Set the maximum packet size which the controller will accept // Do not send packets longer than MAX_FRAMELEN: // Maximum frame length 1500 ENC28J60_Write(MAMXFLL,MAX_FRAMELEN&0xFF); ENC28J60_Write(MAMXFLH,MAX_FRAMELEN>>8); // do bank 3 stuff // write MAC address // NOTE: MAC address in ENC28J60 is byte-backward // Set up MAC Address ENC28J60_Write(MAADR5,macaddr[0]); ENC28J60_Write(MAADR4,macaddr[1]); ENC28J60_Write(MAADR3,macaddr[2]); ENC28J60_Write(MAADR2,macaddr[3]); ENC28J60_Write(MAADR1,macaddr[4]); ENC28J60_Write(MAADR0,macaddr[5]); // To configure PHY Full duplex LEDB Pull current ENC28J60_PHY_Write(PHCON1,PHCON1_PDPXMD); // no loopback of transmitted frames No loopback //HDLDIS:PHY Half duplex loopback inhibit bit // When PHCON1.PDPXMD = 1 or PHCON1.PLOOPBK = 1 when : // This bit can be ignored . // When PHCON1.PDPXMD = 0 And PHCON1.PLOOPBK = 0 when : //1 = The data to be sent is sent only through the twisted pair interface //0 = The data to be sent is looped back MAC And send it through the twisted pair interface ENC28J60_PHY_Write(PHCON2,PHCON2_HDLDIS); // switch to bank 0 //ECON1 register // register 3-1 As shown in the for ECON1 register , It's used to control //ENC28J60 The main function of . ECON1 Receive enable included in 、 Hair // Send request 、DMA Control and store selection bits . ENC28J60_Set_Bank(ECON1); // enable interrutps //EIE: Ethernet interrupt enable register //bit 7 INTIE: overall situation INT Interrupt allow bit //1 = Allow interrupt event driven INT Pin //0 = Prohibit all INT Pin activity ( The pin is always driven high ) //bit 6 PKTIE: Received packet pending interrupt enable bit //1 = Allow receive packet pending interrupt //0 = Prohibit receiving packet pending interrupt ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,EIE,EIE_INTIE|EIE_PKTIE); // enable packet reception //bit 2 RXEN: Receive enable bit //1 = Packets passing through the current filter will be written to the receive buffer //0 = Ignore all received packets ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,ECON1_RXEN); if(ENC28J60_Read(MAADR5)== macaddr[0])return 0;// Successful initialization else return 1; }/* The functionality : Read EREVID ginseng Count :*/u8 ENC28J60_Get_EREVID(void){ // stay EREVID Version information is also stored in the . EREVID Is a read-only controller // System register , Contains a 5 Bit identifier , Used to identify device specific silicon wafers // Version number of return ENC28J60_Read(EREVID);}/* The functionality : adopt ENC28J60 Send packets to network parameters Count : len : Packet size packet: Data packets */void ENC28J60_Packet_Send(u32 len,u8* packet){ // Set send buffer address write pointer entry ENC28J60_Write(EWRPTL,TXSTART_INIT&0xFF); ENC28J60_Write(EWRPTH,TXSTART_INIT>>8); // Set up TXND The pointer , To correspond to the given packet size ENC28J60_Write(ETXNDL,(TXSTART_INIT+len)&0xFF); ENC28J60_Write(ETXNDH,(TXSTART_INIT+len)>>8); // Write control bytes per packet (0x00 Said the use of macon3 Set up ) ENC28J60_Write_Op(ENC28J60_WRITE_BUF_MEM,0,0x00); // Copy packets to send buffer //printf("len:%d\r\n",len); // Monitor the length of transmitted data ENC28J60_Write_Buf(len,packet); // Send data to the network ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON1,ECON1_TXRTS); // Reset sending logic problem . See Rev. B4 Silicon Errata point 12. if((ENC28J60_Read(EIR)&EIR_TXERIF))ENC28J60_Write_Op(ENC28J60_BIT_FIELD_CLR,ECON1,ECON1_TXRTS);}/* The functionality : Get a packet content function parameter from the network : maxlen: Maximum allowable packet receiving length packet: Packet buffer returned return value : Received packet length ( byte ) */u32 ENC28J60_Packet_Receive(u32 maxlen,u8* packet){ u32 rxstat; u32 len; if(ENC28J60_Read(EPKTCNT)==0)return 0; // Received packet ? // Set receive buffer read pointer ENC28J60_Write(ERDPTL,(NextPacketPtr)); ENC28J60_Write(ERDPTH,(NextPacketPtr)>>8); // Read the pointer to the next package NextPacketPtr=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0); NextPacketPtr|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8; // Read packet length len=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0); len|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8; len-=4; // Get rid of CRC Count // Read receive status rxstat=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0); rxstat|=ENC28J60_Read_Op(ENC28J60_READ_BUF_MEM,0)<<8; // Limit receive length if (len>maxlen-1)len=maxlen-1; // Check CRC And symbol errors // ERXFCON.CRCEN For default settings , Generally, we don't need to check . if((rxstat&0x80)==0)len=0;// Invalid else ENC28J60_Read_Buf(len,packet);// Copy packets from receive buffer //RX The read pointer moves to the start of the next received packet // And release the memory we just read out ENC28J60_Write(ERXRDPTL,(NextPacketPtr)); ENC28J60_Write(ERXRDPTH,(NextPacketPtr)>>8); // Decrementing the packet counter indicates that we have got the packet ENC28J60_Write_Op(ENC28J60_BIT_FIELD_SET,ECON2,ECON2_PKTDEC); return(len);}
5.3 enc28j60.h
#include "sys.h" #ifndef __ENC28J60_H#define __ENC28J60_H #include "stm32f10x.h"////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ENC28J60 Control Registers// Control register definitions are a combination of address,// bank number, and Ethernet/MAC/PHY indicator bits.// - Register address (bits 0-4)// - Bank number (bits 5-6)// - MAC/PHY indicator (bit 7)#define ADDR_MASK 0x1F#define BANK_MASK 0x60#define SPRD_MASK 0x80// All-bank registers#define EIE 0x1B#define EIR 0x1C#define ESTAT 0x1D#define ECON2 0x1E#define ECON1 0x1F// Bank 0 registers#define ERDPTL (0x00|0x00)#define ERDPTH (0x01|0x00)#define EWRPTL (0x02|0x00)#define EWRPTH (0x03|0x00)#define ETXSTL (0x04|0x00)#define ETXSTH (0x05|0x00)#define ETXNDL (0x06|0x00)#define ETXNDH (0x07|0x00)#define ERXSTL (0x08|0x00)#define ERXSTH (0x09|0x00)#define ERXNDL (0x0A|0x00)#define ERXNDH (0x0B|0x00)//ERXWRPTH:ERXWRPTL Register definition hardware FIFO in // Where does the receive byte write . The pointer is read-only , Zai Cheng // After receiving a packet , The hardware automatically updates the pointer . The pointer can // Used to judge FIFO Size of remaining space in .#define ERXRDPTL (0x0C|0x00)#define ERXRDPTH (0x0D|0x00)#define ERXWRPTL (0x0E|0x00)#define ERXWRPTH (0x0F|0x00)#define EDMASTL (0x10|0x00)#define EDMASTH (0x11|0x00)#define EDMANDL (0x12|0x00)#define EDMANDH (0x13|0x00)#define EDMADSTL (0x14|0x00)#define EDMADSTH (0x15|0x00)#define EDMACSL (0x16|0x00)#define EDMACSH (0x17|0x00)// Bank 1 registers#define EHT0 (0x00|0x20)#define EHT1 (0x01|0x20)#define EHT2 (0x02|0x20)#define EHT3 (0x03|0x20)#define EHT4 (0x04|0x20)#define EHT5 (0x05|0x20)#define EHT6 (0x06|0x20)#define EHT7 (0x07|0x20)#define EPMM0 (0x08|0x20)#define EPMM1 (0x09|0x20)#define EPMM2 (0x0A|0x20)#define EPMM3 (0x0B|0x20)#define EPMM4 (0x0C|0x20)#define EPMM5 (0x0D|0x20)#define EPMM6 (0x0E|0x20)#define EPMM7 (0x0F|0x20)#define EPMCSL (0x10|0x20)#define EPMCSH (0x11|0x20)#define EPMOL (0x14|0x20)#define EPMOH (0x15|0x20)#define EWOLIE (0x16|0x20)#define EWOLIR (0x17|0x20)#define ERXFCON (0x18|0x20)#define EPKTCNT (0x19|0x20)// Bank 2 registers#define MACON1 (0x00|0x40|0x80)#define MACON2 (0x01|0x40|0x80)#define MACON3 (0x02|0x40|0x80)#define MACON4 (0x03|0x40|0x80)#define MABBIPG (0x04|0x40|0x80)#define MAIPGL (0x06|0x40|0x80)#define MAIPGH (0x07|0x40|0x80)#define MACLCON1 (0x08|0x40|0x80)#define MACLCON2 (0x09|0x40|0x80)#define MAMXFLL (0x0A|0x40|0x80)#define MAMXFLH (0x0B|0x40|0x80)#define MAPHSUP (0x0D|0x40|0x80)#define MICON (0x11|0x40|0x80)#define MICMD (0x12|0x40|0x80)#define MIREGADR (0x14|0x40|0x80)#define MIWRL (0x16|0x40|0x80)#define MIWRH (0x17|0x40|0x80)#define MIRDL (0x18|0x40|0x80)#define MIRDH (0x19|0x40|0x80)// Bank 3 registers#define MAADR1 (0x00|0x60|0x80)#define MAADR0 (0x01|0x60|0x80)#define MAADR3 (0x02|0x60|0x80)#define MAADR2 (0x03|0x60|0x80)#define MAADR5 (0x04|0x60|0x80)#define MAADR4 (0x05|0x60|0x80)#define EBSTSD (0x06|0x60)#define EBSTCON (0x07|0x60)#define EBSTCSL (0x08|0x60)#define EBSTCSH (0x09|0x60)#define MISTAT (0x0A|0x60|0x80)#define EREVID (0x12|0x60)#define ECOCON (0x15|0x60)#define EFLOCON (0x17|0x60)#define EPAUSL (0x18|0x60)#define EPAUSH (0x19|0x60)// PHY registers#define PHCON1 0x00#define PHSTAT1 0x01#define PHHID1 0x02#define PHHID2 0x03#define PHCON2 0x10#define PHSTAT2 0x11#define PHIE 0x12#define PHIR 0x13#define PHLCON 0x14 // ENC28J60 ERXFCON Register Bit Definitions#define ERXFCON_UCEN 0x80#define ERXFCON_ANDOR 0x40#define ERXFCON_CRCEN 0x20#define ERXFCON_PMEN 0x10#define ERXFCON_MPEN 0x08#define ERXFCON_HTEN 0x04#define ERXFCON_MCEN 0x02#define ERXFCON_BCEN 0x01// ENC28J60 EIE Register Bit Definitions#define EIE_INTIE 0x80#define EIE_PKTIE 0x40#define EIE_DMAIE 0x20#define EIE_LINKIE 0x10#define EIE_TXIE 0x08#define EIE_WOLIE 0x04#define EIE_TXERIE 0x02#define EIE_RXERIE 0x01// ENC28J60 EIR Register Bit Definitions#define EIR_PKTIF 0x40#define EIR_DMAIF 0x20#define EIR_LINKIF 0x10#define EIR_TXIF 0x08#define EIR_WOLIF 0x04#define EIR_TXERIF 0x02#define EIR_RXERIF 0x01// ENC28J60 ESTAT Register Bit Definitions#define ESTAT_INT 0x80#define ESTAT_LATECOL 0x10#define ESTAT_RXBUSY 0x04#define ESTAT_TXABRT 0x02#define ESTAT_CLKRDY 0x01// ENC28J60 ECON2 Register Bit Definitions#define ECON2_AUTOINC 0x80#define ECON2_PKTDEC 0x40#define ECON2_PWRSV 0x20#define ECON2_VRPS 0x08// ENC28J60 ECON1 Register Bit Definitions#define ECON1_TXRST 0x80#define ECON1_RXRST 0x40#define ECON1_DMAST 0x20#define ECON1_CSUMEN 0x10#define ECON1_TXRTS 0x08#define ECON1_RXEN 0x04#define ECON1_BSEL1 0x02#define ECON1_BSEL0 0x01// ENC28J60 MACON1 Register Bit Definitions#define MACON1_LOOPBK 0x10#define MACON1_TXPAUS 0x08#define MACON1_RXPAUS 0x04#define MACON1_PASSALL 0x02#define MACON1_MARXEN 0x01// ENC28J60 MACON2 Register Bit Definitions#define MACON2_MARST 0x80#define MACON2_RNDRST 0x40#define MACON2_MARXRST 0x08#define MACON2_RFUNRST 0x04#define MACON2_MATXRST 0x02#define MACON2_TFUNRST 0x01// ENC28J60 MACON3 Register Bit Definitions#define MACON3_PADCFG2 0x80#define MACON3_PADCFG1 0x40#define MACON3_PADCFG0 0x20#define MACON3_TXCRCEN 0x10#define MACON3_PHDRLEN 0x08#define MACON3_HFRMLEN 0x04#define MACON3_FRMLNEN 0x02#define MACON3_FULDPX 0x01// ENC28J60 MICMD Register Bit Definitions#define MICMD_MIISCAN 0x02#define MICMD_MIIRD 0x01// ENC28J60 MISTAT Register Bit Definitions#define MISTAT_NVALID 0x04#define MISTAT_SCAN 0x02#define MISTAT_BUSY 0x01// ENC28J60 PHY PHCON1 Register Bit Definitions#define PHCON1_PRST 0x8000#define PHCON1_PLOOPBK 0x4000#define PHCON1_PPWRSV 0x0800#define PHCON1_PDPXMD 0x0100// ENC28J60 PHY PHSTAT1 Register Bit Definitions#define PHSTAT1_PFDPX 0x1000#define PHSTAT1_PHDPX 0x0800#define PHSTAT1_LLSTAT 0x0004#define PHSTAT1_JBSTAT 0x0002// ENC28J60 PHY PHCON2 Register Bit Definitions#define PHCON2_FRCLINK 0x4000#define PHCON2_TXDIS 0x2000#define PHCON2_JABBER 0x0400#define PHCON2_HDLDIS 0x0100// ENC28J60 Packet Control Byte Bit Definitions#define PKTCTRL_PHUGEEN 0x08#define PKTCTRL_PPADEN 0x04#define PKTCTRL_PCRCEN 0x02#define PKTCTRL_POVERRIDE 0x01// SPI operation codes#define ENC28J60_READ_CTRL_REG 0x00#define ENC28J60_READ_BUF_MEM 0x3A#define ENC28J60_WRITE_CTRL_REG 0x40#define ENC28J60_WRITE_BUF_MEM 0x7A#define ENC28J60_BIT_FIELD_SET 0x80#define ENC28J60_BIT_FIELD_CLR 0xA0#define ENC28J60_SOFT_RESET 0xFF// The RXSTART_INIT should be zero. See Rev. B4 Silicon Errata// buffer boundaries applied to internal 8K ram// the entire available packet buffer space is allocated//// start with recbuf at 0/#define RXSTART_INIT 0x0// receive buffer end#define RXSTOP_INIT (0x1FFF-1518-1)// start TX buffer at 0x1FFF-0x0600, pace for one full ethernet frame (0~1518 bytes)#define TXSTART_INIT (0x1FFF-1518)// stp TX buffer at end of mem#define TXSTOP_INIT 0x1FFF// max frame length which the conroller will accept:#define MAX_FRAMELEN 1518 // (note: maximum ethernet frame length would be 1518)////////////////////////////////////////////////////////////////////////////////////////////////////////////////void ENC28J60_Reset(void);u8 ENC28J60_Read_Op(u8 op,u8 addr);void ENC28J60_Write_Op(u8 op,u8 addr,u8 data);void ENC28J60_Read_Buf(u32 len,u8* data);void ENC28J60_Write_Buf(u32 len,u8* data);void ENC28J60_Set_Bank(u8 bank);u8 ENC28J60_Read(u8 addr);void ENC28J60_Write(u8 addr,u8 data);void ENC28J60_PHY_Write(u8 addr,u32 data);u8 ENC28J60_Init(u8* macaddr);u8 ENC28J60_Get_EREVID(void);void ENC28J60_Packet_Send(u32 len,u8* packet);u32 ENC28J60_Packet_Receive(u32 maxlen,u8* packet); #endif
边栏推荐
- ADB common commands
- 首先看K一个难看的数字
- Redis的五种数据结构
- Blue Bridge Cup real question: one question with clear code, master three codes
- 【.NET CORE】 请求长度过长报错解决方案
- Prophet模型的简介以及案例分析
- 287. Find duplicates
- The third season of Baidu online AI competition is coming in midsummer, looking for you who love AI!
- 【中山大学】考研初试复试资料分享
- 使用block实现两个页面之间的传统价值观
猜你喜欢
[swoole series 2.1] run the swoole first
模板于泛型编程之declval
44 colleges and universities were selected! Publicity of distributed intelligent computing project list
Breadth first traversal of graph
Docker安装Redis
推荐好用的后台管理脚手架,人人开源
Why does wechat use SQLite to save chat records?
Blue Bridge Cup real question: one question with clear code, master three codes
Implementation of queue
Compilation Principle -- C language implementation of prediction table
随机推荐
10、 Process management
Ms-tct: INRIA & SBU proposed a multi-scale time transformer for motion detection. The effect is SOTA! Open source! (CVPR2022)...
2022暑期项目实训(三)
30 minutes to understand PCA principal component analysis
Coco2017 dataset usage (brief introduction)
Maixll-Dock 摄像头使用
Interview shock 62: what are the precautions for group by?
Use cpolar to build a business website (1)
[Sun Yat sen University] information sharing of postgraduate entrance examination and re examination
Reprint: defect detection technology of industrial components based on deep learning
Numerical analysis: least squares and ridge regression (pytoch Implementation)
Declval of template in generic programming
ADB common commands
Excel usage record
[Android] kotlin code writing standardization document
Transfer data to event object in wechat applet
Echart simple component packaging
Cocos2d Lua smaller and smaller sample memory game
Celery best practices
Some understandings of tree LSTM and DGL code implementation