⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 较好的C51实现TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
// Copyright (c) 2002 Jim Brady
// Do not use commercially without author's permission
// Last revised August 2002
// Net MAIN.C
//
// 8051 Web Server project
// See Makefile for build notes 
// Written for Keil C51 V5.1 compiler, notes:
//   It uses big endian order, which is the same as the
//   network byte order, unlike x86 systems.
//   Use OPTIMIZE(2)or higher so that automatic variables get shared
//   between functions, to stay within the 256 bytes idata space
//---------------------------------------------------------------------------

#include <string.h>
//#include <stdlib.h>
#include "C8051f340.h"
#include "net.h"
//#include "eth.h"
#include "cp220x_reg.h"
#include "timer.h"
#include "analog.h"
#include "arp.h"
#include "tcp.h"
#include "http.h"
#include "ip.h"
MACADDRESS xdata MYMAC; 
sbit AB4_RST = P1^0;                        // Set P1.0 High

 

// Global variables
UINT volatile event_word;
char xdata text[20];  
UCHAR idata debug;
UCHAR idata rcve_buf_allocated;
#define LINK_ERROR  0x20
char xdata inbuf1[1500] _at_ 1000;
char xdata outbuf1[1500] _at_ 2500;

// This sets my hardware address to 00:01:02:03:04:05
UCHAR xdata my_hwaddr[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05}; 

// Hardware addr to send a broadcast
UCHAR code broadcast_hwaddr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// This sets my IP address to 192.168.0.10
ULONG code  my_ipaddr = 0xC0A8000AL;

// This sets my subnet mask to 255.255.255.0
ULONG code my_subnet = 0xFFFFFF00L;

// Set to 0 if no gateway is present on network
ULONG code gateway_ipaddr = 0;

//--------------------------------------------------------------------------
// Initialize the memory management routines
// Initialize variables declared in main
//--------------------------------------------------------------------------

unsigned int Count1msInc;
unsigned char Count1ms,Count10ms,Count1s;
unsigned char TimeSecond,TimeMinute;
unsigned char PHY_Init(void);
void MAC_Init(void);
UCHAR xdata * rcve_frame(void);
void eth_rcve(UCHAR xdata * inbuf);
void MAC_Write(unsigned char mac_reg_offset, unsigned int mac_reg_data);
void MAC_SetAddress(MACADDRESS* pMAC);
void CP220x_Send( UCHAR xdata * outbuf, UINT len);

void init_main(void)
{
	// Start the memory pool for incoming and outgoing Ethernet
	// frames at 1000, with length = 1500 bytes. Memory below 500
	// is used for program variables
//	init_mempool((void xdata *)1000, 1500);
	memset(text, 0, sizeof(text));
	event_word = 0;
	rcve_buf_allocated = FALSE;
	debug = FALSE;
}

void PORT_Init (void)
{
    // XBR0    = 0x01;                     // Enable UART on P0.4(TX) and P0.5(RX)    P0MDIN    = 0xFC;
    P0SKIP    = 0x03;

   XBR1    = 0x40;                     // Enable Crossbar and weak pull-ups   P0MDOUT |= 0x10;                    // Enable TX0 as push-pull output   P1MDOUT |= 0xC0;                    // /WR and /RD are push-pull   P1MDOUT |= 0x18;                    // AB4 LEDs are push-pull   P1MDOUT &= ~0x01;                   // /RST is open-drain
      
   // Configure External Memory Interface Pins to push-pull except for
   // P2.0 and P2.1 which are used for target board switches.
   P2MDOUT |= 0xFC;                    // ADDR[15:8]   P3MDOUT |= 0xFF;                    // ADDR[7:0]   P4MDOUT |= 0xFF;                    // DATA[7:0]
   
   // Set initial values of External Memory Interface Pins
   P1 = 0xFE;                          // /WR, /RD, are high, RESET is low
   P1 &= ~0x18;                        // LEDs off   P2 = 0xFF;                          // ADDR[15:8] initially high    P3 = 0xFF;                          // ADDR[7:0] initially high   P4 = 0xFF;                          // DATA[7:0] intially high
 EMI0CF = 0x1B;                      // non-muxed mode; split mode 
                                       // with bank select
  EMI0TC = 0xFF;                      // slowest timing (4-cycle MOVX)

   EMI0CN = 0x20;                      // Off-chip
}



void Timer0_Init (void)
{
   	CKCON|=0x8;
   	TMOD|=0x1;    	//16Bit

	Count10ms=10;
	Count1s=0;
   	TR0 = 0;                         	// STOP Timer0
   	TH0 = (-SYSCLK/1000/12) >> 8;    		// set Timer0 to overflow in 1ms
   	TL0 = -SYSCLK/1000/12;
   	TR0 = 1;   	// START Timer0
   	IE|= 0x2; 
}
void SYSCLK_Init (void)
{
    int i;

   OSCICN |= 0x03;                     // Configure internal oscillator for
                                       // its maximum frequency
  
   CLKMUL = 0x00;                      // Reset Clock Multiplier and select
                                       // internal oscillator as input source

   CLKMUL |= 0x80;                     // Enable the Clock Multiplier

   for(i = 0; i < 256; i++);           // Delay at least 5us
   
   CLKMUL |= 0xC0;                     // Initialize the Clock Multiplier
   
   while(!(CLKMUL & 0x20));            // Wait for MULRDY => 1
   
   RSTSRC = 0x06;                      // Enable missing clock detector
                                       // and VDD monitor
   
   FLSCL |= 0x10;                      // Set Flash Scale for 48MHz
   
   CLKSEL |= 0x03;                     // Select output of clock multiplier
                                       // as the system clock.
}
void Timer0_ISR (void) interrupt 1  //1ms
{
	TH0 = (-SYSCLK/1000/12) >> 8;  
   	TL0 = -SYSCLK/1000/12;
	if (Count1ms) Count1ms--;
	Count1msInc++;
	if (Count10ms) Count10ms--;
	else
	{
		Count10ms=10;    			//10ms
		if (Count1s) Count1s--;
		else
		{
			Count1s=100;			//1s
			TimeSecond++;
			if (TimeSecond>=60)
			{
				TimeSecond=0;		//1min
				TimeMinute++;
				if	(TimeMinute==60)	TimeMinute=0;
			}
		}
	}
}


void Delay1ms(unsigned char T)
{
	Count1ms=T;
	while (Count1ms);
}

  

void LightONOFF(bit b)
{
  b=1;
}

void CP220x_RST_Low(void);
	//加延时
 void   CP220x_RST_High(void);
void main (void)
{
	UINT  event_word_copy;
	UCHAR xdata * inbuf;
	unsigned char error_code;
//	unsigned int num_bytes;
          	
    PCA0MD &= ~0x40;                    // WDTE = 0 (clear watchdog timer
                                       // enable)


	SYSCLK_Init ();                     // initialize oscillator
	Timer0_Init();
	PORT_Init ();                       // initialize crossbar and GPIO
   
	init_timer2();
	init_main();
	init_tcp();
	init_http();
 	EA=1;
	init_adc();
	init_arp();
	//init_8019();
	CP220x_RST_Low();
	//加延时
	
   Delay1ms(200);
    CP220x_RST_High();
	
  
   Delay1ms(200);

    INT0EN = 0x03;                         
   INT1EN = 0x00;
   
   // Clear all Interrupt Flags by reading the self-clearing status registers                          
//   temp_char = INT0;                      
 //  temp_char = INT1;  
   error_code = PHY_Init();  
   Delay1ms(50);
   Delay1ms(50);
   MAC_Init();    
   Delay1ms(50);
   Delay1ms(50);
  
  	ET2 = 1;		            // Enable timer 2 interrupt
	  RXCN = RXCLEAR;
      EA  =  1;

	  Delay1ms(50);
	  Delay1ms(50);
	  Delay1ms(50);
	  Delay1ms(50);
   Delay1ms(50);
    IP        = 0x01;

	   	
   // The code below is a priority based RTOS.  The event
   // handlers are in priority order - highest priority first.
	while (1)
   {
      // Query CS8900A to see if Ethernet frame has arrived
      // If so, set EVENT_ETH_ARRIVED bit in event_word
     // query_8019();
	/* 12.2. Reading a Packet Using the Autoread Interface
Once reset initialization is complete (Section 6.2 on page 18) and the receive buffer, filter, and hash table (Section
12.4) are initialized, the CP2200/1 is ready to receive Ethernet packets. After receiving notification of a new packet,
the following procedure can be used to read the packet:
Step 1: Read RXVALID (CPINFOH.7) and RXOK (CPINFOL.7) to check if the current packet was received
correctly. The host processor may optionally use the packet starting address CPADDR to read
specific bytes in the packet and determine whether to copy or skip the current packet. The random
access method described in Section 7.1 on page 23 can be used to access the buffer.
Step 2: If RXVALID or RXOK is 0, or to skip the packet, write a ‘1’ to RXSKIP (RXCN.1).
If RXVALID and RXOK are 1, read the length of the current packet from CPLENH:CPLENL.
Step 3: Read the entire packet, one byte at a time, by reading RXAUTORD.
Step 4: If the entire packet was read, write a ‘1’ to RXCLRV (RXCN.2).
If there are any unread bytes remaining in the current buffer, write a ‘1’ to RXSKIP (RXCN.1).*/
	  if(CPINFOH & RXVALID)  //CPINFOH的第7位 
      event_word |= EVENT_ETH_ARRIVED;
      // Use a copy of event word to avoid interference
      // with interrupts
		event_word_copy = event_word;
		EA = 1;
      
      // See if an Ethernet frame has arrived      
      if (event_word_copy & EVENT_ETH_ARRIVED)
      {
         EA = 0;
         event_word &= (~EVENT_ETH_ARRIVED);
         EA = 1;
         
         // Allocate a buffer and read frame from CS8900A
	//	 inbuf = (UCHAR xdata *)malloc(1000);
	//	 num_bytes = CP220x_Receive(inbuf, sizeof(inbuf));
         inbuf = rcve_frame();
           if (inbuf != NULL)
         {
            // Process the received Ethernet frame 
            eth_rcve(inbuf); 
         
            // If the memory allocated for the rcve message has
            // not already been freed then free it now
            if (rcve_buf_allocated)
            {
//               free(inbuf);
               rcve_buf_allocated = FALSE;
            }
         }
          
         
          
       
      }
      
      // See if TCP retransmit timer has expired            	       
      else if (event_word_copy & EVENT_TCP_RETRANSMIT)
      {
         event_word &= (~EVENT_TCP_RETRANSMIT);
         EA = 1;
         tcp_retransmit();
 		}

      // See if TCP inactivity timer has expired
      else if (event_word_copy & EVENT_TCP_INACTIVITY)
      {
         event_word &= (~EVENT_TCP_INACTIVITY);
         EA = 1;
         tcp_inactivity();
 		}

      // See if ARP retransmit timer has expired
 		else if (event_word_copy & EVENT_ARP_RETRANSMIT)
      {
         event_word &= (~EVENT_ARP_RETRANSMIT);
         EA = 1;
         arp_retransmit();
		}

      // See if it is time to age the ARP cache
      else if (event_word_copy & EVENT_AGE_ARP_CACHE)
      {
         event_word &= (~EVENT_AGE_ARP_CACHE);
			EA = 1;
         age_arp_cache();
		}

		// See if it is time to read the analog inputs
		else if (event_word_copy & EVENT_READ_ANALOG)
      {
         event_word &= (~EVENT_READ_ANALOG);
         EA = 1;
			// Read one of the 3 analog inputs each time
			read_analog_inputs();
      }

		// See if an RS232 message has arrived.  It is
      // not handled - RS232 is used for sending only
		else if (event_word_copy & EVENT_RS232_ARRIVED)
      {
         event_word &= (~EVENT_RS232_ARRIVED);
         EA = 1;
      }
   }
}

void CP220x_RST_Low(void)
{
   AB4_RST = 0;                        // Set P1.0 Low
}

void CP220x_RST_High(void)
{
 AB4_RST = 1;                        // Set P1.0 High

   while(!AB4_RST);
}

unsigned char PHY_Init()
{
   unsigned char temp_char;
   unsigned char retval = 0;
   
   //--------------------------------------------------------------------------
   // Auto-Negotiation Synchronization (Section 15.2 of CP220x Datasheet)
   //--------------------------------------------------------------------------

   // Step 1: Disable the PHY
   PHYCN = 0x00;  
   
   // Step 2: Enable the PHY with link integrity test and auto-negotiation 
   // turned off
      
      // A. Disable the Transmitter Power Save Option and Configure Options
      TXPWR = 0x80;
      PHYCF = ( SMSQ | JABBER | ADPAUSE | AUTOPOL );

      // B. Enable the Physical Layer
      PHYCN = PHYEN;
Delay1ms(200);
   Delay1ms(200);
   Delay1ms(200);
      // C. Wait for the physical layer to power up
     // wait_ms(10);

      // D. Enable the Transmitter and Receiver
      PHYCN = ( PHYEN | TXEN | RXEN );
   
   // Step 3: Poll the Wake-on-Lan Interrupt
      Delay1ms(200);
  
      // A. Clear Interrupt Flags

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -