Forum: Mikrocontroller und Digitale Elektronik SPI problem myEthernet ATmega644p ENC28J60


von Manfred B. (manni-b)


Lesenswert?

Hallo,

mein myEthernet greift (vorgegeben) mit USART1 in SPI Mode auf den ENC 
zu.
PIN D2=MISO=RX;
D3=MOSI=TX;
D4=SCK=XCK;
D5=invCS;

Initialisierung:

UBRR1=0;//Baud Register erst auf null setzten
SPI2_DDR |= (1<<4);//Clock Ausgang
SPI2_DDR &=~ (1<<SPI2_MISO); //MISO Eingang
SPI2_DDR |= (1<<SPI2_MOSI);//MOSI Ausgang
SPI2_DDR |= (1<<5);//CS Ausgang

UCSR1C = (1<<UMSEL11) | (1<<UMSEL10) | (0<<UCPHA1) | (0<<UCPOL1);//MSPI 
//Mode, SPI Mode 0
UCSR1B = (1<<RXEN1) | (1<<TXEN1);//enable Receiver and Transmitter
UBRR1 = 129;//Baudrate 9600
SPI_DISABLE(); //=CS high

//Es soll zur Probe ein Register aus dem ENC ausgelesen werden
//Nach Reset ist das ERXFCON Register 10100001
//Um den ENC zu lesen wird der OPcode und die Adresse des Registers an 
den ENC gesendet. Dieser antwortet (in diesem Fall) ohne Dummybyte 
direkt mit dem Inhalt des Registers.

SPI_ENABLE();//CS low
//  _delay_ms(1);
dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
reg=(op | (addr & ENC28J60_ADDR_MASK));//RCR register
UDR1 =reg;//sends data; hier:00011000 =  Op code und adressse =read 
ERXFCON
while ( ! (UCSR1A & (1<<RXC1)) );//wait for data to be received
value=UDR1;
SPI_DISABLE();//CS wieder high

DDRA=0xff;//Port A (LEDs-Extern)=Ausgang;
PORTA=value; //Wert zur Kontrolle an die 8 LEDs ausgeben

Nun zum Problem:
Ich bekomme vom UDR1 Register immer nur 0x00 zurück und nicht den Wert, 
den ich von dem abgefragten Register erwarte.
Dass die Register richtig definiert sind und dass die Bits richtig 
gesetzt werden habe ich mit debugging überprüft.

Hat jemand Rat?

Gruß
Manni

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

soweit ich sehen kann sollte es gehen, um auszuschließen, das es am ENC 
liegt, kannst du RX ja mal mit TX verbinden - CS lässt du deaktiviert. 
Damit solltest du das gesendete wieder empfangen.

Sascha

von holger (Gast)


Lesenswert?

>//Um den ENC zu lesen wird der OPcode und die Adresse des Registers an
>den ENC gesendet. Dieser antwortet (in diesem Fall) ohne Dummybyte
>direkt mit dem Inhalt des Registers.

Das halte ich für Blödsinn. Woher soll der ENC wissen
welches Register er lesen soll ohne vorher den Opcode
gesendet zu haben? Das wär ja so als könnte er eine
Antwort raten ohne die Frage zu kennen.

Schick das Dummybyte und lies dann noch mal.

von DrerryProw (Gast)


Lesenswert?

home

von Manfred B. (manni-b)


Lesenswert?

Habe Tx und Rx verbunden.
Damit konnte ich meine gesendete Adresse und opcode selbst empfangen.

@Holger: Der ENC sendet bei Abfragen des MAC Registers erst ein 
Dummybyte, gefolgt von dem Inhalt des MAC registers.
Bei dem abgefragten Ethernet-Register sollte aber sofort der Inhalt 
folgen.


Einen Fehler habe ich schon korrigiert:
Ich habe bisher versucht aus dem falschen Register zu lesen, da es sich 
um ein Bank1 Register handelt. Und nach einem Reset liest der ENC 
erstmal von Bank0.
Habe daraufhin versucht das ERDPTH-Register zu lesen.
das sollte nach Reset nicht null sein.

Ich lese aber immer nur 0x00 aus.

Muss ich den ENC noch zusätzlich irgendwie Initialisieren?
Software-Reset?


Gruß

von holger (Gast)


Lesenswert?

>Bei dem abgefragten Ethernet-Register sollte aber sofort der Inhalt
>folgen.

Wo steht das im Datenblatt? Tut mir leid ich finde das nirgends.
Die Timingdiagramme sagen auch was anderes.

von Manfred B. (manni-b)


Lesenswert?

Seite 27 ENC28J60 user guide:
if the 5 bit address is an ETH Register, then the data in the selected 
register will start shifting out immediately.

von holger (Gast)


Lesenswert?

>Seite 27 ENC28J60 user guide:
>if the 5 bit address is an ETH Register, then the data in the selected
>register will start shifting out immediately.

Ja, aber erst wenn der Opcode komplett übertragen wurde.
Das rausshiften musst du mit dem senden eines Dummybytes machen.
Sonst werden keine Clock Impulse für das SPI generiert.

Aber was rede ich, du willst ja nicht.
Dein Problem hätte vor 10 Minuten gelöst sein können.

von J.-u. G. (juwe)


Lesenswert?

Manfred Brunner schrieb:
> Seite 27 ENC28J60 user guide:
> if the 5 bit address is an ETH Register, then the data in the selected
> register will start shifting out immediately.

Dann schau Dir mal die Abbildung 4-3 auf dieser Seite an, dann siehst 
Du, dass die Daten erst ab dem 8.Takt übertragen werden. Also erst nach 
mit dem 2.Byte.

von Manfred B. (manni-b)


Lesenswert?

Jetzt verstehe ich was ihr meint.
Probier ich gleich.

von Manfred B. (manni-b)


Lesenswert?

Ich dachte ich habs verstanden.
Hab den Code abgeändert:

SPI_ENABLE();//CS low
_delay_ms(1);
dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
reg=(op | (addr & ENC28J60_ADDR_MASK));//RCR register
UDR1 =reg;//sends data from transmit buffer to ENC: opcode und adress

UDR1=dummy;//sendet weiterhin clock
//gleichzeitig wird das Register vom ENC gelesen


 while ( ! (UCSR1A & (1<<RXC1)) );//wait for data to be received (from 
ENC)
value=UDR1;

 SPI_DISABLE();//CS wieder high

value liest aber immer nur null aus;


Sollte der code so in Ordnung sein?

von holger (Gast)


Lesenswert?

Wenn du in UDR1 schreibst musst du warten bis die Daten raus sind.
Du kannst da nicht einfach kurz nacheinander reinschreiben.

von Manfred B. (manni-b)


Lesenswert?

Habe jetzt vor dem Dummybyte den transmitbuffer geleert:



dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
UDR1=dummy;//sendet weiterhin clock
//gleichzeitig wird das Register vom ENC gelesen

usw..

Funktioniert aber immer noch nicht.

von holger (Gast)


Lesenswert?

>Habe jetzt vor dem Dummybyte den transmitbuffer geleert:

Lass das sein.

von Manfred B. (manni-b)


Lesenswert?

SPI_ENABLE();//CS low
_delay_ms(1);
dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
reg=(op | (addr & ENC28J60_ADDR_MASK));//RCR register
UDR1 =reg;//sends data from transmit buffer: opcode und adress
while ( ! (UCSR1A & (1<<RXC1)) );//wait for data to be received (from 
ENC)
 value=UDR1;

//dummybyte senden damit clock weiterläuft
dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
UDR1=dummy;//sendet weiterhin clock
//gleichzeitig wird das Register vom ENC gelesen
while ( ! (UCSR1A & (1<<RXC1)) );//wait for data to be received (from 
ENC)
value=UDR1;


// jetzt wird adresssiertes register ausgelesen
dummy=UDR1;//Transmit buffer leeren
while ( ! (UCSR1A & (1<<UDRE1)) );//Wait for empty transmit buffer
UDR1=dummy;//sendet weiterhin clock
//gleichzeitig wird das Register vom ENC gelesen
while ( ! (UCSR1A & (1<<RXC1)) );//wait for data to be received (from 
ENC)
value=UDR1;
SPI_DISABLE();//CS wieder high


Es hat geklappt.
Ich konnte erfolgreich ein Register (ECON2) auslesen.

Ich danke euch.

von J.-u. G. (juwe)


Lesenswert?

holger schrieb:
> Wenn du in UDR1 schreibst musst du warten bis die Daten raus sind.
> Du kannst da nicht einfach kurz nacheinander reinschreiben.

Doch, das geht. UDR1 ist doppelt gepuffert. Ein 16-Bit Transfer kann 
durchgeführt werden, indem 2 Bytes direkt hintereinander in UDR1 
geschrieben werden.

Aber:
Um zu prüfen, ob die Datenübertragung abgeschlossen wurde, darf dann 
nicht das RXC1-Bit (Receive complete) abgefragt werden (dieses wird 
schon nach dem ersten empfangenen Byte gesetzt). Es muss das TXC1-Bit 
(Transmit Complete) im UCSR1A-Register abgefragt werden. Dieses wird 
nämlich erst dann gesetzt, wenn beide Bytes übertragen wurden.

Aber Manfred hat es ja jetzt mit zwei hintereinander ausgeführten 1-Byte 
Transfers hinbekommen.

von holger (Gast)


Lesenswert?

>> Wenn du in UDR1 schreibst musst du warten bis die Daten raus sind.
>> Du kannst da nicht einfach kurz nacheinander reinschreiben.

>Doch, das geht. UDR1 ist doppelt gepuffert. Ein 16-Bit Transfer kann
>durchgeführt werden, indem 2 Bytes direkt hintereinander in UDR1
>geschrieben werden.

Ja, da hast du recht. Das Problem ist nur ob man sicher stellen
kann das nicht vorher schon mal jemand in UDR1 geschrieben hat.
Wenn nicht muss UDRE1 abgefragt werden.

Ansonsten ist SPI über UART wegen des Double Buffers sogar schneller
als das reine SPI Modul. Man muss halt aufpassen was man tut;)

von J.-u. G. (juwe)


Lesenswert?

holger schrieb:
> Ja, da hast du recht. Das Problem ist nur ob man sicher stellen
> kann das nicht vorher schon mal jemand in UDR1 geschrieben hat.
> Wenn nicht muss UDRE1 abgefragt werden.

UDRE1 sollte vor jedem Transfer abgefragt werden, egal ob 8 oder 16 Bit 
zu übertragen sind.

> Ansonsten ist SPI über UART wegen des Double Buffers sogar schneller
> als das reine SPI Modul.

Ein weiterer Vorteil ist, dass die Clockfrequenz viel feiner einstellbar 
ist.

von Misha (Gast)


Lesenswert?

ich vor einiger Zeit recht bereistegt die Buchreihe von Suzanne Collins 
gelesen hatte, war ich sehr gespannt auf den ersten Film der Serie. Ich 
hatte zwar beffcrchtet das

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.