Forum: Mikrocontroller und Digitale Elektronik enc28j60 spi Byteverschiebung


von grundschüler (Gast)


Lesenswert?

frohe weihnachten!

ich versuche den enc28j60 mittels U-Radig_SW an einen M328 
anzuschließen. Problem:

statt
FF.FF.FF.FF.FF.FF.00.1C.BF.A5.DD.91.
sieht der Anfang des EthernetHeaders so aus:
FF.FF.FF.FF.FF.00.1C.BF.A5.DD.91.08

Ich habe das Problem auf den spi-Aufruf eingegrenzt. Im EncRegister 
stehen die korrekten Werte. bei Aufruf von spi_get() wird der erste Wert 
übersprungen:
1
static inline void xspi_put( unsigned char value )
2
{
3
  //ENC_DEBUG("spi_put(%2x)\n", (unsigned) value );
4
  SPDR = value;
5
  while( !(SPSR & (1<<SPIF)) ) ;
6
}
7
8
static inline unsigned char xspi_get(void)
9
{
10
  unsigned char value = SPDR;
11
  //ENC_DEBUG("spi_get()=%2x\n", (unsigned) value );
12
  return value;
13
}
14
15
16
static void enc_read_buf( unsigned char *buf, unsigned int len )
17
{
18
  enc_select();
19
  spi_put( ENC_SPI_OP_RBM );
20
//if(len > 0){len--; buf++ ;*(buf) = xspi_get();}
21
  for(; len > 0; len--, buf++ ) {
22
    xspi_put( 0x00 );
23
    *(buf) = xspi_get();
24
  }
25
  enc_deselect();
26
}
27
28
29
30
unsigned int enc_receive_packet( unsigned int bufsize, unsigned char *buf )
31
{
32
  unsigned char rxheader[18];
33
  unsigned int len, status;
34
  unsigned char u;
35
36
  // check rx packet counter
37
  u = enc_read_reg( ENC_REG_EPKTCNT );
38
  ENC_DEBUG("enc_receive: EPKTCNT=%i\n", (int) u);
39
  if( u == 0 ) {
40
    // packetcounter is 0, there is nothing to receive, go back
41
    return 0;
42
  }
43
44
  //set read pointer to next packet
45
  enc_write_reg( ENC_REG_ERDPTL, LO8(enc_next_packet_ptr) );
46
  enc_write_reg( ENC_REG_ERDPTH, HI8(enc_next_packet_ptr) );
47
48
  // read enc rx packet header
49
  enc_read_buf( rxheader, 6 );
50
  enc_next_packet_ptr  =             rxheader[0];
51
  enc_next_packet_ptr |= ((unsigned)(rxheader[1])) << 8;
52
  len                  =             rxheader[2];
53
  len                 |= ((unsigned)(rxheader[3])) << 8;
54
  status               =             rxheader[4];
55
  status              |= ((unsigned)(rxheader[5])) << 8;
56
57
//kk
58
ePtr=enc_next_packet_ptr;
59
eLen=len;
60
eStatus=status;
61
62
/*
63
//kk
64
  //kein Fehler:
65
  for(i=6;i<12;i++){
66
  tmp_macd[i-6]=rxheader[i];
67
  }
68
69
  for(i=12;i<18;i++){
70
  tmp_macs[i-12]=rxheader[i];
71
  }
72
73
  
74
  //Fehler:
75
  enc_read_buf( tmp_macd, 6 );//1.byte wird ausgelassen
76
  enc_read_buf( tmp_macs, 6 );//1.byte wird ausgelassen
77
*/
78
  // added by Sjors: reset the ENC when needed
79
  // If the receive OK bit is not 1 or the zero bit is not zero, or the packet is larger then the buffer, reset the enc chip and SPI
80
  if ((!(status & (1<<7))) || (status & 0x8000) || (len > bufsize))
81
  { 
82
    enc_init();
83
  }
84
  //ENC_DEBUG("enc_receive: status=%4x\n", (unsigned) status);
85
86
  // skip the checksum (4 bytes) at the end of the buffer
87
  len -= 4;
88
89
  // if the application buffer is to small, we just truncate
90
  if( len > bufsize ) len = bufsize;
91
92
  // now read the packet data into buffer
93
  enc_read_buf( buf, len );//1.byte wird ausgelassen
94
95
96
97
  // adjust the ERXRDPT pointer (= free this packet in rx buffer)
98
  if(    enc_next_packet_ptr-1 > ENC_RX_BUFFER_END
99
      || enc_next_packet_ptr-1 < ENC_RX_BUFFER_START ) {
100
    enc_write_reg( ENC_REG_ERXRDPTL, LO8(ENC_RX_BUFFER_END) );
101
    enc_write_reg( ENC_REG_ERXRDPTH, HI8(ENC_RX_BUFFER_END) );
102
  } else {
103
    enc_write_reg( ENC_REG_ERXRDPTL, LO8(enc_next_packet_ptr-1) );
104
    enc_write_reg( ENC_REG_ERXRDPTH, HI8(enc_next_packet_ptr-1) );
105
  }
106
107
  // trigger a decrement of the rx packet counter
108
  // this will clear PKTIF if EPKTCNT reaches 0
109
  enc_setbits_reg( ENC_REG_ECON2, (1<<ENC_BIT_PKTDEC) );
110
111
  // return number of bytes written to the buffer
112
  ENC_DEBUG("enc_receive: %i bytes\n", len);
113
  return len;
114
}

Ich habe versucht, das erste dem spi_get() vorausgehende spi_put() zu 
unterdrücken. dann kommt nur Unsinn.


Da es sich um ein bewährtes Standardprogramm mit einem Standardchip 
handelt, stehe ich vor einem Rätsel. Bin für jede Hilfe dankbar.

von dunno.. (Gast)


Lesenswert?

Wie sehen denn spi_get bzw put aus?

Die geposteten Funktionen sind xspi.?

Wird bei SPI put das spdr geflusht..?

von grundschüler (Gast)


Lesenswert?

dunno.. schrieb:
> spi_get bzw put

xspi ist nur eine 1:1 Kopie von spi um die Funktion beim Aufruf durch 
enc_read_buf separat bearbeiten zu können. an enc_read_reg brauch ich 
dann nichts zu ändern, denn dort funktioniert der spi-put-get-Aufruf 
einwandfrei.

von grundschüler (Gast)


Lesenswert?

heureca
ich habe geändert:
1
static void enc_read_buf( unsigned char *buf, unsigned int len )
2
{
3
  enc_select();
4
  spi_put( ENC_SPI_OP_RBM );
5
//if(len > 0){len--; buf++ ;*(buf) = xspi_get();}
6
  for(; len > 0; len--, buf++ ) {
7
    spi_put( 0x00 );
8
    *(buf) = spi_get();
9
  }
10
  enc_deselect();
11
}
12
static void xenc_read_buf( unsigned char *buf, unsigned int len )
13
{
14
  enc_select();
15
//  spi_put( ENC_SPI_OP_RBM );
16
//if(len > 0){len--; buf++ ;*(buf) = xspi_get();}
17
  for(; len > 0; len--, buf++ ) {
18
    spi_put( ENC_SPI_OP_RBM );
19
    *(buf) = spi_get();
20
  }
21
  enc_deselect();
22
}
23
24
25
unsigned int enc_receive_packet( unsigned int bufsize, unsigned char *buf )
26
{
27
...
28
29
  // read enc rx packet header
30
  enc_read_buf( rxheader, 6 );
31
...
32
  // now read the packet data into buffer
33
  xenc_read_buf( buf, len );//1.byte wird ausgelassen
34
...

beim 2. Aufruf von enc_read_buf() ist spi_put( ENC_SPI_OP_RBM ); ein 
spi_put zuviel, da der buffer hierdurch um ein byte weitergelesen wird. 
Eigentlich logisch. Mit der geänderten xenc_read_buf() kommt jetzt das 
Ping. Alles funktioniert wie es soll.

Was ich jetzt nicht verstehe ist, wie die Original-U-Radig Funktion 
trotz diesem einmal zuviel spi_put funktionieren kann. Ich selbst habe 
das Original schon zigmal verwendet. Jetzt auf einmal geht es nicht 
mehr.





Was ich

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.