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

📄 ethmod.c

📁 pic单片机实现的TCP/IP协议
💻 C
📖 第 1 页 / 共 3 页
字号:
{
   /*port 7 is the well-known echo port*/
   if(packet[UDP_destport] == 0x00 && packet[UDP_destport+1] ==0x07)
   {
      /*build the IP header*/
      setipaddrs();

      /*swap the UDP source and destination ports*/
      data_L = packet[UDP_srcport];
      packet[UDP_srcport] = packet[UDP_destport];
      packet[UDP_destport] = data_L;

      data_L = packet[UDP_srcport+1];
      packet[UDP_srcport+1] = packet[UDP_destport+1];
      packet[UDP_destport+1] = data_L;

      /*calculate the UDP checksum*/
      packet[UDP_cksum] = 0x00;
      packet[UDP_cksum+1] = 0x00;

      hdr_chksum =0;
      hdrlen = 0x08;
      addr = &packet[ip_srcaddr];
      cksum();
      hdr_chksum = hdr_chksum + packet[ip_proto];
      hdrlen = 0x02;
      addr = &packet[UDP_len];
      cksum();
      hdrlen = make16(packet[UDP_len],packet[UDP_len+1]);
      addr = &packet[UDP_srcport];
      cksum();
      chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
      packet[UDP_cksum] = make8(chksum16,1);
      packet[UDP_cksum+1] = make8(chksum16,0);

      /*echo the incoming data back to the VB program*/
      echo_packet();
   }

   /*buttons on the VB GUI are pointed towards port address 5000 decimal*/
   else if(packet[UDP_destport] == 0x13 && packet[UDP_destport+1] == 0x88);
	  {
      if(packet[UDP_data])
         /*received a 0x00 from the VB program*/
         bit_set(PORTA,4);
      else
         /*received a 0xFF from the VB program*/
         bit_clear(PORTA,4);
     }
}
/******************************************************************
//*	TCP Function
//*   This function uses TCP protocol to act as a Telnet server on
//*   port 8088 decimal.  The application function is called with
//*   every incoming character.
//******************************************************************/
 
void tcp()
{

   /*assemble the destination port address from the incoming packet*/
   portaddr = make16(packet[TCP_destport],packet[TCP_destport+1]);

   /*calculate the length of the data coming in with the packet*/
   /*tcpdatalen_in = incoming packet length - incoming ip header length - incoming tcp header length*/
   tcpdatalen_in = (make16(packet[ip_pktlen],packet[ip_pktlen+1])) -
   ((packet[ip_vers_len] & 0x0F) * 4) - (((packet[TCP_hdrflags] & 0xF0) >> 4) * 4);

   /*If an ACK is recieved and the destination port address is valid and no data is in the packet*/
   if(ACK_IN && portaddr == MY_PORT_ADDRESS && tcpdatalen_in == 0x00)
   {
      /*assemble the acknowledgment number from the incoming packet*/
      incoming_ack =make32(packet[TCP_acknum],packet[TCP_acknum+1],packet[TCP_acknum+2],packet[TCP_acknum+3]);

      /*if the incoming packet is a result of session establishment*/
      if(synflag)
      {
         /*clear the SYN flag*/
         synflag = 0;

         /*the incoming acknowledgment is my new sequence number*/
         my_seqnum = incoming_ack;

         /*send the Telnet server banner*/
         /*limit the character count to 40 decimal*/
         strcpy(packet[TCP_data],"EASY ETHERNET\r\n1=LED ON\r\n0=LED OFF\r\n>");
         /*length of the banner message*/
         tcpdatalen_out = 37;

         /*expect to get an acknowledgment of the banner message*/
         expected_ack = my_seqnum +tcpdatalen_out;

         /*send the TCP/IP packet*/
         send_tcp_packet();
      }
   }

   /*if an ack is received and the port address is valid and there is data in the incoming packet*/
   if(ACK_IN && portaddr == MY_PORT_ADDRESS && tcpdatalen_in)
   {
      for(i=0;i<tcpdatalen_in;++i)
      {
         /*receive the data and put it into the incoming data buffer*/
         aux_data[i] = packet[TCP_data+i];

         /*run the TCP application*/
         application_code();
      }

      /*assemble the acknowledgment number from the incoming packet*/
      incoming_ack =make32(packet[TCP_acknum],packet[TCP_acknum+1],packet[TCP_acknum+2],packet[TCP_acknum+3]);

      /*check for the number of bytes acknowledged*/
      /*determine how many bytes are outstanding and adjust the outgoing sequence number accordingly*/
      if(incoming_ack <= expected_ack)
         my_seqnum = expected_ack - (expected_ack - incoming_ack);

      /*my expected acknowledgement number*/
      expected_ack = my_seqnum +tcpdatalen_out;


      send_tcp_packet();
   }

   /*this code segment processes the incoming SYN from the Telnet client
   /*and sends back the initial sequence number (ISN) and acknowledges
   /*the incoming SYN packet*/
   if(SYN_IN && portaddr == MY_PORT_ADDRESS)
   {
      tcpdatalen_in = 0x01;
      synflag = 1;

      setipaddrs();

      data_L = packet[TCP_srcport];
      packet[TCP_srcport] = packet[TCP_destport];
      packet[TCP_destport] = data_L;

      data_L = packet[TCP_srcport+1];
      packet[TCP_srcport+1] = packet[TCP_destport+1];
      packet[TCP_destport+1] = data_L;

      assemble_ack();

      if(++ISN == 0x0000 || ++ISN == 0xFFFF)
         ISN = 0x1234;
      my_seqnum = make32(ISN,0xFFFF);

      set_packet32(TCP_seqnum,my_seqnum);

      packet[TCP_hdrflags+1] = 0x00;
      SYN_OUT;
      ACK_OUT;

      packet[TCP_cksum] = 0x00;
      packet[TCP_cksum+1] = 0x00;

      hdr_chksum =0;
      hdrlen = 0x08;
      addr = &packet[ip_srcaddr];
      cksum();
      hdr_chksum = hdr_chksum + packet[ip_proto];
      tcplen = make16(packet[ip_pktlen],packet[ip_pktlen+1]) - ((packet[ip_vers_len] & 0x0F) * 4);
      hdr_chksum = hdr_chksum + tcplen;
      hdrlen = tcplen;
      addr = &packet[TCP_srcport];
      cksum();
      chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
      packet[TCP_cksum] = make8(chksum16,1);
      packet[TCP_cksum+1] = make8(chksum16,0);
      echo_packet();
   }

   /*this code segment processes a FIN from the Telnet client
   /*and acknowledges the FIN and any incoming data.*/
   if(FIN_IN && portaddr == MY_PORT_ADDRESS)
   {
      if(tcpdatalen_in)
      {
         for(i=0;i<tcpdatalen_in;++i)
         {
            aux_data[i] = packet[TCP_data+i];
            application_code();
         }
      }

      finflag = 1;

      ++tcpdatalen_in;

      incoming_ack =make32(packet[TCP_acknum],packet[TCP_acknum+1],packet[TCP_acknum+2],packet[TCP_acknum+3]);
      if(incoming_ack <= expected_ack)
         my_seqnum = expected_ack - (expected_ack - incoming_ack);

      expected_ack = my_seqnum +tcpdatalen_out;
      send_tcp_packet();

   }
}
/******************************************************************
//*	Assemble the Acknowledgment
//*   This function assembles the acknowledgment to send to
//*   to the client by adding the received data count to the
//*   client's incoming sequence number.
//******************************************************************/
void assemble_ack()
{
   client_seqnum=make32(packet[TCP_seqnum],packet[TCP_seqnum+1],packet[TCP_seqnum+2],packet[TCP_seqnum+3]);
   client_seqnum = client_seqnum + tcpdatalen_in;
   set_packet32(TCP_acknum,client_seqnum);
}
/******************************************************************
//*	Send TCP Packet
//*   This routine assembles and sends a complete TCP/IP packet.
//*   40 bytes of IP and TCP header data is assumed.
//******************************************************************/
void send_tcp_packet()
{
   /*count IP and TCP header bytes.. Total = 40 bytes*/
   ip_packet_len = 40 + tcpdatalen_out;
   packet[ip_pktlen] = make8(ip_packet_len,1);
   packet[ip_pktlen+1] = make8(ip_packet_len,0);
   setipaddrs();

   data_L = packet[TCP_srcport];
   packet[TCP_srcport] = packet[TCP_destport];
   packet[TCP_destport] = data_L;
   data_L = packet[TCP_srcport+1];
   packet[TCP_srcport+1] = packet[TCP_destport+1];
   packet[TCP_destport+1] = data_L;

   assemble_ack();
   set_packet32(TCP_seqnum,my_seqnum);


   packet[TCP_hdrflags+1] = 0x00;
   ACK_OUT;
   if(finflag)
   {
      FIN_OUT;
      finflag = 0;
   }

   packet[TCP_cksum] = 0x00;
   packet[TCP_cksum+1] = 0x00;

   hdr_chksum =0;
   hdrlen = 0x08;
   addr = &packet[ip_srcaddr];
   cksum();
   hdr_chksum = hdr_chksum + packet[ip_proto];
   tcplen = ip_packet_len - ((packet[ip_vers_len] & 0x0F) * 4);
   hdr_chksum = hdr_chksum + tcplen;
   hdrlen = tcplen;
   addr = &packet[TCP_srcport];
   cksum();
   chksum16= ~(hdr_chksum + ((hdr_chksum & 0xFFFF0000) >> 16));
   packet[TCP_cksum] = make8(chksum16,1);
   packet[TCP_cksum+1] = make8(chksum16,0);

   txlen = ip_packet_len + 14;
   if(txlen < 60)
      txlen = 60;
   data_L = make8(txlen,0);
   data_H = make8(txlen,1);
   write_creg(CR,0x22);
   write_creg(TPSR,txstart);
   write_creg(RSAR0,0x00);
   write_creg(RSAR1,0x40);
   write_creg(ISR,0xFF);
   write_creg(RBCR0,data_L);
   write_creg(RBCR1,data_H);
   write_creg(CR,0x12);

   for(i=0;i<txlen;++i)
      write_creg(RDMAPORT,packet[enetpacketDest0+i]);

   byte_read = 0;
   while(!bit_test(byte_read,RDC))
      read_creg(ISR);

   write_creg(TBCR0,data_L);
   write_creg(TBCR1,data_H);
   write_creg(CR,0x24);
}
/******************************************************************
//*	Read/Write for show_regs
//*   This routine reads a NIC register and dumps it out to the
//*   serial port as ASCII.
//******************************************************************/
 
void readwrite()
{
     read_creg(i);
     bin2hex(byte_read);
     printf("\t%c%c",high_char,low_char);
}
/******************************************************************
//*	Displays Control Registers in Pages 1, 2 and 3
//*   This routine dumps all of the NIC internal registers
//*   to the serial port as ASCII characters.
//******************************************************************/
 
void show_regs()
{
   write_creg(CR,0x21);
   cls();
   printf("\r\n");
   printf("    Realtek 8019AS Register Dump\n\n\r");
   printf("REG\tPage0\tPage1\tPage2\tPage3\n\r");

   for(i=0;i<16;++i)
   {
     bin2hex((char) i);
     printf("%c%c",high_char,low_char);
     write_creg(CR,0x21);
     readwrite();
     write_creg(CR,0x61);
     readwrite();
     write_creg(CR,0xA1);
     readwrite();
     write_creg(CR,0xE1);
     readwrite();
     printf("\r\n");
   }
}
/******************************************************************
//*	Dump Receive Ring Buffer Header
//*   This routine dumps the 4-byte receive buffer ring header
//*   to the serial port as ASCII characters.
//******************************************************************/
 
void dump_header()
{
    for(i=0;i<4;++i)
      {
         bin2hex(pageheader[i]);
         printf("\r\n%c%c",high_char,low_char);
      }
}
/******************************************************************
//*	Converts Binary to Displayable Hex Characters
//*   ie.. 0x00 in gives 0x30 and 0x30 out
//******************************************************************/
 
void bin2hex(binchar)
{
   high_nibble = (binchar & 0xF0) / 16;
   if(high_nibble > 0x09)
      high_char = high_nibble + 0x37;
   else
      high_char = high_nibble + 0x30;

   low_nibble = (binchar & 0x0F);
   if(low_nibble > 0x09)
      low_char = low_nibble + 0x37;
   else
      low_char = low_nibble + 0x30;
}
/******************************************************************
//*	Used with Tera Term to clear the screen (VT-100 command)
//******************************************************************/
 
void cls(void)
{
   printf("%c[2J",esc);
}
/******************************************************************
//* show_packet  
//*	This routine is for diagnostic purposes and displays
//*   the Packet Buffer memory in the PIC.
//******************************************************************/
 
void show_packet()
{
   cls();
   printf("\r\n");
   data_L = 0x00;
   for(i=0;i<96;++i)
   {
      bin2hex(packet[i]);
      printf(" %c%c",high_char,low_char);
      if(++data_L == 0x10)
         {
            data_L = 0x00;
            printf("\r\n");
         }
   }
}
/******************************************************************
//*   show_aux_packet
//*	This routine is a diagnostic that displays Auxillary
//*   Packet Buffer buffer memory in the PIC.
//******************************************************************/
 
void show_aux_packet()
{
   cls();

⌨️ 快捷键说明

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