当前位置:网站首页>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 .

img Click and drag to move edit

img Click and drag to move edit

img Click and drag to move edit

img Click and drag to move edit

img Click and drag to move edit

img Click and drag to move 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 :

  1. compatible IEEE802.3 Ethernet controller based on Protocol
  2. Integrate MAC and 10 BASE-T The physical layer
  3. Full duplex and half duplex modes are supported
  4. Programmable automatic retransmission in case of data conflict
  5. SPI Interface speed up to 10Mbps
  6. 8K Data receiving and sending dual ports RAM
  7. Internal for fast data movement DMA controller
  8. Configurable receive and send buffer size
  9. Two programmable LED Output
  10. belt 7 Two interrupt pins of an interrupt source
  11. TTL Level input
  12. 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 .

img Click and drag to move edit

img Click and drag to move 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()

img Click and drag to move 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();    }}

 Click and drag to move

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);}

 Click and drag to move

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
原网站

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061017417366.html