Forum: Mikrocontroller und Digitale Elektronik atmega8 spi problem


von Bernhard (Gast)


Lesenswert?

Hallo an alle!

Habe gestern versucht, einen SPI Slave mit dem ATmega8 anzusteuern(als 
Master konfiguriert).


Dachte, dass sei eine ganz einfache Übung, zumal auch im Dtaenblatt 
Codeexamples vorhanden sind.

Habe das genau so abgekupfert, der c ist als master konfiguriert, SPI 
ist enabled.

Ich ziehe also den SS pin "manuell" auf "Low" (weil µc ja im master 
mode) und schiebe dann drei Bytes in das SPI Datenregister.

Danach ziehe ich die SS Leitung wieder auf "high".

Dummerweise passiert auf meiner SCK leitung überhaupt nichts (Immer 
"high").

Habe aber die Pins MOSI, SCK und SS als Ausgang definiert.


Mir fällt einfach keine Fehlerquelle mehr ein.

hat jemand einen Tipp, was ich da noch übersehen könnte?

Danke ;-)

von Matthias L. (Gast)


Lesenswert?

Poste mal den gesamten Code

von crazy horse (Gast)


Lesenswert?

Falls Bascom: da ist ein Bug im Compiler.
Ansonsten: Programm einstellen.

von Bernhard (Gast)


Lesenswert?

OK, hab leider nun leider den Code nicht bei der Hand aber die paar 
Zeilen habe ich glaub ich noch im Kopf(hoffentlich ;-) )


Sieht etwas so aus:



void writeFrame(char *frame)
{
   PORTB &= ~(1<<PB2);

   for(i=0;i<3;i++)
  {
    SPDR = *frame;
    while(!(SPSR & (1<<SPIF)));
    frame++;
  }

 PORTB |= (1<<PB2);

}


Im void main ist dann der Aufruf:

char frame[3];

frame[0] = 0x02;
frame[1] = 0x06;
frame[2] = 0x55;


//MOSI, SS and SCK as Output
DDRB = (1<<PB2) | (1<<PB3) | (1<<PB5);

//Enable SPI
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0) | (1<<DORD);

writeFrame(frame);


Hoffe, hab nun aus dem Kopf heraus nichts vergessen....

von Falk B. (falk)


Lesenswert?

@ Bernhard (Gast)

>Dachte, dass sei eine ganz einfache Übung, zumal auch im Dtaenblatt
>Codeexamples vorhanden sind.

AVR-Tutorial: Schieberegister

>OK, hab leider nun leider den Code nicht bei der Hand aber die paar
>Zeilen habe ich glaub ich noch im Kopf(hoffentlich ;-) )

Sowas kannst du dir sparen. Es kommt da auf jedes Detail an. Entweder 
originalen Quelltext oder gar nichts.

MFG
Falk

von Steffen (Gast)


Lesenswert?

Hast du deine Interrupts eingeschaltet (im SREG)???
1
    while(!(SPSR & (1<<SPIF)));

Falls du das Bit SPIF im SPI-Comtrollregister ließt, ohne den Interrupt 
einzuschalten, bis du in einer Edenlosschleife !?!

von Jörg X. (Gast)


Lesenswert?

Im Gegenteil: wenn du den Interrupt aktivierst (SPIE und sei()), landest 
du wahrscheinlich in einer Endlosschleife, weil das flag sofort von der 
ISR gelöscht wird ;)

sry for klugscheißing
-Jörg

von Bernhard (Gast)


Lesenswert?

Ok, sorry!

Werde heute Abend den Originalcode posten ;-)

Danke erstmal!

von ---=DIAN=--- (Gast)


Lesenswert?

Hallo,

Der Code sollte OK sein, das Datenblatt von Atmel ist da etwas 
bescheiden geschrieben.

Zitat von Dir:

"Ich ziehe also den SS pin "manuell" auf "Low" (weil µc ja im master
mode) und schiebe dann drei Bytes in das SPI Datenregister."

Schau dir mal den Inhalt vom SPSR Register an - ist das WCOL bit gesetzt 
wenn du versuchst zu schreiben?

Habe vor ein paar Tagen dasselbe gehabt. Atmel als Master, SD-Card als 
Slave, SS Pin als Chip select. Das geht mal definitiv NICHT!

Der SS-PIN darf im Mastermodus NICHT low sein während der Master senden 
will.

SS Pin Low bedeutet ein anderer Master versucht zu senden. Nehm einfach 
nen anderen Pin und sorge dafür das SS High ist und bleibt
{ DDRB|=(1<<SS-PIN) PORTB|=(1<<SS-PIN) }

Das sollte helfen

Gruß

---=DIAN=---

von Johannes M. (johnny-m)


Lesenswert?

---=DIAN=--- wrote:
> Der SS-PIN darf im Mastermodus NICHT low sein während der Master senden
> will.
Solange er als Ausgang konfiguriert ist, ist das völlig egal. Er darf 
nur nicht Eingang und Low sein.

von Berhard (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

So, der Vollständigkeit halber nun hier mein ganzes AVRStudio project im 
anhang!

Vielleicht kommt da ja noch ein Fehler zu Tage ;-)

Bitte um eure Hilfe.

Lg,
Bernhard

von ---=DIAN=--- (Gast)


Lesenswert?

Ok, ich hab zwar nen Mega32, aber da sollte es wohl gleich sein.

Komischerweise klappt bei     DDRB|=(1<<SS) PORTB|=(1<<SS)    die SPI 
Kommunikation und bei    DDRB|=(1<<SS) PORTB&=~(1<<SS)
eben nicht mehr, dann bekomme ich WCOL ohne Ende.

Hab's ja selbst probiert, das Tutorial im Datenblatt funzt nicht, wenn 
man SS auf low zieht, weiß ich warum....

---=DIAN=---

von Berhard (Gast)


Lesenswert?

Gut, aber wenn ich das datenblatt richtig verstanden haben, muss sich 
der Coder selbst um das chipsselect signal kümmern,  wenn der avr im spi 
master modus arbeitet.

Aber das man den eigentlich dazu gedachten SS pin nicht benutzen kann, 
gibt es eigentlich nicht (sorry, ich weiß du sagtest, du hast es 
ausprobiert).

Aber da ist dann doch irgendetwas faul oder?

Grüße

von Johannes M. (johnny-m)


Lesenswert?

Berhard wrote:
> Gut, aber wenn ich das datenblatt richtig verstanden haben, muss sich
> der Coder selbst um das chipsselect signal kümmern,  wenn der avr im spi
> master modus arbeitet.
Richtig.

> Aber das man den eigentlich dazu gedachten SS pin nicht benutzen kann,
> gibt es eigentlich nicht (sorry, ich weiß du sagtest, du hast es
> ausprobiert).
Nein, der Pin ist nicht dafür gedacht. SS\ ist immer ein Eingangssignal, 
über das der jeweilige Slave vom Master aktiviert wird. Der Master 
selbst hat kein Slave Select, weil er eben kein Slave ist. Er muss aber 
über entsprechende Datenleitungen den Slave Select-Eingang des Slaves, 
mit dem er sprechen will, ansteuern. Da der Master selbst kein Slave 
Select hat, wird der Pin im Master-Modus auch eigentlich nicht 
verwendet. Und (lt. Datenblatt) ist er auch, wenn er als Ausgang 
konfiguriert ist, als allgemeiner Ausgang nutzbar (ob man damit jetzt 
den Slave Select eines der angeschlossenen Slaves ansteuert, bleibt dem 
Nutzer überlassen). Nur wenn SS\ als Eingang konfiguriert ist, hat er 
auch im Master-Modus eine Funktion, nämlich den Master in den 
Slave-Modus zu schalten, wenn der Pin auf Low gezogen wird. Dies soll 
den Aufbau eines "Pseudo-Multi-Master-Systems" ermöglichen. "Pseudo" 
deshalb, weil es bei SPI immer nur einen Master geben kann und deshalb 
alle Master, die von einem anderen als Master konfigurierten Teilnehmer 
angesprochen werden, sofort in den Slave-Modus schalten müssen. (Ist wie 
bei Highlander: Es kann nur einen geben...).

> Aber da ist dann doch irgendetwas faul oder?
Wenn sich das so verhält, wie  ---=DIAN=--- es oben beschrieben hat, 
dann ist tatsächlich etwas faul. Es besteht dann zumindest ein 
Widerspruch zwischen Realität und Dokumentation (Datenblatt)...

von ---=DIAN=--- (Gast)


Lesenswert?

schon probiert ?

von Berhard (Gast)


Lesenswert?

Hy!

Habe dieses Verhalten noch nicht probiert(besser gesagt, keine 
Gelegenheit dazu).

Ich habe bei mir zuhause kein Oszilloskop oder ähnliches zur Verfügung 
und ohne allem tu ich mir etwas schwer, Diagnosen zu stelllen.

Eigentlich sollte ich die SPI Ansteuerung heute schon fertig haben, aber 
was soll man machen ;-)

Hab mich nur gewundert, warum der Slave nicht antwortet, bis ich heute 
morgen gesehen habe, dass da ja gar nichts rauskommt aus meinem AVR :-P

Trotzem: Was mir noch fehlt , ist herauszufinden, was der Fehler in 
meinem Programm ist (Programm ist für diese paar Zeilen eigentlich 
übertrieben,...)


Johannes, hast du einen Blick auf den Code geworfen und ist dir etwas 
aufgefallen?

Kann durchaus sein, dass ein ganz dummer Fehler dahintersteckt, bin 
quais Anfänger :-)


Danke.

Lg,
Bernhard

von Falk B. (falk)


Lesenswert?

@ Berhard (Gast)

>Hab mich nur gewundert, warum der Slave nicht antwortet, bis ich heute
>morgen gesehen habe, dass da ja gar nichts rauskommt aus meinem AVR :-P

Wie hast du das ohne Oszi gesehen?

>Kann durchaus sein, dass ein ganz dummer Fehler dahintersteckt, bin
>quais Anfänger :-)

Dein Programm sieht erstmal gut aus. Ich kann keinen Fehler entdecken. 
Wenn gleich man einige Sachen takisch besser machen kann/sollte. Die 
Defines für die Register des SPI-Moduls sind Quark. Sinnvoll sind eher 
defines für die Pins des SPI-Moduls, weil die auf jedem AVR anders 
liegen. Siehe AVR-Tutorial: Schieberegister . Und wenn eine Funktion 
SPIWriteByte() heisst, dann sollte sie auch das machen was der Name 
sagt, nämliche EIN Byte senden. Du sendest aber mehrere. Die Anzahl 
sollte man als Parameter übergeben und nicht fest kodieren.

Das ist nicht gut, da entstehen ggf. zu grosse Rundungsfehler

#define UBBR_VAL  F_CPU/16/BAUD-1

besser so wie hier

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#UART_initialisieren

Ausserdem sind deine Headerfiles ein ziemliches Kauderwelsch, es werden 
verschiedene Files mehrfach eingebunden, das kann auch mal daneben 
gehen, z.B. mit globalen Variablen.

MFG
Falk

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.