Я пытаюсь запустить веб-сервер на 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() функции и как избавиться от этого.