SPI-Problem mit ENC28J60

OP #5387123
Lesenswert?

Hallo,

ich versuche gerade einen ENC28J60 an einem ATmega324A in Betrieb zu 
nehmen und habe ein Problem mit dem MISO-Pin (siehe Anhang). Hat jemand 
schon mal soetwas gesehen und weiß, was zu tun ist?

Über einen ISP kann ich den ATmega324A programmieren, daher würde ich 
einen Kurzschluss mal ausschließen. Und wenn ich mir mit dem Oszilloskop 
die MOSI-Leitung anschaue, sieht die auch normal aus, d.h. ich würde 
eine falsche Einstellung am Oszi auch ausschließen. Wenn ich 
programmiere, dann sieht die MOSI-Leitung auch normal aus (geht runter 
bis auf 0V). Und den MISO-Pin habe ich auch nicht auf Ausgang 
geschaltet...

Gibt es sonst noch was, was man vergessen haben könnte?

Danke schon mal und viele Grüße

---------------------
Edit:
Also die gelbe Linie ist MISO...
Angehängte Dateien:
Gast #5387154
Lesenswert?

Tobias E. schrieb:
> Gibt es sonst noch was, was man vergessen haben könnte?

- Einen Chip Select zu verdrahten?
- Einen Chip Select programmtechnisch zu bedienen?

Ansonsten hilft ein Schaltplan und dein Programm erheblich
weiter. Wenn nicht (keines von beiden), dann bleibt es ein
Rätselraten.
OP #5387169
Lesenswert?

Schaltplan ist als pdf angehängt
(Ich bin noch mehr oder weniger Anfänger, also ein paar Sachen sind 
bestimmt nicht optimal, aber ich denke es sollte schon funktionieren...)

und der Code:

(ich poste ihn mal hier direkt rein, dann müsst ihr keine Dateien 
downloaden)
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include "enc28j60.h"
4
#include "SPI.h"
5
#include "UART.h"
6

7

8
int main(void)
9
{
10
  //UARTInit();
11
  //uart_puts("Bootloader Version 0\n");
12
  //uart_puts("Noch passiert hier nichts...\n");
13
  
14
  //uart_puts("Initialisiere ENC28J60...\n");
15
  char ver = enc28j60::init();
16
  //uart_putc(ver);
17
  
18
    while (1) 
19
    {
20
    
21
    }
22
}

enc28j60.cpp:
(ist im wesentlichen aus dem Ethercard-Projekt)
1
#include "enc28j60.h"
2
#include "SPI.h"
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6

7
#define SS_DDR DDRB
8
#define SS_PORT PORTB
9
#define SS_PIN DDB0
10

11
static char Enc28j60Bank;
12

13
char enc28j60::init(){
14
  SPIInit();
15
  
16
  disableChip();
17
  writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET);
18
  _delay_ms(2); // errata B7/2
19
  while (!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY)
20
  ;
21
  
22
  writeReg(ERXST, RXSTART_INIT);
23
  writeReg(ERXRDPT, RXSTART_INIT);
24
  writeReg(ERXND, RXSTOP_INIT);
25
  writeReg(ETXST, TXSTART_INIT);
26
  writeReg(ETXND, TXSTOP_INIT);
27

28
  writeRegByte(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN);
29
  writeReg(EPMM0, 0x303f);
30
  writeReg(EPMCS, 0xf7f9);
31
  writeRegByte(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS);
32
  writeRegByte(MACON2, 0x00);
33
  writeOp(ENC28J60_BIT_FIELD_SET, MACON3,
34
  MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN);
35
  writeReg(MAIPG, 0x0C12);
36
  writeRegByte(MABBIPG, 0x12);
37

38
  writeReg(MAMXFL, MAX_FRAMELEN);
39
  writeRegByte(MAADR5, 0x12);
40
  
41
  writeRegByte(MAADR4, 0x23);
42
  writeRegByte(MAADR3, 0x34);
43
  writeRegByte(MAADR2, 0x45);
44
  writeRegByte(MAADR1, 0x56);
45
  writeRegByte(MAADR0, 0x67);
46
  writePhy(PHCON2, PHCON2_HDLDIS);   //<------- hier hängt es -----
47

48
  SetBank(ECON1);
49
  writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
50
  writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
51

52
  char rev = readRegByte(EREVID);
53
   // microchip forgot to step the number on the silicon when they
54
   // released the revision B7. 6 is now rev B7. We still have
55
   // to see what they do when they release B8. At the moment
56
   // there is no B8 out yet
57
  if (rev > 5) ++rev;
58
  return rev;
59
  
60
}
61

62
void enc28j60::enableChip()
63
{
64
  cli();
65
  SS_PORT &= ~(1 << SS_PIN);
66
}
67

68
void enc28j60::disableChip()
69
{
70
  SS_PORT |= (1 << SS_PIN);
71
  sei();
72
}
73

74
void enc28j60::xferSPI (char data) {
75
  SPDR0 = data;
76
  while (!(SPSR0&(1<<SPIF0)))
77
  ;
78
}
79

80
char enc28j60::readOp (char op, char address) {
81
  enableChip();
82
  xferSPI(op | (address & ADDR_MASK));
83
  xferSPI(0x00);
84
  if (address & 0x80)
85
  xferSPI(0x00);
86
  char result = SPDR0;
87
  disableChip();
88
  return result;
89
}
90

91
void enc28j60::writeOp (char op, char address, char data) {
92
  enableChip();
93
  xferSPI(op | (address & ADDR_MASK));
94
  xferSPI(data);
95
  disableChip();
96
}
97

98
void enc28j60::readBuf(uint16_t len, char* data) {
99
  uint8_t nextbyte;
100

101
  enableChip();
102
  if (len != 0) {
103
    xferSPI(ENC28J60_READ_BUF_MEM);
104
    
105
    SPDR0 = 0x00;
106
    while (--len) {
107
      while (!(SPSR0 & (1<<SPIF0)))
108
      ;
109
      nextbyte = SPDR0;
110
      SPDR0 = 0x00;
111
      *data++ = nextbyte;
112
    }
113
    while (!(SPSR0 & (1<<SPIF0)))
114
    ;
115
    *data++ = SPDR0;
116
  }
117
  disableChip();
118
}
119

120
void enc28j60::writeBuf(uint16_t len, const char* data) {
121
  enableChip();
122
  if (len != 0) {
123
    xferSPI(ENC28J60_WRITE_BUF_MEM);
124
    
125
    SPDR0 = *data++;
126
    while (--len) {
127
      uint8_t nextbyte = *data++;
128
      while (!(SPSR0 & (1<<SPIF0)))
129
      ;
130
      SPDR0 = nextbyte;
131
    };
132
    while (!(SPSR0 & (1<<SPIF0)))
133
    ;
134
  }
135
  disableChip();
136
}
137

138
void enc28j60::SetBank (char address) {
139
  if ((address & BANK_MASK) != Enc28j60Bank) {
140
    writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_BSEL1|ECON1_BSEL0);
141
    Enc28j60Bank = address & BANK_MASK;
142
    writeOp(ENC28J60_BIT_FIELD_SET, ECON1, Enc28j60Bank>>5);
143
  }
144
}
145

146
char enc28j60::readRegByte (char address) {
147
  SetBank(address);
148
  return readOp(ENC28J60_READ_CTRL_REG, address);
149
}
150

151
uint16_t enc28j60::readReg(char address) {
152
  return readRegByte(address) + (readRegByte(address+1) << 8);
153
}
154

155
void enc28j60::writeRegByte (char address, char data) {
156
  SetBank(address);
157
  writeOp(ENC28J60_WRITE_CTRL_REG, address, data);
158
}
159

160
void enc28j60::writeReg(char address, uint16_t data) {
161
  writeRegByte(address, data);
162
  writeRegByte(address + 1, data >> 8);
163
}
164

165
uint16_t enc28j60::readPhyByte (char address) {
166
  writeRegByte(MIREGADR, address);
167
  writeRegByte(MICMD, MICMD_MIIRD);
168
  while (readRegByte(MISTAT) & MISTAT_BUSY)
169
  ;
170
  writeRegByte(MICMD, 0x00);
171
  return readRegByte(MIRD+1);
172
}
173

174
void enc28j60::writePhy (char address, uint16_t data) {
175
  writeRegByte(MIREGADR, address);
176
  writeReg(MIWR, data);
177
  while (readRegByte(MISTAT) & MISTAT_BUSY)
178
  ;
179
}
1
#include "SPI.h"
2
#include <avr/io.h>
3
#include "avr/iom324a.h"
4

5
void SPIInit(void){
6
  DDRB |= (1<<DDB7)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB0);
7
  /*
8
   *  SPCR0:
9
   *    SPIE:  Interrupt ausführen, wenn gesetzt
10
   *    SPE:  SPI Enable
11
   *    DORD:  1=LSB, 0=MSB
12
   *    MSTR:  1=AVR ist Master, 0=AVR ist Slave
13
   *    CPOL:  Clock Polarity
14
   *    CPHA:  Clock Phase
15
   *    SPR:  Clock Rate
16
   */
17
  SPCR0 = ((1<<SPE0)|(1<<MSTR0));
18
  SPSR0 |= (1<<SPI2X0);
19
}
Angehängte Dateien:
Gast #5387191
Lesenswert?

Tobias E. schrieb:
> ist im wesentlichen aus dem Ethercard-Projekt

So so, das Ethercard-Projekt? Es gibt nur eins, und das kennen
wir alle, nicht wahr?

Also nur nicht zu viel Informationen hier bringen, immer schön
den Leser im Dunklen lassen um was es sich handelt.

Ich suche mir die Infos jedenfalls nicht zusammen.
Die enc28j60.h Datei fehlt auch noch ....

Und dann noch: siehe Bild. Bist 8 Jahre hier angemeldet
und solltest wissen was Sache ist.
Angehängte Dateien:
Gast #5387224
Lesenswert?

Tobias E. schrieb:
> (ich poste ihn mal hier direkt rein, dann müsst ihr keine Dateien
> downloaden)
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include "enc28j60.h"
4
#include "SPI.h"
5
#include "UART.h"
6

7
int main(void)
8
{
9
  //UARTInit();
10
  //uart_puts("Bootloader Version 0\n");
11
  //uart_puts("Noch passiert hier nichts...\n");
12
  
13
  //uart_puts("Initialisiere ENC28J60...\n");
14
  char ver = enc28j60::init();
15
  //uart_putc(ver);
16
  
17
    while (1) 
18
    {
19
    
20
    }
21
}

Zunächst musst du mal lernen was (im Sinne von C-Programmierung)
eine Klasse ist, und dass man eine Klasse, wenn man sie benutzen
will, instanzieren muss.

Beispiele dazu gibt es in dem Projektverzeichnis.
Um zu verstehen was eine Klasse ist musst du ein Buch
über C++ lesen.
Gast #5387229
Lesenswert?

Michael U. schrieb:
> Hallo,
>
> fast schrieb:
>> Tobias E. schrieb:
>>> MISO vom AVR auf SO vom ENC, ist doch richtig, oder?
>
> Ja, ist richtig.
>
>> MOOOOOOOSI bedeutet „Master Out Slave in“
>> und passt zu SO (Slave out)
>
> Häääää???
>
> Gruß aus Berlin
> Michael

Danke, ich fing schon an zu zweifeln :)

Berlin ist übrigens eine sehr geile Stadt :D

@Bescheidener Beobachter (Gast)

Ok, C++ ist tatsächlich neu für mich. Aber daran liegt es hier doch 
nicht, oder?
OP #5387350
Lesenswert?

fast schrieb:
> versuch mal kurz
> DDRB = (1<<DDB7)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB0);
> anstatt
> DDRB |= (1<<DDB7)|(1<<DDB5)|(1<<DDB4)|(1<<DDB3)|(1<<DDB0);

funktioniert leider auch nicht... da hatte ich schon ziemlich viele 
Kombinationen durchprobiert...
Was ich vorhin vergessen hatte zu erwähnen: Mir ist noch aufgefallen, 
dass wenn DDB4 auf 0 steht, also Eingang ist, dann bekomme ich nicht 
einmal diese kleinen Zacken... Da bleibt die gelbe Linie ziemlich 
konstant...

Also mal angenommen, ich hätte beim löten was versaut... wo müsste ich 
dann am ehesten gucken? Ich habe schon versucht, mit dem Finger die Pins 
vom ENC auf die Platine zu drücken, aber auch das hat nichts geändert...
Gast #5387598
Lesenswert?

Ich betreibe das ganze mit 3,3V, also das sollte schon hinkommen.

Aber mir ist gestern Abend beim rumprobieren noch etwas aufgefallen: 
wenn ich den ISP-progammer abziehe, dann fällt das signal runter auf 0V, 
hat aber immer noch diese zacken. Und wenn man sich das Signal mal 
anschaut sieht das ja auch nicht aus wie sinnvolle Daten, sondern eher, 
als wenn hier das sck-signal überspricht... ich mess heute abend mal 
nach, ob die beiden Signale synchron sind.

Wenn ja, dann überprüfe ich noch mal die Lötstelle am ENC.
#5387613
Lesenswert?

@Tobias E. (Gast)

>Aber mir ist gestern Abend beim rumprobieren noch etwas aufgefallen:
>wenn ich den ISP-progammer abziehe,

Welchen denn? Wenn das eine Billiggurke ist, dann macht der kein 
Tristate und blockiert dir das SPI.

>hat aber immer noch diese zacken. Und wenn man sich das Signal mal
>anschaut sieht das ja auch nicht aus wie sinnvolle Daten, sondern eher,

Eben. Das ist keine Digitalsignal, denn man hat nur ein paar 100mV 
Amplitude. Du mißt ein Artefakt. Das kann aber auch am Tastkopf liegen, 
wenn der Klemmhaken nicht richtig kontaktiert ist.

>als wenn hier das sck-signal überspricht... ich mess heute abend mal
>nach, ob die beiden Signale synchron sind.

Miß einfach mal ALLE 4 SPI-Signale, dort muss auf JEDEM Signal ein 
sauberer Pegel mit HIGH/LOW anliegen.
Gast #5387658
Lesenswert?

Also der Programmieradapter ist eher ein preiswertes Modell, von diamex, 
aber bei reichelt bestellt, kein China-Teil.
Mein oszilloskop ist auch ein digilent analog discovery 2. Eigentlich 
ganz ok, aber kein Profi-werkzeug.
SCK und MOSI sehen gut aus, CS ist etwas schwierig zu messen, weil ich 
nichts fest anschließen kann. Ich probiere es nachher aber nochmal. Mit 
meinem oszilloskop kann ich aber maximal 2 Kanäle gleichzeitig messen. 
Aber ich probiere es heute Nachmittag mal.

Die Spannung ist eigentlich stabil, sie schwankt nur im mV Bereich. Ich 
gucke heute Nachmittag mal, ob ich zum probieren auch mal 5 V 
anschließen kann.
Gast #5387703
Lesenswert?

Die gelbe Linie sieht ganz und gar nicht stabil aus. Ich sehe da HF 
Anteile drin. Die folgenden Tips beziehen sich darauf, auch wenn sie 
dein Hauptproblem nicht lösen solltest du sie trotzdem umsetzen:

Der AVR sollte 4 100nF Abblock-Kondensatoren bekommen. Für jedes VCC/GND 
sowie AVCC/GND Paar einen eigenen.

Am ESP-12 Modul fehlt ein 100µF oder 220µF Pufferkondensator an VCC/GND.

Beim ESP-12 Modul gehört ein Widerstand (z.B. 2,2k Ohm) zwischen GPO15 
und GND, da der Pin beim Start kurzzeitig als Ausgang mit "flackerndem" 
Signal angesteuert wird.
#5388021
Lesenswert?

Hallo,

Stefanus F. schrieb:
> Am ESP-12 Modul fehlt ein 100µF oder 220µF Pufferkondensator an VCC/GND.

von welchem ESP sprichst Du?
Er will einen ENC28J60 LAN-IC in Gang bringen.

Oh gerade auf seinen Schaltplan geschaut: der hat aber mit dem Thread so 
rein garnichts zu tun...

@Tobias E. (tobinator): hast Du auch den Schaltplan zu Deinem Projekt?
Sind das Module oder Eigenbau von Dir?

Gruß aus Berlin
Michael
Gast #5388034
Lesenswert?

Der schaltplan ist genau wie in der pdf, nur das das esp-modul nicht 
eingelötet ist. Ist auch eine Eigenentwicklung von mir.
Die platine hab ich bei elecrow fertigen lassen und selbst bestückt. Und 
meine Vermutung ist gerade, das da beim smd-löten was schief gegangen 
ist...
Gast #5388148
Lesenswert?

> von welchem ESP sprichst Du? ... der hat aber mit dem Thread so
> rein garnichts zu tun...

Wenn er denn bestückt gewesen wäre, hätte er einen Einfluss auf die 
Stabilität der Versorgungsspannung gehabt, was diese zacken in der 
gelben Linie hervorrufen könnte.

Das dies nicht sein Haupt-Problem löst, hatte ich selbst dazu 
geschrieben.
#5388200
Lesenswert?

Hallo,

Tobias E. schrieb:
> Der schaltplan ist genau wie in der pdf, nur das das esp-modul nicht
> eingelötet ist. Ist auch eine Eigenentwicklung von mir.

ok, hatte mir nicht das ganze pdf angeschaut...

Frage: der Quarz ist auch ein 25MHz Grundwellenquarz und nicht 
versehentlich ein Oberwellenquarz? Der würde in dieser Schaltung nicht 
gehen, weil er auf 8,xxx MHz schwingen würde.
Die Kennzeichnung ist leider nicht mehr so sicher wie früher:
Frequenzangabe in kHz Grundwellenquarz, in MHz Oberwellenquarz.
Macht nur leider nicht mehr jeder Quarzhersteller so.

Gruß aus Berlin
Michael
#5388343
Lesenswert?

Hallo,

Tobias E. schrieb:
> Das müsste doch
> dann ein Grundwellenquarz sein, oder?

ja, sollte passen. Das Herstellerdatenblatt sagt auch daß sie erst ab 
27MHz Oberwellenquarze machen.
Fällt mir im Moment nichts weiter ein. Wenn der ENC28J60 Spannung und 
Takt hat geht SPI auch. Normalerweise... Zumindest hatte ich damals 
damit nie Probleme.

Eigentlich kann nur /CS nicht passend ankommen wäre zumindest mein 
Verdacht.

Gruß aus Berlin
Michael
OP #5388382
Lesenswert?

Hab jetzt gerade nochmal nachgemessen:

Also wenn ich nicht aus versehen den falschen Pin erwischt habe, dann 
hängt der CS-Pin auf ca. 2,4V... Ich habe dann mal was anderes drauf 
geflasht, quasi alle Pins an Port B im 100 ms Takt an und aus machen, 
und es ist immer noch das selbe... Am SCK-Pin sehe ich den 100 ms Takt 
wunderbar, aber am CS-Pin nicht...

Mein Code:
1
#define F_CPU 3125000UL
2

3
#include <avr/io.h>
4
#include <util/delay.h>
5

6
int main(void)
7
{
8
DDRB = 0xff;
9
    while (1) 
10
    {
11
        PORTB = 0xff;
12
        _delay_ms(100);
13
        PORTB = 0x00;
14
        _delay_ms(100);
15
    }
16
}

Wie kann denn das sein? Ich verzweifel hier noch an dem Zeug...
Angehängte Dateien:
OP #5390325
Lesenswert?

@Karl M:

Ja, danke, du hast recht... Ich hab mich auch schon gewundert, aber 
nicht weiter nachgeguckt... Hab mich einfach gefreut, dass die 
delay-Funktion halbwegs passt... Aber ich hab tatsächlich die Quarze 
vertauscht...

@Alle anderen:

Jetzt geht es... es muss wohl wirklich eine Lötstelle gewesen sein.
Vielen Dank für eure Hilfe

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren