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_count 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(ð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); }