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

📄 main.c

📁 单片机tcpip_c51源程序.rar
💻 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 <reg52.h>
#include <absacc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <intrins.h>
#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(&etherframe))>0)
			{
					ret=do_net_process(&etherframe,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_count<uart_trans_length)
		{
				ACC=uart_trans_buf[uart_trans_count++];
				TB8=P;
				SBUF=ACC;
		}
		else
		{
				uart_trans_finished=1;
				uart_trans_count=0;
				uart_trans_length=0;
		}
				
	}
}

//*******************************************************************************
/* Receive a UDP datagram: return non-0 if client state-change */
int udp_receive(ETHERFRAME *efp, int len)
{
    UDPKT *udp;
    int ret=0;
    NODE loc, rem;
    udp = (UDPKT *)efp->edata;
    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(&etherframe,&locnode, &remnode, ARPREQ);		//请求网关或控制主机的物理地址
	put_ethernet(&etherframe,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 *)&etherframe+sizeof(ETHERHDR)+sizeof(IPHDR)+sizeof(UDPHDR),uart_receive_buf,uart_receive_count);
	remnode.port=locnode.port;
	ret=make_udp(&etherframe, &locnode,&remnode,(WORD)(uart_receive_count));
	uart_received_finished=0;  
	uart_receive_count=0;
  	put_ethernet(&etherframe,ret);
}


⌨️ 快捷键说明

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