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

📄 main.c

📁 这是一个用单片机控制网卡传输的程序,集成了TCP/IP协议,使用硬件为89C51+RTL8019,另外传输另一端是计算机串口,可以方便的实现数据验证
💻 C
📖 第 1 页 / 共 4 页
字号:
    create_ip_packet(datalength, ip_address >> 16, ip_address&0xffff, 17);
}

//40//
void process_udp_command()
{
    if(udp_count > 0)
    {
        udp_count--;
        if(udp_count > 0)
        {
            if(ping_ip_address_ttl > 0)
            {
            //表示ip地址已经解析
                  udp_request(ping_ip_address.dwords ,port.word);
                 udp_count=0;
            }
            else
            {
            //解析ip地址
                arp_request(ping_ip_address.dwords);
            }
            if(ping_ip_address.dwords==my_ip_address.dwords)
            {
            //ping的是自己的ip地址
                 send_string("\r\nCannot connect self");
                 udp_count=0;
            }
        }
    }
}
/*//41//
void create_ethernet_packet()
{


    ...
}
*/
//42//
void serial_init()
{
//scon
//SM0  SM1   SM2   REN    TB8   RB8   TI   RI

TMOD=0x20;//time1  mode2
TL1=0xf4;//bps:9600
TH1=0xf4;
TR1=1;
PCON=0x00;
SCON=0x50;//MODE1  start receive
TI=1;
}

//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

void readmyipadd()
{my_ip_address.bytes[0]=Myipaddr[0];
 my_ip_address.bytes[1]=Myipaddr[1];
 my_ip_address.bytes[2]=Myipaddr[2];
 my_ip_address.bytes[3]=Myipaddr[3];
 }
void readnetgate()
{gateway_ip_address.bytes[0]=MyNetgate[0];
  gateway_ip_address.bytes[1]=MyNetgate[1];
  gateway_ip_address.bytes[2]=MyNetgate[2];
  gateway_ip_address.bytes[3]=MyNetgate[3];

}
void readmask()
{
mask_ip_address.bytes[0]=MyMaskip[0];
mask_ip_address.bytes[1]=MyMaskip[1];
mask_ip_address.bytes[2]=MyMaskip[2];
mask_ip_address.bytes[3]=MyMaskip[3];
}
//1//
void write_register(unsigned char address_offset,unsigned char value)
{

    unsigned char xdata* regbasetemp = R8019as_regbase + address_offset;
    bit    tempbit;
    tempbit         = p2_7;
    p2_7            = 1;
    *regbasetemp     = value;
    p2_7            = tempbit;
}

//2//
unsigned char read_register(unsigned char addr)
{
    unsigned char temp;
     unsigned char xdata* regbasetemp = R8019as_regbase + addr;
    bit tempbit;
    tempbit   = p2_7;
    p2_7 = 1;
    temp = *regbasetemp;
    p2_7 = tempbit;
    return(temp);
}

//3//
void write_dma_port(unsigned char value)
{
    bit tempbit;
    tempbit         = p2_7;
    p2_7            = 1;
    R8019as_reg16     = value;
    p2_7            = tempbit;
}

//4//
unsigned char read_dma_port()
{
    unsigned char temp;
    bit    tempbit;
    tempbit    = p2_7;
    p2_7    = 1;
    temp    = R8019as_reg16;
    p2_7    = tempbit;
    return(temp);
}

//5//
void rtl8019as_page(unsigned char pagenumber)
{
    unsigned char data temp;
    bit tempbit;
    tempbit    = p2_7;
    p2_7    = 1;
    temp     = R8019as_reg00;
    p2_7    = 0;
    temp    = temp & 0x3B; //注意不是0x3F ,TXP位在平时一定要置为0.
    pagenumber = pagenumber << 6;
    temp    = temp | pagenumber;
    p2_7    = 1;
    R8019as_reg00 =    temp;
    p2_7    = tempbit;
}

//加一函数(从9364中读物理地址和配置信息)
//6//
void readmynodeid_self()
{
    my_ethernet_address.bytes[0]= NetCardNode[0];//52:54:AB:35:48:8A
    my_ethernet_address.bytes[1]= NetCardNode[1];
    my_ethernet_address.bytes[2]= NetCardNode[2];
    my_ethernet_address.bytes[3]= NetCardNode[3];
    my_ethernet_address.bytes[4]= NetCardNode[4];
    my_ethernet_address.bytes[5]= NetCardNode[5];
}

//7//
void writemynodeid()
{
    unsigned char wtemp1;
    bit tempbit;
    tempbit    = p2_7;

    rtl8019as_page(1);
    p2_7    = 0;
    wtemp1    = my_ethernet_address.bytes[0];
    p2_7    = 1;
    R8019as_reg01 = wtemp1;//PAR0,实际地址寄存器:这些寄存器包括以太网节点地址且用来对目标地址数据包进行比较来确定接收或者拒绝接收。
    p2_7=0;
    wtemp1    = my_ethernet_address.bytes[1];
    p2_7    = 1;
    R8019as_reg02 = wtemp1;//PAR1

    p2_7    = 0;
    wtemp1    = my_ethernet_address.bytes[2];
    p2_7    = 1;
    R8019as_reg03 =wtemp1;//PAR2

    p2_7    = 0;
    wtemp1    = my_ethernet_address.bytes[3];
    p2_7    = 1;
    R8019as_reg04 = wtemp1;//PAR3

    p2_7    = 0;
    wtemp1    = my_ethernet_address.bytes[4];
    p2_7    = 1;
    R8019as_reg05 = wtemp1;//PAR4

    p2_7    =0;
    wtemp1    = my_ethernet_address.bytes[5];
    p2_7    = 1;
    R8019as_reg06 = wtemp1;//PAR5

    p2_7    = tempbit;
}

//8//
void send_packet(unsigned int length)
{
//发送一个数据包的命令,长度最小为60字节,最大1514字节需要发送的数据包要先存放在txdnet缓冲区
    unsigned char i;
    unsigned int ii;

    rtl8019as_page(0);
    if(length < 60)
        length = 60;
    for(i = 0; i < 3; i++)
        txdnet.etherframe.sourcenodeid[i] = my_ethernet_address.words[i];
    txd_buffer_select    = !txd_buffer_select;
    if(txd_buffer_select)
    {
        write_register(remote_start_address_register1, 0x40) ;//8019发送buffer第一页
    }
    else
    {
        write_register(remote_start_address_register1, 0x46) ;//8019发送buffer第二页
    }
    write_register(remote_start_address_register0, 0x00); //按页存储
    write_register(remote_byte_count_register1, length >> 8);//read count high,远程DMA(单片机端)将要发送的字节数
    write_register(remote_byte_count_register0, length & 0xff);//read count low;
    write_register(command_register, 0x12);//remote write dma, page0,激活8019传送数据

    //for(ii = 4; ii < length+4; ii++)
   for(ii = 0; ii < length; ii++)
   {
        write_dma_port(txdnet.bytes.bytebuf[ii]);//数据传送:单片机发送缓存---〉8019register_16(远程DMA端口)

    }

// 以下3句为中止dma的操作,可以不要
    write_register(remote_byte_count_register1, 0x00);//read count high   中止DMA操作
    write_register(remote_byte_count_register0, 0x00);//read count low;
    write_register(command_register, 0x22);//complete dma page 0

           //==============

    for(i = 0; i < 16; i++)//最多重发16次
    {

        //write_register(command_register,0x3e);
        write_register(command_register,0x1e);//select send packet

          for(ii = 0; ii < 1000; ii++)
        {//检查txp为是否为低
            if((read_register(command_register)&0x04) == 0)
                break;
        }
        if((read_register(transmit_status_register)&0x01)!=0)//表示发送成功
            break;
    }
    write_register(interrupt_status_register,0xff);
    /*if(txd_buffer_select)
        write_register(transmit_page_start_register, 0x40);//txd packet start;
    else
        write_register(transmit_page_start_register, 0x46);//txd packet start;

    write_register(transmit_byte_count_register1, length >> 8);//high byte counter
    write_register(transmit_byte_count_register0, length & 0xff);//low byte counter
    write_register(interrupt_status_register, 0xff);
    write_register(command_register, 0x3e);//to sendpacket;
    */
}

//9//
void rtl8019as_reset()
{
    unsigned char temp;
    bit    tempbit;
    tempbit = p2_7;
    p2_7     = 1;
    temp    = R8019as_reg31;//读网卡的复位端口
    R8019as_reg31 = temp; //写网卡的复位端口
    p2_7    = tempbit;
}

//10//
void rtl8019as_init()//i write it myself
{
    bit tempbit;
    tempbit    = p2_7;
    p2_7    = 1;
    R8019as_reg00    = 0x21; //选择页0的寄存器,网卡停止运行,因为还没有初始化。

//   R8019as_reg07=0xff;//清除中断寄存器 ISR

    R8019as_reg01    = 0x4c; //寄存器Pstart (receive buffer)
    R8019as_reg02    = 0x80; //Pstop
    R8019as_reg03    = 0x4c; //BNRY
    R8019as_reg04    = 0x45; //TPSR
    R8019as_reg12    = 0xcc; //RCR
//  R8019as-reg12=0xca;//广播包不接受,少于60字节的接受
    R8019as_reg13    = 0xe0; //TCR
    R8019as_reg14    = 0xc8; //DCR 数据配置寄存器 8位数据dma
    R8019as_reg15    = 0x00; //IMR disable all interrupt
    p2_7    = 0;

    rtl8019as_page(1); //选择页1的寄存器

    p2_7    = 1;
    R8019as_reg07    = 0x4d; //CURR
    R8019as_reg08    = 0x00; //MAR0  清除多播地址
    R8019as_reg09    = 0x00; //MAR1
    R8019as_reg10    = 0x00; //MAR2
    R8019as_reg11    = 0x00; //MAR3
    R8019as_reg12    = 0x00; //MAR4
    R8019as_reg13    = 0x00; //MAR5
    R8019as_reg14    = 0x00; //MAR6
    R8019as_reg15    = 0x00; //MAR7
    R8019as_reg00    = 0x22;//选择页0寄存器,网卡执行命令。
    p2_7    = 0;

//    readmynodeid_self();    //不使用93c46
//    writemynodeid();
    p2_7    = tempbit;
}

//11//
unsigned char check_new_packet()
{
//如果收到一个有效的数据包,返回1,否则返回0
    unsigned char i;
    unsigned int ii;

    rtl8019as_page(0);
    bnry    = read_register(boundary_register);//bnry page have read 读页指针
    rtl8019as_page(1);
    curr    = read_register(current_page_register);//curr writepoint 8019写页指针
    rtl8019as_page(0);
    if(curr == 0)
        return(0);//读的过程出错
    next_page    = bnry;
    bnry        = bnry+1;

    if(bnry > 0x7f)
        bnry    = 0x4c;
    if(bnry != curr)
//此时表示有新的数据包在缓冲区里
    {
        rtl8019as_page(0);
        //==============清除错误计数器,可以不做清除
        read_register(tally_counter0);  //page0 read
        read_register(tally_counter1);  //page0 read
        read_register(tally_counter2);  //page0 read
        //==============
        write_register(remote_start_address_register1, bnry);//read page address
        write_register(remote_start_address_register0, 0x00); //read page address
        write_register(remote_byte_count_register1, 0x00);//read head count 4+6+6+2=18
        write_register(remote_byte_count_register0, 18);//先读头部
        write_register(command_register, 0x0a);//read dma,数据发到单片机方向
        for(i = 0; i < 18; i++)
        {
            rxdnet.bytes.bytebuf[i] = read_dma_port();
        }
//以下3句为中止dma的操作,可以不要
        write_register(remote_byte_count_register1, 0x00);//read count high   中止DMA操作
        write_register(remote_byte_count_register0, 0x00);//read count low;
        write_register(command_register, 0x22);//complete dma page 0
            //==============
//将长度字段的高低字节掉转 使高字节在前
        i = rxdnet.bytes.bytebuf[3];
        rxdnet.bytes.bytebuf[3] = rxdnet.bytes.bytebuf[2];
        rxdnet.bytes.bytebuf[2] = i;

        rxdnet.etherframe.length = rxdnet.etherframe.length-4;//去掉4个字节的CRC

           //表示读入的数据包有效
        if(((rxdnet.bytes.bytebuf[0]&0x01)==0)||(rxdnet.bytes.bytebuf[1]>0x7f)||(rxdnet.bytes.bytebuf[1]<0x4c)||(rxdnet.bytes.bytebuf[2]>0x06))
        {
        //next_page_start错误或者长度错误,或者接收状态错误,将丢弃所有数据包
            rtl8019as_page(1);
            curr = read_register(current_page_register); //page1
            rtl8019as_page(0);//切换回page0
            bnry = curr -1;
            if(bnry < 0x4c)
                bnry = 0x7f;
            write_register(boundary_register, bnry); //write to bnry
            //===================下面这句清除中断状态可以不用
            write_register(interrupt_status_register, 0xff);
            return(0);
        }
        else
        {//表示数据包是完好的.读取剩下的数据
                //============
            if((rxdnet.etherframe.protocal == 0x0800) || (rxdnet.etherframe.protocal == 0x0806))
            { //协议为IP或ARP才接收

                write_register(remote_start_address_register1, bnry);//read page address high
                write_register(remote_start_address_register0, 4); //read page address low
                write_register(remote_byte_count_register1, rxdnet.etherframe.length >> 8);//read count high
                write_register(remote_byte_count_register0, rxdnet.etherframe.length & 0xff);//read count low;
                write_register(command_register, 0x0a);//read dma
                for(ii = 4; ii < rxdnet.etherframe.length + 4; ii++)
                {
                    rxdnet.bytes.bytebuf[ii] = read_dma_port();
                }//读回数据为除去crc字和头部四个字的包,但是头部没被覆盖,此时整个缓冲区为有效的完整包

                write_register(remote_byte_count_register1, 0x00);//read count high   中止DMA操作
                write_register(remote_byte_count_register0, 0x00);//read count low;
                write_register(command_register, 0x22);//dma complete  page0
            }
             //=========================================
            bnry = rxdnet.bytes.bytebuf[1]-1;//next page start-1
            if(bnry < 0x4c)
                bnry = 0x7f;
            write_register(boundary_register, bnry); //write to bnry
            write_register(interrupt_status_register,0xff);
            return(1);//have new packet
        }
    }
    return(0);
}


//12//
void do_93c46(unsigned char dataes)
{
//串行输入8位数据
//93c46 commond register:
// 7     6      5     4      3      2     1      0
//eem1   eem0   nc   nc      eecs   eeck  eedi   eedo
unsigned char count;
for(count=0;count<8;count++)
{
 if((dataes&0x80!)=0)
 //input 1
    R8019as_reg01=0x8a;//1000 1010  cs=1  ck=0  di=1
    R8019as_reg01=0x8e;//1000 1110  cs=1  ck=1  di=1
 else
 // input 0
  {R8019as_reg01=0x80;//1000 1010  cs=1  ck=0  di=0
   R8019as_reg01=0x8c;//1000 1110  cs=1  ck=1  di=0
  }
dataes=dataea<<1;
}
//13//
unsigned int read_93c46(unsigned char address)
{
//返回一个16位的数据;
//93c46 commond register:
// 7     6      5     4      3      2     1      0
//eem1   eem0   nc   nc      eecs   eeck  eedi   eedo

⌨️ 快捷键说明

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