📄 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 <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(ð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<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(ð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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -