1 /* Arduino Projekt aus der Beispielsammlung http://www.nuelectronics.com/download/projects/etherShield.zip

2

3 */

4

5 //extern "C" void __cxa_pure_virtual(void); //for C++ defines

6 //void __cxa_pure_virtual(void) {;

7

8 #pragma GCC diagnostic ignored "-Wwrite-strings"

9

10 #include "WProgram.h" //import main Arduino header file

11

12 #include "EncEthernet.h"

13

14 // change MAC and IP address if necessary

15 static uint8_t mymac[6] = {0x54,0x55,0x58,0x10,0x00,0x24};

16 static uint8_t myip[4] = {192,168,0,15};

17 static char baseurl[]="http://192.168.0.15/";

18 static uint16_t mywwwport =80;

19

20 #define BUFFER_SIZE 500

21 static uint8_t buf[BUFFER_SIZE+1];

22 #define STR_BUFFER_SIZE 22

23 static char strbuf[STR_BUFFER_SIZE+1];

24

25 EncEthernet es = EncEthernet();

26

27 // prepare the webpage by writing the data to the tcp send buffer

28 uint16_t print_webpage(uint8_t *buf);

29 int8_t analyse_cmd(char *str);

30 int main(){

31 setup();

32 loop();

33 }

34 void setup(){

35

36 /*initialize enc28j60*/

37 es.E_enc28j60Init(mymac);

38 es.E_enc28j60clkout(2); // change clkout from 6.25MHz to 12.5MHz

39 delay(10);

40

41 /* Magjack leds configuration, see enc28j60 datasheet, page 11 */

warum sind in diesem Beispiel die Bits 12-13 nicht auf 1???

42 // LEDA=greed LEDB=yellow

43

Wie die Leds angeschlossen sind entscheidet über full oder half duplex

44 // 0x880 is PHLCON LEDB=on, LEDA=on

45 // enc28j60PhyWrite(PHLCON,0b0000 1000 1000 00 00);

46 es.E_enc28j60PhyWrite(PHLCON,0x880);

47 delay(500);

48

49 // 0x990 is PHLCON LEDB=off, LEDA=off

50 // enc28j60PhyWrite(PHLCON,0b0000 1001 1001 00 00);

51 es.E_enc28j60PhyWrite(PHLCON,0x990);

52 delay(500);

53

54 // 0x880 is PHLCON LEDB=on, LEDA=on

55 // enc28j60PhyWrite(PHLCON,0b0000 1000 1000 00 00);

56 es.E_enc28j60PhyWrite(PHLCON,0x880);

57 delay(500);

58

59 // 0x990 is PHLCON LEDB=off, LEDA=off

60 // enc28j60PhyWrite(PHLCON,0b0000 1001 1001 00 00);

61 es.E_enc28j60PhyWrite(PHLCON,0x990);

62 delay(500);

63

64 // 0x476 is PHLCON LEDA=links status, LEDB=display receive/transmit activity

65 // enc28j60PhyWrite(PHLCON,0b0000 0100 0111 01 10);

66 es.E_enc28j60PhyWrite(PHLCON,0x476);

67 delay(100);

68

69 //init the ethernet/ip layer:

70 es.E_init_ip_arp_udp_tcp(mymac,myip,mywwwport);

71 }

72

73 void loop(){

74 uint16_t plen, dat_p;

75 int8_t cmd;

76

77 plen = es.E_enc28j60PacketReceive(BUFFER_SIZE, buf);

78 // plen will ne unequal to zero if there is a valid packet

79 if(plen!=0){

Arp liefert für eine gesuchte IP-Adresse die zugehörige MAC-Adresse; hier: der Router sucht die Mac-Adresse des Shields und stellt daher eine ARP-Anfrage ins Netz 

80 // arp is broadcast if unknown but a host may also verify

81 // the mac address by sending it to a unicast address.

82 if(es.E_eth_type_is_arp_and_my_ip(buf,plen)){

83 es.E_make_arp_answer_from_request(buf);

84 return;

85 }

86

falsche IP-Adresse => Paket verwerfen

87 // check if ip packets are for us:

88 if(es.E_eth_type_is_ip_and_my_ip(buf,plen)==0){

89 return;

90 }

91

Reaktion auf einen PING Pakettyp: ICMP Paket Typ: Echorequest  Typen: siehe net.h

92 if(buf[IP_PROTO_P]==IP_PROTO_ICMP_V

93 && buf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){

94 es.E_make_echo_reply_from_request(buf,plen);

95 return;

96 }

97

TCP fragt nach den Portnummern: diese sind 16bit ACHTUNG: hier ist das höhere Byte NULL

98 // tcp port www start, compare only the lower byte

99 if (buf[IP_PROTO_P]==IP_PROTO_TCP_V

100 && buf[TCP_DST_PORT_H_P]== 0

101 && buf[TCP_DST_PORT_L_P]== mywwwport){

TCP-Flags http://en.wikipedia.org/wiki/Transmission_Control_Protocol

102 if (buf[TCP_FLAGS_P] & TCP_FLAGS_SYN_V){

TCP Verbindungsaufbau

103 // make_tcp_synack_from_syn does already send the syn,ack

104 es.E_make_tcp_synack_from_syn(buf);

105 return;

106 }

ACK empfangen ==> Paket im Puffer buf

107 if (buf[TCP_FLAGS_P] & TCP_FLAGS_ACK_V){

108 es.E_init_len_info(buf); // init some data structures necessary for the following operation

109 dat_p=es.E_get_tcp_data_pointer(); //get a pointer to the start of tcp data in buf

110 if (dat_p==0){ // we can possibly have no data, just ack:

111 if (buf[TCP_FLAGS_P] & TCP_FLAGS_FIN_V){

112 es.E_make_tcp_ack_from_any(buf);

113 }

114 return;

115 }

die Daten liegen ab der Stelle dat_p im Puffer
(char*)&(buf[dat_p]) ist ein Pointer auf den Start der Daten

116 if (strncmp("GET ",(char *)&(buf[dat_p]),4)!=0){

117 // head, post and other methods for possible status codes

118 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

eine Get-Anfrage wird sofort positiv bestätigt

119 plen=es.E_fill_tcp_data_p(buf, 0, PSTR("HTTP/1.0 200 OK-Type: text/html<h1>200 OK</h1>"));

120 goto SENDTCP;

121 }

122 if (strncmp("/ ",(char *)&(buf[dat_p+4]),2)==0){

123 plen=print_webpage(buf);

124 goto SENDTCP;

125 }

126 cmd=analyse_cmd((char *)&(buf[dat_p+5]));

127 if (cmd==1){

128 plen=print_webpage(buf);

129 }

if (cmd==2) plen=print_webpage1(buf) usw...

130 // send ack for http get

131 SENDTCP: es.E_make_tcp_ack_from_any(buf);

132 // send data

133 es.E_make_tcp_ack_with_data(buf,plen);

134 }

135 }

136 }

137 }

138

139 // The returned value is stored in the global var strbuf

140 uint8_t find_key_val(char *str,char *key)

141 {

142 uint8_t found=0;

143 uint8_t i=0;

144 char *kp;

145 kp=key;

146 while(*str && *str!=' ' && found==0){

147 if (*str == *kp){

148 kp++;

149 if (*kp == '0'){

150 str++;

151 kp=key;

152 if (*str == '='){

153 found=1;

154 }

155 }

156 }else{

157 kp=key;

158 }

159 str++;

160 }

161 if (found==1){

162 // copy the value to a buffer and terminate it with '0'

163 while(*str && *str!=' ' && *str!='&' && i<STR_BUFFER_SIZE){

164 strbuf[i]=*str;

165 i++;

166 str++;

167 }

168 strbuf[i]='0';

169 }

170 return(found);

171 }

172

173 int8_t analyse_cmd(char *str)

174 {

175 int8_t r=-1;

176

177 if (find_key_val(str,"cmd")){

178 if (*strbuf < 0x3a && *strbuf > 0x2f){

179 // is a ASCII number, return it

180 r=(*strbuf-0x30);

181 }

182 }

183 return r;

184 }

185

186

187 uint16_t print_webpage(uint8_t *buf)

188 {

189 uint16_t plen;

190 plen=es.E_fill_tcp_data_p(buf,0,PSTR("HTTP/1.0 200 OK-Type: text/html"));

191 plen=es.E_fill_tcp_data_p(buf,plen,PSTR("<center><p><h1>Welcome to Arduino Ethernet Shield V1.0</h1></p> "));

192 plen=es.E_fill_tcp_data_p(buf,plen,PSTR("<hr><br> <h2><font color="blue">-- Your Arduino is online now -- "));

193 plen=es.E_fill_tcp_data_p(buf,plen,PSTR("<br> Control digital outputs "));

194 plen=es.E_fill_tcp_data_p(buf,plen,PSTR("<br> Read digital analog inputs HERE "));

195 plen=es.E_fill_tcp_data_p(buf,plen,PSTR(" <br></font></h2> ") );

196 plen=es.E_fill_tcp_data_p(buf,plen,PSTR("</center><hr> <a href="http://www.flamingoeda.com">www.flamingoeda.com<a>"));

197

198 return(plen);

199 }

Kner 2011 /home/roland/Dropbox/Projekte/ethernet/home/webserver/index.odt 4/4