📄 main.c
字号:
//---------------------------------------------------------------------------
// 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 + -