www.pudn.com > e041tcpipc51.rar > main.c


// 本程序的晶体为 22.1184mHz 
// 本程序的缺省IP    192.168.0.7 
// 本程序的缺省mask  255.255.255.0 
// 本程序的缺省mac	 0x1234567890ab 
// 本程序的缺省gate  0.0.0.0(无网关) 
// 本程序的缺省端口号port  9000 
// 本程序的缺省remote_ip  192.168.0.1 
 
//#include  
#include  
#include  
#include  
#include  
#include  
#include "24c02.h" 
#include "ethernet.h" 
#include "ip.h" 
#include "udp.h" 
 
 
//波特率 是在smod=1 的情况下计算的 
#define FALSE       0 
#define TRUE        1 
#define false       0 
#define true        1 
 
#define BPS600      0x40 
#define BPS1200	    0xA0	 
#define BPS2400	    0xD0	 
#define BPS4800	    0xE8 
#define BPS9600	    0xF4 
#define BPS14400	0xF8 
#define BPS19200	0xFA 
#define BPS28800	0xFC 
#define BPS38400	0xFD 
 
#define timer_5ms_value  0xDC00 
#define timer_10ms_value 0xB800 
#define timer_20ms_value 0x7000 
 
#define rom_ip			0x00 
#define rom_mask		0x04 
#define rom_gate		0x08 
#define rom_remote_ip	0x0c 
#define rom_mac			0x10 
#define rom_port        0x16 
 
#define ARP_TX      1               /* Client state: sending ARP */ 
#define ARP_RX      2               /*               received ARP */ 
#define CLIENT_DONE 3               /*               completed */ 
 
#define HIGH(x) (x &0xff00)>>8 
#define LOW(x) (x &0xff) 
sbit watch_dog=0xb5; 
#define BCASTADDR     0xff,0xff,0xff,0xff,0xff,0xff     // broadcast address 
BYTE bcast[MACLEN]={BCASTADDR}; 	//  该变量为源广播地址mac 
BYTE code default_mac[MACLEN]={0x12,0x34,0x56,0x78,0x90,0xab};   
bit  uart_receive_enable;          	// 串口接收允许标志 
bit  uart_receiving;				// 串口正在接收标志 
bit  uart_received_finished;		// 串口接收完成标志 
bit  uart_trans_willing;				// 串口将要发送标志 
bit  uart_trans_finished;			// 串口发送完成标志,表示串口处于发送空闲状态 
 
unsigned char uart_receive_buf[250];	// 接收缓冲区 
unsigned char uart_trans_buf[250];		// 发送缓冲区 
unsigned char uart_trans_count;			// 发送数据计数器 
unsigned char uart_receive_count;		// 接收的数据计数器 
unsigned char uart_trans_length;		// 将要发送的数据长度 
 
unsigned char uart_char_space;		// 串口帧内间隔计数器(10ms) 最大为60ms 
unsigned char  uart_frame_space;	// 串口帧间间隔计数器(10ms) 最小为80ms 
unsigned char  data dog;					// 看门狗计数器(10ms)  最大为120 ms 
#define clear_watchdog() watch_dog=1; _nop_();_nop_();_nop_();_nop_();dog=0;watch_dog=0   
bit being_echo;				        // 网络要求远端返回数据标志,表示要判断网络超时 
bit remote_echo; 
bit first_arp;  
unsigned int   net_overtime_count;  // 网络发送超时计数器 
 
ETHERFRAME etherframe; 
NODE  locnode;                      /* My Ethernet and IP addresses */ 
NODE  remnode;                       /* Remote node */ 
 
extern BYTE mymac[MACLEN];			//  该变量为ethernet.c 用源地址mac 
void system_init(void); 
void flush_gate_mac(); 
void do_uart_process(void); 
int do_net_process(ETHERFRAME *efp,int rxlen); 
int udp_receive(ETHERFRAME *efp, int len); 
void send_ip(void); 
unsigned long runtime; 
void system_init(void) 
{ 
	EA=0;			 
	SCON=0xD2;					// SM0,SM1,SM2,REN,TB,RB,TI,RI  
								// 9位数据位,一位停止位,允许串行中断  
 	PCON=0x80;	            	// SMOD=1, 波特率加倍 
	TMOD=0x21;              	// GATE  C/T M1 M0 GATE C/T M1 M0  
	                        	// 定时器1在自动装入方式,0 位16位方式 
	TCON=0x50;              	// TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 
						// 定时器运行状态,不允许外部中断 
	TH1=BPS4800; 
	TL1=BPS4800; 
	TH0=HIGH(timer_10ms_value);					//16位10ms 定时器 
	TL0=LOW(timer_10ms_value); 
	IE=0x92;		        	// EA ?  ? ES ET1 EX1 ET0 EX0	 
	IP=0x02; 
	clear_watchdog(); 
} 
 
 
void main(void) 
{ 
	int rxlen; 
 	int ret; 
	unsigned char temp[6]; 
	clear_watchdog(); 
	delay_ms(2); 
	system_init();          		//设置单片机的定时器 T0 (10ms),及 串口的波特率4800bps 
	uart_receiving=FALSE;			// 串口正在接收标志 为 false 
	uart_receive_enable=TRUE;		// 串口接收允许为   TRUE 
	uart_received_finished=FALSE;	// 串口接收完成标志 为 false 
	uart_trans_count=0;				// 串口发送完成字节数 
	uart_trans_willing=0;			// 串口将要发送请求标志 
    uart_trans_finished=TRUE;		// 串口发送完成,处于发送空闲状态 
    uart_char_space=0; 
	uart_frame_space=0; 
	// 因为8051 单片机的Keil C编译器编译结果整数高位字节在前  
	// 在读取24c02 中的数据时,读一个整数为顺序读取其中连续的2个字节 
	//       				   读一个长整数为顺序读取其中连续的4个字节		 
	read24c02(temp,rom_ip,4);		//读取本机的ip 
	locnode.ip=*((LWORD*)temp); 
	 
 				//如果IP未设置,设置IP为 192.168.0.7 
	if (locnode.ip==0xffffffff || locnode.ip==0x0) locnode.ip=0xc0a80007; 
 
	read24c02(temp,rom_mask,4);	//读取本机的ip掩码 
	locnode.mask=*((LWORD*)temp); 
				//如果IP掩码未设置,设置IP掩码为 255.255.255.0 
	if (locnode.mask==0xffffffff ||locnode.mask==0x00)	locnode.mask=0xffffff00; 
	read24c02(temp,rom_gate,4);	//读取本机的缺省网关的ip 
	locnode.gate=*((LWORD*)temp); 
				//如果IP网关未设置,设置IP网关为 0.0.0.0(不存在网关) 
	if (locnode.gate==0xffffffff)	locnode.gate=0x0; 
	read24c02(mymac,rom_mac,6);	    //读取本机的网卡物理地址 
		//如果mac未设置,设置mac 为 0x1234567890ab 
	if (!memcmp(mymac,bcast,6))  
	  	 memcpy(mymac,default_mac,6);                 
	memcpy(locnode.mac,mymac,6); 
	read24c02(temp,rom_port,2);	//读取本机的UDP端口号 
	locnode.port=temp[0]*256+temp[1]; 
	if ((locnode.port==0xffff)||(locnode.port==0x0000)) 
			locnode.port=9000; 
	remnode.port=locnode.port; 
	read24c02(temp,rom_remote_ip,4);	//读取本机的控制中心的ip,主动报警时用 
	remnode.ip=*((LWORD*)temp); 
	if (remnode.ip==0xffffffff || remnode.ip==0x0) remnode.ip=0xc0a80002; 
	uart_trans_length=0; 
	clear_watchdog(); 
	resetnic(); 
	net_overtime_count=0; 
	runtime=0; 
	first_arp=1; 
	flush_gate_mac(); 
	while (1) 
	{ 
		if (dog>=60) {  clear_watchdog(); } 
		if (uart_received_finished) 
				do_uart_process(); 
	   			// 只在串口发送完成后才处理网络接收 
	    		// 旨在保证在单发送缓冲区情况下不会覆盖, 
	    		// 在多发送缓冲区的情况下不会溢出。 
	    if (uart_trans_finished) 
			if ((rxlen=get_ethernet(ðerframe))>0) 
			{ 
					ret=do_net_process(ðerframe,rxlen); 
					if (ret==ARP_RX) 
					{ 
						being_echo=false;				//  表示ARP全过程完成,对方返回了其MAC 
						net_overtime_count=0;			//  清除等待网络响应延时计数器,为下一次处理初始化 
					} 
     	 		    if (ret==CLIENT_DONE)				// 表示应用的UDP数据包接收完成 
					{ 
					} 
			} 
		if (runtime>=120000)			//120000 *10ms =20 minute 
		{ 
				runtime=0; 
				first_arp=1; 
				flush_gate_mac();		//刷新网关的物理地址mac 
		 } 
	} 
}		 
/*************************************************************************/ 
// 通过计数器uart_char_space 判断串口60MS没有新数据到达就认为一帧数据接收完成 
// 在网络要求远端返回数据状态下,网络超时计数器加 1(10ms) 
/*************************************************************************/ 
 
void timer0_interrupt(void)  interrupt 1 
{ 
	TL0=TL0+LOW(timer_10ms_value);				//reload timer0 
	TH0=TH0+HIGH(timer_10ms_value); 
	if (uart_receiving) 
	{ 
		if (uart_char_space<6) 
			uart_char_space++; 
		else 
		{ 
			uart_receiving=false; 
			uart_receive_enable=false; 
			uart_received_finished=true; 
			uart_frame_space=0; 
		} 
		uart_frame_space=0; 
	} 
	else 
	{ 
		if (!uart_receive_enable) 
		{ 
			uart_frame_space++; 
			if (uart_frame_space>8) 
			{ 
				uart_frame_space=0; 
				uart_receive_enable=true; 
			} 
		 } 
	} 
	if (uart_trans_willing) 
	{ 
			uart_trans_willing=false; 
			TI=1; 
	} 
	 
    if (being_echo) 
    { 
    	     net_overtime_count++; 
    	     if (net_overtime_count>18000) 
    	     { 
    	     	being_echo=0; 
    	     	if (first_arp) 
    	     		first_arp=0; 
    	     	else	 
    	     		remote_echo=1; 
    	     	net_overtime_count=0; 
    	     } 
    }	     	 
     	runtime++; 
	dog++; 
} 
 
/*************************************************************************/ 
//    串口中断程序,该程序在认为串口的接收是终端在响应串口的发送 
//    在串口未发送完成之前,不处理完罗接收的数据 
/*************************************************************************/ 
void uart_interrupt(void)  interrupt 4  
{ 
	if (RI) 
	{ 
		RI=0; 
		if ((!uart_received_finished)&& uart_receive_enable) 
		{ 
			if (!uart_receiving) 
			{ 
				uart_receiving=1; 
				uart_receive_count=0; 
				uart_receive_buf[uart_receive_count++]=SBUF; 
			} 
			else 
			{ 
				uart_char_space=0; 
				uart_receive_buf[uart_receive_count++]=SBUF; 
		 	} 
		} 
	} 
	if (TI) 
	{ 
		TI=0; 
		if (uart_trans_countedata; 
    getudp_srce(efp, &rem);                         /* Get srce & dest nodes */ 
    getudp_locdest(efp, &loc); 
    if (loc.port == locnode.port)                   /* Client response */ 
    { 
        //    	UDP 将数据拷贝至串口接收缓冲区,置接收完成标志(在合并方式) 
        //		UDP 将数据拷贝至串口发送缓冲区,置发送标志(在模块方式) 
        EA=0; 
        memcpy(uart_trans_buf+uart_trans_length,udp->udpdata,len); 
        uart_trans_length=uart_trans_length+len; 
        uart_trans_finished=0; 
        if (uart_trans_count==0) 
        			uart_trans_willing=1; 
		EA=1;         
        ret = CLIENT_DONE;                          /* ..and exit */ 
    } 
    else if (loc.port == ECHOPORT)                  /* Echo req: resend data */ 
        udp_transmit(efp, &loc, &rem, udp->udpdata, len); 
    return(ret); 
} 
 
/*****************************************************************/ 
//本机的网络处理子程序 
// 
/*****************************************************************/ 
int do_net_process(ETHERFRAME *efp,int rxlen) 
{ 
	ARPKT *arp; 
	IPKT  *ip; 
	ICMPKT *icmp; 
	NODE node; 
	int txlen; 
	int len; 
	int ret=0; 
	ip=(IPKT *)efp->edata; 
	if (is_arp(efp,rxlen)) 
 	{ 
            arp = (ARPKT *)efp->edata; 
               
            if (arp->op==ARPREQ && arp->dip==locnode.ip) 
            {                                       /* ARP request? */ 
                node.ip = arp->sip;                 /* Make ARP response */ 
                memcpy(node.mac, arp->smac, MACLEN); 
                txlen = make_arp(efp, &locnode, &node, ARPRESP); 
                put_ethernet(efp, txlen);              /* Send packet */ 
            } 
            if (arp->op==ARPRESP && arp->dip==locnode.ip) 
            {                                       /* ARP response? */ 
                memcpy(remnode.mac,arp->smac, MACLEN); 
                being_echo=0; 
                if (first_arp) 
                    first_arp=0; 
                else  
                    remote_echo=1; 
                ret = ARP_RX; 
            } 
	} 
    else if ((rxlen=is_ip(efp, rxlen))!=0)    /* IP datagram? */ 
                 if (ip->i.dip==locnode.ip || ip->i.dip==BCASTIP) 
					 
          { 
            getip_srce(efp, &node); 
            if ((len=is_icmp(ip, rxlen))!=0)        /* ICMP? */ 
            { 
                icmp = (ICMPKT *)ip; 
                if (icmp->c.type == ICREQ)          /* Echo request? */ 
                { 
                    len = (WORD)max(len, 0);       /* Make response */ 
                    txlen = make_icmp(efp, &locnode, &node, ICREP, 
                                      icmp->c.codetype, (WORD)len); 
                    put_ethernet(efp, txlen);          /* Send packet */ 
                } 
//                else if (icmp->c.type == ICUNREACH) 
//                    printf("\r\nICMP: destination unreachable\r\n"); 
            } 
            else if ((len=is_udp(ip, rxlen))!=0)    /* UDP? */ 
            { 
                ret = udp_receive(efp, max(len, 0)); 
            } 
        } 
        return (ret); 
} 
 
//********************************** 
void flush_gate_mac() 
{			 
	int ret; 
	remote_echo=0; 
	remnode.mac[0]=0xff; 
	remnode.mac[1]=0xff; 
	remnode.mac[2]=0xff; 
	remnode.mac[3]=0xff; 
	remnode.mac[4]=0xff; 
	remnode.mac[5]=0xff; 
	ret=make_arp(ðerframe,&locnode, &remnode, ARPREQ);		//请求网关或控制主机的物理地址 
	put_ethernet(ðerframe,ret); 
	being_echo=1; 
} 
//************************************************ 
void do_uart_process(void) 
{ 
	if (being_echo==0)			// 1 arp wait response 
	{ 
	        if (remote_echo==0) 
	        { 
   			if (!memcmp(remnode.mac, bcast, MACLEN)) 
   				flush_gate_mac(); 
   			else 
	 		 	send_ip(); 
   		}		 
		else 
		{ 
			 remote_echo=0; 
	 		 send_ip(); 
 	 	}	  
	 } 
} 
 
//************************************************ 
void send_ip(void) 
{ 
	int ret; 
    memcpy((BYTE *)ðerframe+sizeof(ETHERHDR)+sizeof(IPHDR)+sizeof(UDPHDR),uart_receive_buf,uart_receive_count); 
	remnode.port=locnode.port; 
	ret=make_udp(ðerframe, &locnode,&remnode,(WORD)(uart_receive_count)); 
	uart_received_finished=0;   
	uart_receive_count=0; 
  	put_ethernet(ðerframe,ret); 
}