原创 ENC28J60提供的超小协议栈

2010-12-10 19:29 5396 12 12 分类: MCU/ 嵌入式


ENC28J60提供的超小协议栈,它用一个全局的数组来做接收和发送缓冲。部分发送数据包从接收包中更改标志和校验和得到,最大化的减少内存拷贝。实现TCP/IP协议收发数据包的各个子功能,如校验和计算,标志填充,包头填充等,但是要求用户应用层程序自行组包解包,要求程序员更加深入的了解TCP/IP协议,是学习的好资料。


以下是典型应用主程序



void main(void)
{
 uint8_t data i=0;
    uint16_t data j=0; 
 uint16_t data plen=0;
  uint16_t data dat_p=0;
 uint32_t data dat_p_post;


 uint8_t data cmd_pos=0;
 uint8_t data payloadlen=0;
char temp[100]; 
// char str[30];
// char cmdval;


 int data post_succeed;
// int write_succeed;
// int read_succeed;
// int eeprom_succeed;


//System_Hardware_Init:
    
InitHardware();  //硬件初始化


SBUF=0xEF;
    _delay_ms(20);



 // Create_PPPOE(buf);//建立PPPOE连接


 


 while(1){
   // get the next new packet:
   WDT_CONTR=0x3C;//00111100//1.1S@11.0592MHz//初始化看门狗fosc/32,2s溢出@6MHZ


  plen = enc28j60PacketReceive(BUFFER_SIZE, buf);//1500
                /*plen will ne unequal to zero if there is a valid
                 * packet (without crc error) */
  if(plen==0)
   continue;  //  "no data"


    // "Get one"                        
                // arp is broadcast if unknown but a host may also
                // verify the mac address by sending it to
                // a unicast address.
 if((buf[ETH_TYPE_H_P]==ETHTYPE_PPPOE_SESS_H_V)&&(buf[ETH_TYPE_L_P]==ETHTYPE_PPPOE_SESS_L_V))//SESSION//8864
  if(PPP_LCP_V==(buf[PPP_PROTOCOL_H_P]<<8|buf[PPP_PROTOCOL_L_P]))//PPP_LCP协议
  if(PPP_ECHO_REQ_V==buf[PPP_CODE_P])//回应远程主机的ECHO查询
  {
  make_ECHO_REPLAY_FROM_REQ(buf);
  UART1_PutNormalStr("echo reply.\r\n");
  }


  //if(eth_type_is_arp_and_my_ip(buf,plen))
  //{
   //UART1_PutStr(buf,plen);//过交换机接收正确
   //if(eth_type_is_arp_req(buf))
   //{
   // make_arp_answer_from_request(buf);  // make arp answer from request
    //UART1_PutStr(buf,plen);//过交换机发送正确
   //}
   //continue;


   
  //}



  // arp is broadcast if unknown but a host may also
  // verify the mac address by sending it to
  // a unicast address.
  if(eth_type_is_arp_and_my_ip(buf,plen)) {
            if(eth_type_is_arp_req(buf))
   make_arp_answer_from_request(buf);
   continue;
  }



                // check if ip packets are for us:
  if(eth_type_is_ip_and_my_ip(buf,plen)==0)
   continue;
 
                // led----------


                // a ping packet, let's send pong
  if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V)
  {
   make_echo_reply_from_request(buf,plen);   
   continue;
  }
         
          // tcp port www start, compare only the lower byte
  if (buf[IP_PROTO_P]==IP_PROTO_TCP_V&&buf[TCP_DST_PORT_H_P]==0&&buf[TCP_DST_PORT_L_P]==MYWWWPORT)
  {
   if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V)
   {
    make_tcp_synack_from_syn(buf);  // make_tcp_synack_from_syn does already send the syn,ack
    continue;
   }
      if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V)
   {
    init_len_info(buf);  // init some data structures, we can possibly have no data, just ack:
    dat_p=get_tcp_data_pointer();
    if (dat_p==0)
    {
     if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V)   // finack, answer with ack
      make_tcp_ack_from_any(buf);
         // just an ack with no data, wait for next packet
     continue;
    }
/*************************** POST Module ********************************/
    if (strncmp("POST ",(char *)&(buf[dat_p]),5)==0)
    {
     UART1_PutNormalStr( str_uart1_post );
     UART1_PutNormalStr( buf+dat_p );


     if( strncmp( "/ipctrl ", (char *)&(buf[dat_p+5]), 8 ) == 0 )
     {
      dat_p_post = find_ip_information( (char *)&(buf[dat_p]) );
      UART1_PutNormalStr( buf+dat_p+dat_p_post );
      post_succeed = ip_refresh( buf+dat_p+dat_p_post );
      if( post_succeed == 0 );    // 上传成功,-1为操作失败,1为无变化
      {
       UART1_PutNormalStr( New_NET );
//       eeprom_succeed = save_ip_2_eeprom();
      // if( eeprom_succeed == 4)
//        goto System_Hardware_Init;
      }


      plen=webpage_ipctrl(buf);
     }
     else if( strncmp( "/IPG ", (char *)&(buf[dat_p+5]), 5 ) == 0 )
     {
      dat_p_post = find_useful_information( (char *)&(buf[dat_p]) );
      UART1_PutNormalStr( buf+dat_p+dat_p_post );
      post_succeed = members_refresh( buf+dat_p+dat_p_post );
      if( post_succeed == 0 );  // 0为上传成功,开始写入下位机
//       write_succeed = Uart_write();    


//      read_succeed = Uart_read();  // 不管是否写入新参数,都读取


      plen=webpage_IPG(buf);
     }
     
     goto SENDTCP;
    }
/******************************** GET Module ********************************/  
    else if (strncmp("GET ",(char *)&(buf[dat_p]),4)==0)
    {
     UART1_PutNormalStr( str_uart1_get );
     UART1_PutNormalStr( buf+dat_p );


     if( strncmp( "/ipctrl ", (char *)&(buf[dat_p+4]), 8 ) == 0 )
      plen=webpage_ipctrl(buf);
     else if( strncmp( "/IPG ", (char *)&(buf[dat_p+4]), 5 ) == 0 )
     {
//      read_succeed = Uart_read();   // 读取下位机最新信息
//      if( read_succeed == 0 )
       plen=webpage_IPG(buf);
     }
     else if(  strncmp( "/ ", (char *)&(buf[dat_p+4]), 2 ) == 0 )
      //plen=webpage_index(buf);
      plen=fill_tcp_data( buf, 0, webpage_index );


     else
     { 
       sprintf(temp,"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n");  
       plen=fill_tcp_data( buf, 0, temp );
       sprintf(temp,"<p>Usage: http://host_or_ip/pagename</p>\n");  
       plen=fill_tcp_data( buf, plen, temp ); 
      //plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"));
      //plen=fill_tcp_data_p(buf,plen,PSTR("<p>Usage: http://host_or_ip/pagename</p>\n"));         
     }
     
     goto SENDTCP;
    }
       
   
SENDTCP:


    make_tcp_ack_from_any(buf);   // send ack for http get
    make_tcp_ack_with_data(buf,plen);  // send data
    continue;
   }
  }
                // tcp port www end
                //
              // udp start, we listen on udp port 1200=0x4B0
 /*
  if (buf[IP_PROTO_P]==IP_PROTO_UDP_V&&buf[UDP_DST_PORT_H_P]==4&&buf[UDP_DST_PORT_L_P]==0xb0)
  {
      payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN;
    // you must sent a string starting with v
    // e.g udpcom version 10.0.0.24
   if (verify_password((char *)&(buf[UDP_DATA_P])))
   {
    // find the first comma which indicates
    // the start of a command:
    cmd_pos=0;
    while(cmd_pos<payloadlen)
    {
     cmd_pos++;
     if (buf[UDP_DATA_P+cmd_pos]==',')
     {
      cmd_pos++;   // put on start of cmd
      break;
     }
    }
    // a command is one char and a value. At
    // least 3 characters long. It has an '=' on
    // position 2:
    if (cmd_pos<2 || cmd_pos>payloadlen-3 || buf[UDP_DATA_P+cmd_pos+1]!='=')
    {
     strcpy(str,"e=no_cmd");
     goto ANSWER;
    }
    // supported commands are
    // t=1 t=0 t=?
    if (buf[UDP_DATA_P+cmd_pos]=='t')
    {
     cmdval=buf[UDP_DATA_P+cmd_pos+2];
     if(cmdval=='1')
     {   // transistor on
      IOCLR0 = LED;
      strcpy(str,"t=1");
      goto ANSWER;
     }
     else if(cmdval=='0')
     {  // transistor off
      IOSET0 = LED;
      strcpy(str,"t=0");
      goto ANSWER;
     }
     else if(cmdval=='?')
     {
      if (IOPIN0 & LED)
      {
       strcpy(str,"t=1");
       goto ANSWER;
      }
     strcpy(str,"t=0");
     goto ANSWER;
     }
    }
    strcpy(str,"e=no_such_cmd");
    goto ANSWER;
   }
   strcpy(str,"e=invalid_pw");


ANSWER:
   make_udp_reply_from_request(buf,str,strlen(str),MYUDPPORT);
  }
*/
 }
_delay_ms(200);//
//return;
}//end main

文章评论0条评论)

登录后参与讨论
我要评论
0
12
关闭 站长推荐上一条 /2 下一条