2016-07-13 9 views
1

Я пытаюсь запустить веб-сервер на AVR ATmega8 с помощью модуля ENC28J60. Для этого я получил образец кода from here. Этот код работает нормально. Вот мой код: -Невозможно запустить режим ввода с использованием SPI

#define F_CPU 8000000UL 

#include <avr/io.h> 
#include <string.h> 
#include "ip_arp_udp_tcp.h" 
#include "enc28j60.h" 
#include "timeout.h" 
#include "avr_compat.h" 
#include "net.h" 

// please modify the following two lines. mac and ip have to be unique 
// in your local area network. You can not have the same numbers in 
// two devices: 
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX 
static uint8_t myip[4] = {192,168,24,39}; 
// listen port for www 
#define MYWWWPORT 80 
//// listen port for udp 
#define MYUDPPORT 1200 
// 

#define BUFFER_SIZE 450 
static uint8_t buf[BUFFER_SIZE+1]; 

int main(void) 
{ 

    uint16_t plen; 
    uint16_t dat_p; 
    uint8_t i=0; 
    uint8_t payloadlen=0; 

    _delay_loop_1(50); 

    /*initialize enc28j60*/ 
    enc28j60Init(mymac); 
    enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz 
    _delay_loop_1(50); // 12ms 
    enc28j60PhyWrite(PHLCON,0x476); 
    _delay_loop_1(50); // 12ms 

    //init the ethernet/ip layer: 
    init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); 

    while(1) 
    { 
     // get the next new packet: 
     plen = enc28j60PacketReceive(BUFFER_SIZE, buf); 

     /*plen will ne unequal to zero if there is a valid * packet (without crc error) */ 
     if(plen==0) 
     { 
      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)) 
     { 
      make_arp_answer_from_request(buf); 
      continue; 
     } 
     // check if ip packets (icmp or udp) are for us: 
     if(eth_type_is_ip_and_my_ip(buf,plen)==0) 
     { 
     continue; 
     } 


     if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V) 
     { 
      // a ping packet, let's send pong 
      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; 
       } 
       if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0) 
       { 
        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>")); 
       } 
       else 
       { 
        // Web Code 
        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>")); 

        plen=fill_tcp_data_p(buf,plen,PSTR("<body>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));       
        plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("};")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("</script>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("</body")); 
       } 


       make_tcp_ack_from_any(buf); // send ack for http get 
       make_tcp_ack_with_data(buf,plen); // send data 
       continue; 
      } 

     } 
     // udp interface: 
     if (buf[IP_PROTO_P]==IP_PROTO_UDP_V) 
     { 
     payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN; 
     // the received command has to start with t and be 4 char long 
     // e.g "test\0" 
     if (buf[UDP_DATA_P]=='t' && payloadlen==5) 
     { 
      make_udp_reply_from_request(buf,"hello",6,MYUDPPORT); 
     } 
     } 
    } 
    return (0); 
} 

Теперь я хочу, чтобы добавить режим ввода захвата, поэтому я добавляю interrupt header file затем перейти в режим ввода захвата в основной(), а затем ввести sei() функцию. Теперь мой код выглядит так: -

#define F_CPU 8000000UL 

#include <avr/io.h> 
#include <string.h> 
#include "ip_arp_udp_tcp.h" 
#include "enc28j60.h" 
#include "timeout.h" 
#include "avr_compat.h" 
#include "net.h" 
#include <avr/interrupt.h> 
// please modify the following two lines. mac and ip have to be unique 
// in your local area network. You can not have the same numbers in 
// two devices: 
static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24}; 
// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX 
static uint8_t myip[4] = {192,168,24,39}; 
// listen port for www 
#define MYWWWPORT 80 
//// listen port for udp 
#define MYUDPPORT 1200 
// 

#define BUFFER_SIZE 450 
static uint8_t buf[BUFFER_SIZE+1]; 

int main(void) 
{ 


    TCCR1A = 0; 
    TCCR1B = (1<<ICNC1)|(1<<ICES1)|(1<<CS11); 
    TIMSK = (1<<TICIE1); 
    TCNT1 = 0; 
    sei(); 
    uint16_t plen; 
    uint16_t dat_p; 
    uint8_t i=0; 
    uint8_t payloadlen=0; 

    _delay_loop_1(50); 

    /*initialize enc28j60*/ 
    enc28j60Init(mymac); 
    enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz 
    _delay_loop_1(50); // 12ms 
    enc28j60PhyWrite(PHLCON,0x476); 
    _delay_loop_1(50); // 12ms 

    //init the ethernet/ip layer: 
    init_ip_arp_udp_tcp(mymac,myip,MYWWWPORT); 

    while(1) 
    { 
     // get the next new packet: 
     plen = enc28j60PacketReceive(BUFFER_SIZE, buf); 

     /*plen will ne unequal to zero if there is a valid * packet (without crc error) */ 
     if(plen==0) 
     { 
      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)) 
     { 
      make_arp_answer_from_request(buf); 
      continue; 
     } 
     // check if ip packets (icmp or udp) are for us: 
     if(eth_type_is_ip_and_my_ip(buf,plen)==0) 
     { 
     continue; 
     } 


     if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V) 
     { 
      // a ping packet, let's send pong 
      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; 
       } 
       if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0) 
       { 
        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<h1>200 OK</h1>")); 
       } 
       else 
       { 
        // Web Code 
        plen=fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n<p>PLANETCAST MEDIA SERVICES LTD</p>")); 

        plen=fill_tcp_data_p(buf,plen,PSTR("<body>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"text\" id=\"myurl\" name=\"url\" placeholder=\"Enter Url\"/><br>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<input type=\"submit\" id=\"clickbutton\" name=\"Click Here\" />")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("<script type=\"text/javascript\">")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("document.getElementById(\"clickbutton\").onclick = function(){"));       
        plen=fill_tcp_data_p(buf,plen,PSTR("var url = document.getElementById(\"myurl\").value;")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("location.href=url;")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("};")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("</script>")); 
        plen=fill_tcp_data_p(buf,plen,PSTR("</body")); 
       } 


       make_tcp_ack_from_any(buf); // send ack for http get 
       make_tcp_ack_with_data(buf,plen); // send data 
       continue; 
      } 

     } 
     // udp interface: 
     if (buf[IP_PROTO_P]==IP_PROTO_UDP_V) 
     { 
     payloadlen=buf[UDP_LEN_L_P]-UDP_HEADER_LEN; 
     // the received command has to start with t and be 4 char long 
     // e.g "test\0" 
     if (buf[UDP_DATA_P]=='t' && payloadlen==5) 
     { 
      make_udp_reply_from_request(buf,"hello",6,MYUDPPORT); 
     } 
     } 
    } 
    return (0); 
} 


ISR(TIMER1_CAPT_vect) 
{ 
    //do something 
} 

Теперь, когда я запускаю свой код, у меня нет веб-страницы в моем браузере. Итак, я прокомментирую функцию . После этого мой код работает нормально. Итак, я проверяю настройки SPI в enc28j60.c. По моим сведениям, SPI не работает на прерывании, поэтому на него не должно влиять sei(). Вот мои настройки СПИ в enc28j60.c: -

#define ENC28J60_CONTROL_PORT PORTB 
#define ENC28J60_CONTROL_DDR DDRB 
#define ENC28J60_CONTROL_CS  2 
#define ENC28J60_CONTROL_SO 4 
#define ENC28J60_CONTROL_SI 3 
#define ENC28J60_CONTROL_SCK 5 

void enc28j60Init(uint8_t* macaddr) 
{ 
    // initialize I/O 
     // ss as output: 
    ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_CS; 
    CSPASSIVE; // ss=0 
     // 
    ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_SI | 1<<ENC28J60_CONTROL_SCK; // mosi, sck output 
    cbi(ENC28J60_CONTROL_DDR,ENC28J60_CONTROL_SO); // MISO is input 
     // 
     cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SI); // MOSI low 
     cbi(ENC28J60_CONTROL_PORT,ENC28J60_CONTROL_SCK); // SCK low 

Так, может кто-нибудь сказать мне, почему мой режим SPI является адресности осуществляется SEI() функции и как избавиться от этого.

ответ

0

Я не прочитал весь ваш код, но я думаю, что вы все время в прерывании. В нормальном режиме таймер не сбрасывается, когда он достигает вершины. Попробуйте с TCNT1 = 0; в ISR.