Hallo Forum, ich bin gerade dabei einen Atmega16 im Verbund mit einem ENC60J28 zu betrieben. Die Schaltung ist aufgebaut, die Status LED an der MAGJack leuchtet, auch die Sende/Empfangs LED Idelt. Leider kommen leider scheint die Kommunikation zum Atmega noch nicht zu funktionieren. Auf der Fehlersuche habe ich entdeckt, dass ich an SCK keine Frequenz anliegen haben. Die Frage ist nur wieso. Momentan weis ich nicht weiter. Anbei der Schaltplan und die Programmteile. Vielleicht könnt ihr helfen? SPI Einstellungen:
1 | SPCR |= 1<<MSTR |
2 | SPCR |= 1<<SPE; |
3 | SPSR |= 1<<SPI2X |
Frequenz --> intern 8Mhz
1 | /* ##################################
|
2 | -Der buffer ist in stack.h definiert
|
3 | er ist in der Grösse ziemlich variabel,
|
4 | wenn man nicht gerade TCP verwendet,
|
5 | dann sollte auch eine Buffergrösse von
|
6 | 256 Reichen, für nur arp und udp evt
|
7 | sogar 128
|
8 | -Ip & Mac wird in stack.c festgelegt!
|
9 | -der zu verwendende Pin für /CS wird
|
10 | am Anfang von enc28h60.h festgelegt
|
11 | ####################################
|
12 | */
|
13 | #include <avr/io.h> |
14 | #include "stack.h" |
15 | #include "enc28j60.h" |
16 | |
17 | |
18 | #define TERMINATE 1
|
19 | #define DONT_TERMINATE 0
|
20 | |
21 | /*einfache memcpy*/
|
22 | void printinbuffer(uint8_t *buff,uint8_t *text,uint8_t terminate){ |
23 | while(*text){ |
24 | *buff++ = *text++; |
25 | }
|
26 | if(terminate) *buff++ = 0x00; |
27 | }
|
28 | |
29 | |
30 | /* einfache strcmp, zwecks Lerneffekt auch selbst gemacht*/
|
31 | uint8_t compare(uint8_t *buffone, uint8_t *bufftwo){ |
32 | |
33 | uint8_t counterone=0,countertwo=0; |
34 | while(*bufftwo){ |
35 | if(*buffone++ == *bufftwo++){counterone++;} |
36 | countertwo++; |
37 | }
|
38 | if(counterone==countertwo) return(1); |
39 | return(0); |
40 | |
41 | }
|
42 | |
43 | |
44 | int main(void){ |
45 | |
46 | |
47 | unsigned int packet_lenght; |
48 | |
49 | |
50 | /*ENC Initialisieren*/
|
51 | enc28j60Init(); |
52 | //Mac Adresse setzen(stack.h, dort wird auch die Ip festgelegt)
|
53 | nicSetMacAddress(mymac); |
54 | |
55 | /* Leds konfigurieren
|
56 | LEDA : Link status
|
57 | LEDB : Receive activity
|
58 | Led Settings : enc28j60 datasheet, page 11*/
|
59 | |
60 | enc28j60PhyWrite(0x14,0b0000010000100000); |
61 | |
62 | /* Leds konfigurieren
|
63 | LEDA : Link status
|
64 | LEDB : Blink Fast
|
65 | Led Settings : enc28j60 datasheet, page 11
|
66 | Auskommentieren, wenn mans lieber blinken sieht ;-) */
|
67 | |
68 | //enc28j60PhyWrite(0x14,0b0000010000100000);
|
69 | |
70 | |
71 | while(1){ |
72 | //Buffer des Enc's abhohlen :-)
|
73 | packet_lenght = enc28j60PacketReceive(BUFFER_SIZE, buffer); |
74 | |
75 | /*Wenn ein Packet angekommen ist, ist packet_lenght =! 0*/
|
76 | if(packet_lenght){ |
77 | |
78 | |
79 | /*Ist das Packet ein Broadcast packet, vom Typ Arp und an unsere Ip gerichtet?*/
|
80 | if(Checkbroadcast() && Checkarppackage() && Checkmyip()){ |
81 | arp(packet_lenght, buffer); |
82 | }
|
83 | |
84 | /*Ist das Packet kein Broadcast, sondern explizit an unsere mac adresse gerichtet?*/
|
85 | if(Checkmymac()){ |
86 | |
87 | /*Handelt es sich um ein ICMP Packet? ->beantworten (Pong)*/
|
88 | if (buffer[IP_TYPEFIELD] == TYPE_ICMP)icmp(packet_lenght,buffer); |
89 | |
90 | |
91 | /*Handelt es sich um ein UDP Packet, das auf Port 85 reinkommt?*/
|
92 | if(buffer[IP_TYPEFIELD] == TYPE_UDP && buffer[UDP_PORT_L] == 85){ |
93 | |
94 | /* Folgendes dient bloss als Anwendungsbeispiel,
|
95 | die empfangenen Daten liegen im buffer ab adresse UDP_DATA
|
96 | und können natürlich auch für ganz andere Zweche verwendet
|
97 | werden.
|
98 | TODO: -Funktion um nicht nur auf UDP Packete zu antworten,
|
99 | sondern auch welche zu erzeugen
|
100 | -TCP(muss ich erst noch verstehen :-) )
|
101 | */
|
102 | |
103 | if(compare(&buffer[UDP_DATA], "test")){ |
104 | |
105 | printinbuffer(&buffer[UDP_DATA], "Das Test Packetchen ist angekommen :-)",TERMINATE); |
106 | //Die Länge 38 bezieht sich hier nur auf die Nutzdaten, headerlänge etc wird von der
|
107 | //Udp Funktion natürlich selbst übernommen...
|
108 | udp(38,buffer); |
109 | }
|
110 | |
111 | }
|
112 | |
113 | }
|
114 | |
115 | }
|
116 | |
117 | |
118 | }
|
119 | |
120 | return (1); |
121 | }
|
1 | /*! \file enc28j60.c \brief Microchip ENC28J60 Ethernet Interface Driver. */
|
2 | //*****************************************************************************
|
3 | //
|
4 | // File Name : 'enc28j60.c'
|
5 | // Title : Microchip ENC28J60 Ethernet Interface Driver
|
6 | // Author : Pascal Stang (c)2005
|
7 | // Created : 9/22/2005
|
8 | // Revised : 9/22/2005
|
9 | // Version : 0.1
|
10 | // Target MCU : Atmel AVR series
|
11 | // Editor Tabs : 4
|
12 | //
|
13 | // Description : This driver provides initialization and transmit/receive
|
14 | // functions for the Microchip ENC28J60 10Mb Ethernet Controller and PHY.
|
15 | // This chip is novel in that it is a full MAC+PHY interface all in a 28-pin
|
16 | // chip, using an SPI interface to the host processor.
|
17 | //
|
18 | //*****************************************************************************
|
19 | |
20 | #include "global.h" |
21 | //#include "timer.h"
|
22 | //#include "rprintf.h"
|
23 | |
24 | #include "enc28j60.h" |
25 | #include <avr/io.h> |
26 | |
27 | |
28 | u08 Enc28j60Bank; |
29 | u16 NextPacketPtr; |
30 | #define ENC28J60_CONTROL_PORT PORTD
|
31 | #define ENC28J60_CONTROL_DDR DDRD
|
32 | #define ENC28J60_CONTROL_CS 4
|
33 | |
34 | #define F_CPU 8000000 /* Processor Speed */ |
35 | #define CYCLES_PER_US ((F_CPU+500000)/1000000) /* cpu cycles per microsecond */ |
36 | |
37 | void delay(unsigned short us) |
38 | {
|
39 | unsigned short delay_loops; |
40 | register unsigned short i; |
41 | |
42 | delay_loops = (us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty) |
43 | |
44 | // one loop takes 5 cpu cycles
|
45 | for (i=0; i < delay_loops; i++) {}; |
46 | }
|
47 | |
48 | void nicSetMacAddress(u08* macaddr) |
49 | {
|
50 | // write MAC address
|
51 | // NOTE: MAC address in ENC28J60 is byte-backward
|
52 | enc28j60Write(MAADR5, *macaddr++); |
53 | enc28j60Write(MAADR4, *macaddr++); |
54 | enc28j60Write(MAADR3, *macaddr++); |
55 | enc28j60Write(MAADR2, *macaddr++); |
56 | enc28j60Write(MAADR1, *macaddr++); |
57 | enc28j60Write(MAADR0, *macaddr++); |
58 | }
|
59 | |
60 | |
61 | |
62 | |
63 | |
64 | u08 enc28j60ReadOp(u08 op, u08 address) |
65 | {
|
66 | u08 data; |
67 | |
68 | // assert CS
|
69 | ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); |
70 | |
71 | // issue read command
|
72 | SPDR = op | (address & ADDR_MASK); |
73 | while(!(SPSR & (1<<SPIF))); |
74 | // read data
|
75 | SPDR = 0x00; |
76 | while(!(SPSR & (1<<SPIF))); |
77 | // do dummy read if needed
|
78 | if(address & 0x80) |
79 | {
|
80 | SPDR = 0x00; |
81 | while(!(inb(SPSR) & (1<<SPIF))); |
82 | }
|
83 | data = SPDR; |
84 | |
85 | // release CS
|
86 | ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); |
87 | |
88 | return data; |
89 | }
|
90 | |
91 | void enc28j60WriteOp(u08 op, u08 address, u08 data) |
92 | {
|
93 | // assert CS
|
94 | ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); |
95 | |
96 | // issue write command
|
97 | SPDR = op | (address & ADDR_MASK); |
98 | while(!(SPSR & (1<<SPIF))); |
99 | // write data
|
100 | SPDR = data; |
101 | while(!(SPSR & (1<<SPIF))); |
102 | |
103 | // release CS
|
104 | ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); |
105 | }
|
106 | |
107 | void enc28j60ReadBuffer(u16 len, u08* data) |
108 | {
|
109 | // assert CS
|
110 | ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); |
111 | |
112 | // issue read command
|
113 | SPDR = ENC28J60_READ_BUF_MEM; |
114 | while(!(SPSR & (1<<SPIF))); |
115 | while(len--) |
116 | {
|
117 | // read data
|
118 | SPDR = 0x00; |
119 | while(!(SPSR & (1<<SPIF))); |
120 | *data++ = SPDR; |
121 | }
|
122 | // release CS
|
123 | ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); |
124 | }
|
125 | |
126 | void enc28j60WriteBuffer(u16 len, u08* data) |
127 | {
|
128 | // assert CS
|
129 | ENC28J60_CONTROL_PORT &= ~(1<<ENC28J60_CONTROL_CS); |
130 | |
131 | // issue write command
|
132 | SPDR = ENC28J60_WRITE_BUF_MEM; |
133 | while(!(SPSR & (1<<SPIF))); |
134 | while(len--) |
135 | {
|
136 | // write data
|
137 | SPDR = *data++; |
138 | while(!(SPSR & (1<<SPIF))); |
139 | }
|
140 | // release CS
|
141 | ENC28J60_CONTROL_PORT |= (1<<ENC28J60_CONTROL_CS); |
142 | }
|
143 | |
144 | void enc28j60SetBank(u08 address) |
145 | {
|
146 | // set the bank (if needed)
|
147 | if((address & BANK_MASK) != Enc28j60Bank) |
148 | {
|
149 | // set the bank
|
150 | enc28j60WriteOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); |
151 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); |
152 | Enc28j60Bank = (address & BANK_MASK); |
153 | }
|
154 | }
|
155 | |
156 | u08 enc28j60Read(u08 address) |
157 | {
|
158 | // set the bank
|
159 | enc28j60SetBank(address); |
160 | // do the read
|
161 | return enc28j60ReadOp(ENC28J60_READ_CTRL_REG, address); |
162 | }
|
163 | |
164 | void enc28j60Write(u08 address, u08 data) |
165 | {
|
166 | // set the bank
|
167 | enc28j60SetBank(address); |
168 | // do the write
|
169 | enc28j60WriteOp(ENC28J60_WRITE_CTRL_REG, address, data); |
170 | }
|
171 | |
172 | |
173 | |
174 | void enc28j60PhyWrite(u08 address, u16 data) |
175 | {
|
176 | // set the PHY register address
|
177 | enc28j60Write(MIREGADR, address); |
178 | |
179 | // write the PHY data
|
180 | enc28j60Write(MIWRL, data); |
181 | enc28j60Write(MIWRH, data>>8); |
182 | |
183 | // wait until the PHY write completes
|
184 | while(enc28j60Read(MISTAT) & MISTAT_BUSY); |
185 | }
|
186 | |
187 | void enc28j60Init(void) |
188 | {
|
189 | // initialize I/O
|
190 | |
191 | ENC28J60_CONTROL_DDR |= 1<<ENC28J60_CONTROL_CS; |
192 | ENC28J60_CONTROL_PORT |= 1<<ENC28J60_CONTROL_CS; |
193 | |
194 | |
195 | /*
|
196 | PORTB |= 1<<PB5; //SCK HI
|
197 | DDRB |= 1<<PB2 |1<<PB3 | 1<<PB5; // mosi, sck, ss output
|
198 | DDRB &= ~(1<<PB4); // miso input
|
199 | */
|
200 | |
201 | PORTB |= 1<<PB7; //SCK HI |
202 | DDRB |= 1<<PB4 |1<<PB5 | 1<<PB7; // mosi, sck, ss output |
203 | DDRB &= ~(1<<PB6); // miso input |
204 | |
205 | //SS muss out sein, damit nicht auf Slave gewechselt wird
|
206 | |
207 | // initialize SPI interface
|
208 | // master mode und /2x takt (klappt auch wenn der mega8 mit 16mhz läuft !!)
|
209 | SPCR |= 1<<MSTR |
210 | SPCR |= 1<<SPE; |
211 | SPSR |= 1<<SPI2X |
212 | |
213 | |
214 | |
215 | // perform system reset
|
216 | enc28j60WriteOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); |
217 | // check CLKRDY bit to see if reset is complete
|
218 | delay(50); |
219 | while(!(enc28j60Read(ESTAT) & ESTAT_CLKRDY)); |
220 | |
221 | // do bank 0 stuff
|
222 | // initialize receive buffer
|
223 | // 16-bit transfers, must write low byte first
|
224 | // set receive buffer start address
|
225 | NextPacketPtr = RXSTART_INIT; |
226 | enc28j60Write(ERXSTL, RXSTART_INIT&0xFF); |
227 | enc28j60Write(ERXSTH, RXSTART_INIT>>8); |
228 | // set receive pointer address
|
229 | enc28j60Write(ERXRDPTL, RXSTART_INIT&0xFF); |
230 | enc28j60Write(ERXRDPTH, RXSTART_INIT>>8); |
231 | // set receive buffer end
|
232 | // ERXND defaults to 0x1FFF (end of ram)
|
233 | enc28j60Write(ERXNDL, RXSTOP_INIT&0xFF); |
234 | enc28j60Write(ERXNDH, RXSTOP_INIT>>8); |
235 | // set transmit buffer start
|
236 | // ETXST defaults to 0x0000 (beginnging of ram)
|
237 | enc28j60Write(ETXSTL, TXSTART_INIT&0xFF); |
238 | enc28j60Write(ETXSTH, TXSTART_INIT>>8); |
239 | |
240 | // do bank 2 stuff
|
241 | // enable MAC receive
|
242 | enc28j60Write(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); |
243 | // bring MAC out of reset
|
244 | enc28j60Write(MACON2, 0x00); |
245 | // enable automatic padding and CRC operations
|
246 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); |
247 | |
248 | // set inter-frame gap (non-back-to-back)
|
249 | enc28j60Write(MAIPGL, 0x12); |
250 | enc28j60Write(MAIPGH, 0x0C); |
251 | // set inter-frame gap (back-to-back)
|
252 | enc28j60Write(MABBIPG, 0x12); |
253 | // Set the maximum packet size which the controller will accept
|
254 | enc28j60Write(MAMXFLL, MAX_FRAMELEN&0xFF); |
255 | enc28j60Write(MAMXFLH, MAX_FRAMELEN>>8); |
256 | |
257 | // do bank 3 stuff
|
258 | // write MAC address
|
259 | // NOTE: MAC address in ENC28J60 is byte-backward
|
260 | enc28j60Write(MAADR5, ENC28J60_MAC0); |
261 | enc28j60Write(MAADR4, ENC28J60_MAC1); |
262 | enc28j60Write(MAADR3, ENC28J60_MAC2); |
263 | enc28j60Write(MAADR2, ENC28J60_MAC3); |
264 | enc28j60Write(MAADR1, ENC28J60_MAC4); |
265 | enc28j60Write(MAADR0, ENC28J60_MAC5); |
266 | |
267 | // no loopback of transmitted frames
|
268 | enc28j60PhyWrite(PHCON2, PHCON2_HDLDIS); |
269 | |
270 | // switch to bank 0
|
271 | enc28j60SetBank(ECON1); |
272 | // enable interrutps
|
273 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); |
274 | // enable packet reception
|
275 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); |
276 | |
277 | }
|
278 | |
279 | void enc28j60PacketSend(unsigned int len, unsigned char* packet) |
280 | {
|
281 | // Set the write pointer to start of transmit buffer area
|
282 | enc28j60Write(EWRPTL, TXSTART_INIT); |
283 | enc28j60Write(EWRPTH, TXSTART_INIT>>8); |
284 | // Set the TXND pointer to correspond to the packet size given
|
285 | enc28j60Write(ETXNDL, (TXSTART_INIT+len)); |
286 | enc28j60Write(ETXNDH, (TXSTART_INIT+len)>>8); |
287 | |
288 | // write per-packet control byte
|
289 | enc28j60WriteOp(ENC28J60_WRITE_BUF_MEM, 0, 0x00); |
290 | |
291 | // copy the packet into the transmit buffer
|
292 | enc28j60WriteBuffer(len, packet); |
293 | |
294 | // send the contents of the transmit buffer onto the network
|
295 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); |
296 | }
|
297 | |
298 | unsigned int enc28j60PacketReceive(unsigned int maxlen, unsigned char* packet) |
299 | {
|
300 | u16 rxstat; |
301 | u16 len; |
302 | |
303 | // check if a packet has been received and buffered
|
304 | if( !(enc28j60Read(EIR) & EIR_PKTIF) ) |
305 | return 0; |
306 | |
307 | // Make absolutely certain that any previous packet was discarded
|
308 | //if( WasDiscarded == FALSE)
|
309 | // MACDiscardRx();
|
310 | |
311 | // Set the read pointer to the start of the received packet
|
312 | enc28j60Write(ERDPTL, (NextPacketPtr)); |
313 | enc28j60Write(ERDPTH, (NextPacketPtr)>>8); |
314 | // read the next packet pointer
|
315 | NextPacketPtr = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); |
316 | NextPacketPtr |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; |
317 | // read the packet length
|
318 | len = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); |
319 | len |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; |
320 | // read the receive status
|
321 | rxstat = enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0); |
322 | rxstat |= enc28j60ReadOp(ENC28J60_READ_BUF_MEM, 0)<<8; |
323 | |
324 | // limit retrieve length
|
325 | // (we reduce the MAC-reported length by 4 to remove the CRC)
|
326 | len = MIN(len, maxlen); |
327 | |
328 | // copy the packet from the receive buffer
|
329 | enc28j60ReadBuffer(len, packet); |
330 | |
331 | // Move the RX read pointer to the start of the next received packet
|
332 | // This frees the memory we just read out
|
333 | enc28j60Write(ERXRDPTL, (NextPacketPtr)); |
334 | enc28j60Write(ERXRDPTH, (NextPacketPtr)>>8); |
335 | |
336 | // decrement the packet counter indicate we are done with this packet
|
337 | enc28j60WriteOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); |
338 | |
339 | return len; |
340 | }
|
1 | #include "stack.h" |
2 | |
3 | /*NIC Einstellungen !! -----------------------------------
|
4 | #########################################################*/
|
5 | |
6 | volatile unsigned char myip[4] = {192,168,178,3}; |
7 | volatile unsigned char mymac[6] = {0xab,0xbc,0x6f,0x55,0x1c,0xc2}; |
8 | |
9 | /*#######################################################
|
10 | # Funktion um die Checksumme zu berechnen, stammt #
|
11 | # ursprünglich von #
|
12 | # Ulrich Radig :-),www.ulrichradig.de #
|
13 | # wer genaueres zur Checksummenbildung wissen möchte: #
|
14 | # http://www.netfor2.com/udpsum.htm #
|
15 | ########################################################*/
|
16 | int checksum (unsigned char * pointer,unsigned long result32,unsigned int result16) |
17 | {
|
18 | unsigned int result16_1 = 0x0000; |
19 | unsigned char DataH; |
20 | unsigned char DataL; |
21 | |
22 | //Jetzt werden alle Packete in einer While Schleife addiert
|
23 | while(result16 > 1) |
24 | {
|
25 | //schreibt Inhalt Pointer nach DATAH danach inc Pointer
|
26 | DataH=*pointer++; |
27 | |
28 | //schreibt Inhalt Pointer nach DATAL danach inc Pointer
|
29 | DataL=*pointer++; |
30 | |
31 | //erzeugt Int aus Data L und Data H
|
32 | result16_1 = ((DataH << 8)+DataL); |
33 | //Addiert packet mit vorherigen
|
34 | result32 = result32 + result16_1; |
35 | //decrimiert Länge von TCP Headerschleife um 2
|
36 | result16 -=2; |
37 | }
|
38 | |
39 | //Ist der Wert result16 ungerade ist DataL = 0
|
40 | if(result16 > 0) |
41 | {
|
42 | //schreibt Inhalt Pointer nach DATAH danach inc Pointer
|
43 | DataH=*pointer; |
44 | //erzeugt Int aus Data L ist 0 (ist nicht in der Berechnung) und Data H
|
45 | result16_1 = (DataH << 8); |
46 | //Addiert packet mit vorherigen
|
47 | result32 = result32 + result16_1; |
48 | }
|
49 | |
50 | //Komplementbildung (addiert Long INT_H Byte mit Long INT L Byte)
|
51 | result32 = ((result32 & 0x0000FFFF)+ ((result32 & 0xFFFF0000) >> 16)); |
52 | result32 = ((result32 & 0x0000FFFF)+ ((result32 & 0xFFFF0000) >> 16)); |
53 | result16 =~(result32 & 0x0000FFFF); |
54 | |
55 | return (result16); |
56 | }
|
57 | /* Funktionen, um zu überprüfen, ob das Packet für uns bestimmt ist, weitere Prüf'routinen'
|
58 | sind als Macros in stack.h definiert, da sie unabhängig von der IP immer auf dieselbe Art
|
59 | geprüft werden können
|
60 | ######################################################################################*/
|
61 | uint8_t Checkmymac(void){ |
62 | if(buffer[0] == mymac[0] && buffer[1] == mymac[1] && buffer[2] == mymac[2] && buffer[3] == mymac[3] && buffer[4] == mymac[4] && buffer[5] == mymac[5])return(1); |
63 | return(0); |
64 | }
|
65 | |
66 | uint8_t Checkmyip(void){ |
67 | if(buffer[38] == myip[0] && buffer[39] == myip[1] && buffer[40] == myip[2] && buffer[41] == myip[3])return(1); |
68 | return(0); |
69 | }
|
70 | |
71 | /*Funktion um den Ethernet II Header zu erzeugen
|
72 | ####################################################################################*/
|
73 | void eth(unsigned char *buff){ |
74 | |
75 | for(unsigned char a=0; a<6; a++) |
76 | {
|
77 | buff[a] = buff[a+6]; |
78 | buff[a+6] = mymac[a]; |
79 | }
|
80 | }
|
81 | /*Funktion um den IP Header zu erzeugen
|
82 | ####################################################################################*/
|
83 | void ip(unsigned char *buff){ |
84 | struct IP_header *ip; |
85 | unsigned int sum; |
86 | |
87 | ip = (struct IP_Header *)&buff[24]; |
88 | |
89 | for(unsigned char a=0;a<4; a++) |
90 | {
|
91 | ip->IP_destIp[a] = ip->IP_sourceIp[a]; |
92 | ip->IP_sourceIp[a] = myip[a]; |
93 | }
|
94 | |
95 | |
96 | ip->IP_checksum = 0x00; // checksum auf null setzen |
97 | sum = checksum(&buff[14],0x00000000,20); // checksumme ausrechnen |
98 | |
99 | ip->IP_checksum = ((sum & 0xFF00) >> 8)|((sum & 0x00FF)<<8); |
100 | }
|
101 | /*Funktion um auf ein Arp Request eine Antwort zurück zu senden
|
102 | ####################################################################################*/
|
103 | void arp(unsigned int len, unsigned char *buff){ |
104 | |
105 | eth(buff); // ETHERNET II header erzeugen |
106 | struct ARP_header *arp; |
107 | arp = (struct ARP_Header *)&buff[21]; |
108 | arp->Opcode = 0x02; //Reply einstellen |
109 | for(unsigned char a=0; a<6; a++) |
110 | {
|
111 | arp->ARP_destMac[a] = arp->ARP_sourceMac[a]; |
112 | arp->ARP_sourceMac[a] = mymac[a]; |
113 | }
|
114 | for(unsigned char a=0; a<4; a++) |
115 | {
|
116 | arp->ARP_destIp[a] = arp->ARP_sourceIp[a]; |
117 | arp->ARP_sourceIp[a] = myip[a]; |
118 | }
|
119 | |
120 | |
121 | enc28j60PacketSend(len-4,buff); |
122 | }
|
123 | /*Funktion um ICMP packete zu beantworten
|
124 | ####################################################################################*/
|
125 | void icmp(unsigned int len, unsigned char *buff){ |
126 | eth(buff); // ETHERNET II header erzeugen |
127 | ip(buff); // IP header erzeugen |
128 | |
129 | struct ICMP_header *icmp; |
130 | icmp = (struct ICMP_Header *)&buff[34]; |
131 | |
132 | icmp->ICMP_type = 0x00; // auf reply einstellen |
133 | icmp->ICMP_code = 0x00; |
134 | |
135 | //Simple ICMP Checksummenbildung, die Idee stammt von
|
136 | //Simon, siehe http://avr.auctionant.de/
|
137 | if(icmp->ICMP_checksumByteOne > 0xFF-0x08)icmp->ICMP_checksumByteTwo++; |
138 | icmp->ICMP_checksumByteOne+=0x08; |
139 | |
140 | enc28j60PacketSend(len-4,buff); |
141 | }
|
142 | |
143 | /*UDP Funktion, beliebige Antwort
|
144 | ####################################################################################*/
|
145 | void udp(unsigned int len, unsigned char *buff){ |
146 | uint16_t tempport,sum; |
147 | struct UDP_header *udp; |
148 | udp = (struct UDP_Header *)&buff[34]; |
149 | |
150 | // ETHERNET II header erzeugen
|
151 | eth(buff); |
152 | |
153 | // IP header erzeugen
|
154 | buff[16] = ((IP_UDP_HEADERLENGHT+len) & 0xFF00)>>8; |
155 | buff[17] = ((IP_UDP_HEADERLENGHT+len) & 0x00FF); // ip header lenght anpassen |
156 | |
157 | ip(buff); |
158 | |
159 | //An den Port zurücksenden, von dem das Packet gekommen ist
|
160 | tempport = udp->UDP_destPort; // Ziel Port zwischenspeichern |
161 | udp->UDP_destPort = udp->UDP_sourcePort; //ZielPort neuschreiben |
162 | udp->UDP_sourcePort = tempport; // SourcePort neuschreiben |
163 | |
164 | //Udp Header&Datenlänge schreiben
|
165 | udp->UDP_lenght_h = ((UDP_HEADERLENGHT+len) & 0xFF00)>>8; |
166 | udp->UDP_lenght_l = ((UDP_HEADERLENGHT+len) & 0x00FF); |
167 | |
168 | //Checksumme ausrechnen...
|
169 | udp->UDP_checksum = 0x00; |
170 | sum = checksum(&buff[26],TYPE_UDP+UDP_HEADERLENGHT+len,16+len); |
171 | udp->UDP_checksum = ((sum & 0xFF00) >> 8)|((sum & 0x00FF)<<8); |
172 | |
173 | //Und ab damit :-)
|
174 | enc28j60PacketSend(IP_UDP_HEADERLENGHT + ETH_HEADERLENGHT +len,buff); |
175 | }
|