SPI will auf AVR nicht laufen

#6421531
Lesenswert?

Hallo,

versuche gerade einen Hardware SPI für ein späteres Projekt zum laufen 
zu bringen.

Habe mir schon das originale Datenblatt durchgelesen und sämtliche 
Beispielprojekte ausprobiert, aber der SPI will nicht gehen.

MOSI ist dauernd auf High
CK ist auch nur auf HIGH
UND SS pulsiert wie gewollt.

Ist evtl. einfach mein uC kaputt?

uC = ATMega328P

Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
void SPI_MasterInit(void)
5
{
6
  /* Set MOSI and SCK output, all others input */
7
  DDRB = (1<<5) | (1<<3) | (1<<2);
8
  /* Enable SPI, Master, set clock rate fck/16 */
9
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
10
}
11

12
void SPI_MasterTransmit(char cData)
13
{
14
  /* Start transmission */
15
  SPDR = cData;
16
  /* Wait for transmission complete */
17
  while(!(SPSR & (1<<SPIF)));
18
}
19

20
int main(void)
21
{
22
  
23
  SPI_MasterInit();
24

25
  
26
  while(1)
27
  {
28
     PORTB &= ~(1<<2);
29
     SPI_MasterTransmit(0xAB);
30
     PORTB |= (1<<2);
31
  }
32
}
#6421554
Lesenswert?

Maci M. schrieb:
> DDRB = (1<<5) | (1<<3) | (1<<2);

Das ist unschön. Besser wäre es:
1
#define SPI_SS PB2
2
#define SPI_MOSI PB3
3
#define SPI_SCK PB5
4

5
DDRB |= (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_SS);


> MOSI ist dauernd auf High
> CK ist auch nur auf HIGH
> UND SS pulsiert wie gewollt.

Kann sein, daß SPI_MasterTransmit(0xAB); vom Compiler wegoptimiert 
wurde.
Du kannst in Simulator Assembler-Code ankucken, dort siehst du das 
genau. Ansonsten arbeitet so ein Programm oft anders als vollwertige. 
Compiler ist klug. Er sieht, daß hier nichts gemacht wird. Deshalb 
optimiert er vieles weg.
Moderator (Firma: Titel) Persönliche Seite #6421555
Lesenswert?

Maci M. schrieb:
> SS pulsiert wie gewollt.
Mit welchem zeitlichen Ablauf?

> Ist evtl. einfach mein uC kaputt?
Bei mir waren das in 99,9% irgendwelche Programmfehler. Ich probiere in 
so einem Fall einfach mal einen anderen µC aus...

Maxim B. schrieb:
> Compiler ist klug. Er sieht, daß hier nichts gemacht wird.
Natürlich wird da was gemacht. Das Programm soll aussen am Controller 
einen Pegelwechsel erzeugen. Den darf er niemals wegoptimieren. 
Bestenfalls eine Codefolge, die keinerlei Aussenwirkungen hat, darf 
weggelassen werden. Eine Änderung des zeitlichen Ablaufs gilt hier nicht 
als Auswirkung, weil ein C-Programm keine Zeit "braucht" oder innehat.
#6421569
Lesenswert?

Lothar M. schrieb:
> Das Programm soll aussen am Controller
> einen Pegelwechsel erzeugen. Den darf er niemals wegoptimieren.
> Bestenfalls eine Codefolge, die keinerlei Aussenwirkungen hat, darf
> weggelassen werden.

Bei TO wird ja SS-Pegel geändert, nur ISP sendet nichts. So haben Sie 
recht: was außen am Controller einen Pegelwechsel erzeugt, das bleibt. 
Anders mit SPI. Deshalb war meine erste Gedanke: wegoptimiert.
Wenn das Programm etwas größer würde und SPI mit verschiedenen Daten 
hantierte oder mindestens mit Variablen, die sich im Laufe ändern, dann 
wäre Wegoptimieren weniger wahrscheinlich.
Gast #6421571
Lesenswert?

Maci M. schrieb:
> /* Set MOSI and SCK output, all others input */
>   DDRB = (1<<5) | (1<<3) | (1<<2);
Du setzt außer MOSI und SCK noch einen Pin. Wahrscheinlich SS. Nur mal 
so als Idee, lass SS oder benutze einen anderen Pin. Vielleicht gibt es 
da Probleme. Sollte es eigentlich nicht, aber wer weiß.
#6421586
Lesenswert?

Dussel schrieb:
> Maxim B. schrieb:
>> wenn SS als Eingang bleibt und
>> zufällig (z.B. durch Störungen) "0" bekommt, dann schaltet SPI
>> automatisch auf Slave.
> Meine Befürchtung war, dass durch irgendein Zusammenspiel SPI in den
> Slavemodus schaltet.

TO sollte Assembler-Code ankucken. Erst dann gibt es mehr Klarheit.

Meine Erfahrung: so kurze Prüfabschnitte bringen nichts. Man sollte 
etwas mehr einprogrammieren, um keine realitätsfremden Ergebnisse zu 
bekommen. Oder auch Optimieren vollständig abschalten.
#6421589
Lesenswert?

Dussel schrieb:
> Maci M. schrieb:
>> /* Set MOSI and SCK output, all others input */
>>   DDRB = (1<<5) | (1<<3) | (1<<2);
> Du setzt außer MOSI und SCK noch einen Pin. Wahrscheinlich SS. Nur mal
> so als Idee, lass SS oder benutze einen anderen Pin. Vielleicht gibt es
> da Probleme. Sollte es eigentlich nicht, aber wer weiß.

Habe es sogar schonmal komplett ohne ss versucht, geht auch nicht.

Gehe immer mit dem oszi an die Ports aber sehe nichts
#6421605
Lesenswert?

Das ist für eine wirkliche Probe zu kurz:
1
int main(void)
2
{
3
  
4
  SPI_MasterInit();
5

6
  
7
  while(1)
8
  {
9
     PORTB &= ~(1<<2);
10
     SPI_MasterTransmit(0xAB);
11
     PORTB |= (1<<2);
12
  }
13
}

Besser etwa so:
1
unsigned char a=0, b=201;
2
unsigned int c=0;
3

4
int main(void)
5
{
6
  
7
  SPI_MasterInit();
8

9
  
10
  while(1)
11
  {
12
     PORTB &= ~(1<<2);
13
     SPI_MasterTransmit((unsigned char)(c>>8));
14
     SPI_MasterTransmit((unsigned char)c);
15
     PORTB |= (1<<2);
16
     a++;
17
     b--;
18
     c=a*b;
19
  }
20
}

Hier ist Wahrscheinlichkeit, daß etwas wegoptimiert wird, viel geringer.
Beitrag #6421614 wurde von einem Moderator gelöscht.
#6421643
Lesenswert?

PB2 ist der Chipselect vom Atmega328. Wird der angeknusbert denkt der 
Atmega328, dass er ein Slave ist und wartet, dass der Pseudo-Master mal 
was sagt ;)

Ist jetzt nur so das, was mir beim Überfliegen auffiel und ist IMO ne 
beliebte "Falle" bei Atmega328 und seinen Freunden ;)

Hier mal ein Ausschnitt aus dem Datenblatt des Atmega328PB dazu:

If SS is configured as an input, it must be held high to ensure master 
SPI operation. If the SS pin is driven low by peripheral circuitry when 
the SPI is configured as a master with the SS pin defined as an input, 
the SPI system interprets this as another master selecting the SPI as a 
slave and starting to send data to it. To avoid bus contention, the SPI 
system takes the following actions:

Aus dem Kapitel 23.3.2 des aktuellen Datenblatts
(Firma: Vescomp) #6421760
Lesenswert?

Falk B. schrieb:
> Maci M. schrieb:
>> Danke funktioniert war wirklich ein Optimierungsfehler.
>
> Sicher nicht.

 Wenn ich ein bisschen nachdenke, glaube ich auch, daß du Recht
 hast...
 Ein Byte muß auf jeden Fall gesendet werden, egal ob dies später
 irgendwo gebraucht wird oder nicht...
 Vielleicht wird mit diesem Byte ein Gerät aktiviert, es ist nicht
 der Compiler, der darüber entscheiden soll...
Moderator (Firma: Titel) Persönliche Seite #6421765
Lesenswert?

M. K. schrieb:
> PB2 ist der Chipselect vom Atmega328. Wird der angeknusbert denkt der
> Atmega328, dass er ein Slave ist und wartet, dass der Pseudo-Master mal
> was sagt ;)
Aber doch nur, wenn der SS-Pin als Eingang konfiguriert ist.

Falk B. schrieb:
> Maci M. schrieb:
>> Danke funktioniert war wirklich ein Optimierungsfehler.
> Sicher nicht.
Ich glaube, der Compiler hatte einfach statt des C-Codes den falschen 
Kommentar in Code umgesetzt:
1
    /* Set MOSI and SCK output, all others input */
2
    DDRB = (1<<5) | (1<<3) | (1<<2);
Denn dann wäre der SS-Pin ein Eingang gewesen und die SPI-Einheit hätte 
das gemacht, was sie halt macht, wenn der SS-Pin als Eingang deklariert 
ist.

Maci M. schrieb:
> Danke funktioniert war wirklich ein Optimierungsfehler.
Wie hast du festgestellt, dass das ein Optimierungsfehler war?
Was hast du denn geändert, dass es jetzt läuft?
#6421767
Lesenswert?

Marc V. schrieb:
> Vielleicht wird mit diesem Byte ein Gerät aktiviert, es ist nicht
>  die Sache des Compilers, darüber zu entscheiden...

Das Problem liegt nicht nur daran, daß vorgegebene Byte und keine 
Variable geschickt würde. Das Problem liegt daran, daß das ganze 
Programm nichts macht. Das erkennt Compiler.
Meine Erfahrung: wäre in main() und in der Schleife etwas mehr, auch 
andere Funktionen, andere Aufgaben, so würde auch SPI-Sendung nicht 
wegoptimiert.
Ich denke, Compiler ist wirklich klug. Er analysiert keine einzelnen 
Funktionen. Er analysiert das ganze Programm.

Deshalb, wenn ich eine mir unbekannte IC mit einer Versuchsplatine 
erproben möchte, mache ich auch viel anderes: beschreibe CLKPR zum 
Beispiel, initialisiere TWI usw. Das alles nur um zu viel Wegoptimieren 
zu vermeiden. Anders gesagt, es sollte ein Programm sein, das etwas 
macht, was Compiler nicht gleich als "nichts" erkennt.
Gast #6421776
Lesenswert?

Maxim B. schrieb:
> Das Problem liegt daran, daß das ganze
> Programm nichts macht. Das erkennt Compiler.
Warum macht es nichts? Es ist ja klar, dass es etwas machen soll, 
nämlich eben Daten an die Außenwelt senden. Wo ist der Fehler, dass es 
mit dem Code nichts macht?
Unabhängig davon, ob es am Oszilloskop lag.
#6421780
Lesenswert?

Dussel schrieb:
> Wo ist der Fehler, dass es
> mit dem Code nichts macht?

Ich bleibe bei meiner Meinung: Compiler hat erkannt, daß das Programm 
nichts macht, und hat alles, was er als überflüssig sieht, wegoptimiert.

Ich glaube daran einfach deshalb, weil mit mir das auch mehrmals 
passierte. Ein Blick in Assembler reichte gewöhnlich.

Solch kurze Programme, wenn man wirklich nur und ausschließlich eine 
Konstante kontinuierlich zu schicken braucht, so was schreibt man lieber 
auf dem Assembler. C ist zu klug dafür, zu unübersichtlich.
#6421783
Lesenswert?

Maxim B. schrieb:
> Das Problem liegt nicht nur daran, daß vorgegebene Byte und keine
> Variable geschickt würde. Das Problem liegt daran, daß das ganze
> Programm nichts macht. Das erkennt Compiler.
> Meine Erfahrung: wäre in main() und in der Schleife etwas mehr, auch
> andere Funktionen, andere Aufgaben, so würde auch SPI-Sendung nicht
> wegoptimiert.
> Ich denke, Compiler ist wirklich klug. Er analysiert keine einzelnen
> Funktionen. Er analysiert das ganze Programm.

Was für ein Quark.
Die Register sind volatile aus gutem Grund – derartige Zugriffe darf der 
Compiler nicht wegoptimieren. So ist volatile definiert – alles andere 
wäre ein Compilerbug.
Einem Compiler ist es auch egal, ob du einer Funktion eine Konstante 
oder eine Variable übergibst – sollte eine Funktion vom Compiler leer 
hinterlassen werden, kann maximal noch der Linker den Aufruf entfernen.
(Firma: Vescomp) #6421784
Lesenswert?

Maxim B. schrieb:
> Marc V. schrieb:
>> Vielleicht wird mit diesem Byte ein Gerät aktiviert, es ist nicht
>>  die Sache des Compilers, darüber zu entscheiden...
>
> Das Problem liegt nicht nur daran, daß vorgegebene Byte und keine
> Variable geschickt würde. Das Problem liegt daran, daß das ganze
> Programm nichts macht. Das erkennt Compiler.

 Sagt wer?
 Was, wenn mit diesem Programm wirklich irgendetwas ein- oder
 ausgeschaltet werden soll?
 Das kann (und soll) der Compiler nicht entscheiden.

> Ich denke, Compiler ist wirklich klug. Er analysiert keine einzelnen
> Funktionen. Er analysiert das ganze Programm.

 Und ich wiederum glaube das nicht.
 Variable aus Loop oder unbenutzte Variablen wegoptimieren ist eine
 Sache, aber das ganze Programm analysieren?
 Ausserdem ist jede Ausgabe, egal ob SPI, I2C oder UART von optimieren
 ausgenommen - wie schon Arduino Fanboy D. schrieb.
Gast #6421786
Lesenswert?

Maxim B. schrieb:
> Compiler hat erkannt, daß das Programm
> nichts macht, und hat alles, was er als überflüssig sieht, wegoptimiert.
>
> Ich glaube daran einfach deshalb, weil mit mir das auch mehrmals
> passierte. Ein Blick in Assembler reichte gewöhnlich.
'Glaubt erkannt zu haben'. Die Annahme, dass das Programm (im Quelltext) 
nichts macht, ist ja eindeutig falsch. Erst nachdem der Compiler eine 
Fehler gemacht hat, tut es wirklich nichts mehr.

Unter der Annahme, dass es wirklich am Compiler lag.
Gast #6421787
Lesenswert?

Maxim B. schrieb:
> Arduino Fanboy D. schrieb:
>> Also sind sie von Optimierungen ausgeschlossen.
>
> Das sagt Theorie. Praxis sieht aber etwas anders aus...

Das mit der Optimierung ist alles blödes Gelaber.
Ohne Hand und Fuß.... auch ohne Hirn.

Zwischenzeitlich mit 1/2 Dutzend AVR Toolchains getestet.
Das tuts perfekt, ohne jede Ausnahme.
Sowohl als C als auch C++

Maxim B. schrieb:
> Ich bleibe bei meiner Meinung: Compiler hat erkannt, daß das Programm
> nichts macht, und hat alles, was er als überflüssig sieht, wegoptimiert.
Ist klar!
Bedeutung von volatile vielleicht noch mal nachlesen...
Bitte.
#6421817
Lesenswert?

Ich habe nun das Programm von TO mit AVR Studio compiliert.
Der Grund war wirklich anders.
Das Programm beginnt
1
void SPI_MasterTransmit(char cData)
2
{
3
  /* Start transmission */
4
  SPDR = cData;
5
  8a:  8e bd         out  0x2e, r24  ; 46
6
  /* Wait for transmission complete */
7
  while(!(SPSR & (1<<SPIF)));
8
  8c:  0d b4         in  r0, 0x2d  ; 45
9
  8e:  07 fe         sbrs  r0, 7
10
  90:  fd cf         rjmp  .-6        ; 0x8c <SPI_MasterTransmit+0x2>
11
}
12
  92:  08 95         ret
Und bleibt auf 090: auch hängen. Weil noch ein Befehl fehlt: IN reg,0x2e 
!!! :)

D.h. TO hat die Funktion für Übertragung nicht korrekt geschrieben.
Richtig wäre z.B. so:
1
unsigned char SPI_MasterTransmit(char cData)
2
{
3
  /* Start transmission */
4
  SPDR = cData;
5
  /* Wait for transmission complete */
6
  while(!(SPSR & (1<<SPIF)));
7
  return SPDR;
8
}

Ohne Lesen von SPDR nach der Übertragung funktioniert das alles nicht.

Und auch wichtig: in Init sollte man einmal dummi-Byte schicken, damit 
SPDR  einmal gelesen wird. Sonst wird die Mechanik hängen.
So einfach ist das...
#6421836
Lesenswert?

Also, es fehlte in der Funktion SPI_MasterTransmit einiges:
1. kein void sondern unsigned char
2. return SPDR; am Ende.
Das noch in Programm zu geben, und dann wird schon alles laufen.

Jetzt erinnere ich: einmal habe ich gleiche Fehler gemacht. Ich dachte: 
wozu muß ich noch die Zeit vergeuden, und SPDR lesen, wenn ich nur 
senden möchte? Und ich habe zwei Funktionen gemacht: eine mit Lesen, 
andere ohne Lesen. Das hat aber nicht funktioniert.
#6421848
Lesenswert?

Arduino Fanboy D. schrieb:
> Auch das ist Unfug.

Vielleicht ist das in Arduino Unfug? Weil man dort immer "Lib" verwendet 
und genau Code von SPI sieht man selber nie.

Wenn man aber alles selber macht, ohne Mama zu rufen, dann muß schon 
return SPDR stehen. Ich bin sicher, in Arduino-Lib ist das auch so, nur 
sieht man das nicht.

Du könntest mal Assembler-Listing von einem Arduino-Programm kucken; 
steht dort in  reg, 0x2e oder nicht

Arduino Fanboy D. schrieb:
> Du gibst nicht auf, oder?
habe ich schon doch! Ich sage nun: das war kein Wegoptimieren. Das war 
nur eine nicht korrekt geschriebene Funktion. Compiler hat keine Schuld, 
er machte alles richtig. Schuldig ist Programmierer (was ich auch früher 
behauptete).
Gast #6421855
Lesenswert?

Maxim B. schrieb:
> Wenn man aber alles selber macht, ohne Mama zu rufen, dann muß schon
> return SPDR stehen.
Muss es weder nach C-Standard noch nach Programmlogik.
Ich zitiere aus dem Datenblatt von "ATmega48A ATmega48PA ATmega88A 
ATmega88PA ATmega168A ATmega168PA ATmega328 ATmega328P":
1
void SPI_MasterTransmit(char cData) {
2
/* Start transmission */
3
SPDR = cData;
4
/* Wait for transmission complete */ while(!(SPSR & (1<<SPIF)))
5
; }

Aber Atmel hat wahrscheinlich einfach keine Ahnung.
#6421867
Lesenswert?

Dussel schrieb:
> Aber Atmel hat wahrscheinlich einfach keine Ahnung.

Ich kenne Menschen aus Atmel nicht. Ich kann deswegen nichts sagen.
Aber bei mir arbeitete Funktion ohne Lesen von SPDR nicht. Und, wie ich 
noch erinnern kann, hat jemand hier auf dem Forum über den Fehler 
gesagt. Ich habe korrigiert - und alles wurde gut.

Aber macht wie ihr wollt, mir ist das eigentlich egal.
Gast #6421870
Lesenswert?

Dussel schrieb:
> Aber Atmel hat wahrscheinlich einfach keine Ahnung.
Sehe ich auch so!
Nur der  Maxim B. (max182) der hats voll auf dem Schirm.

Maxim B. schrieb:
> Wenn man aber alles selber macht, ohne Mama zu rufen, dann muß schon
> return SPDR stehen.

Selbst nach dem Hinweis darauf, dass du falsch liegst, machst du 
unbeirrt weiter.
Du bist ein Denunziant
Ein Lügner
Und hast offensichtlich keine Ahnung, von dem, was du da blubberst.
#6421875
Lesenswert?

Arduino Fanboy D. schrieb:
> Selbst nach dem Hinweis darauf, dass du falsch liegst

Wo liege ich falsch?
Arduino Fanboy D. schrieb:
> Du bist ein Denunziant
> Ein Lügner
Ich habe dich aber noch nie beleidigt.
nach solchen deinen Worten existierst du für mich nicht mehr. Deine 
Posten werde ich in der Zukunft nie mehr beantworten.

P.S. Wer die Wahrheit sehen will, der hat immer noch die Möglichkeit, 
selbst AVR Studio starten, Text von TO eingeben und compilieren. Dann 
return SPDR dazu schreiben, noch mal kompilieren und vergleichen.
Das bedeutet aber ein bißchen mehr Bewegung, als einfach "Lügner" zu 
schreiben, wie? :)
Gast #6421881
Lesenswert?

Maxim B. meint vermutlich diesen Mechanismus, aus dem Datenblatt zu 
'SPSR – SPI Status Register, • Bit 7 – SPIF: SPI Interrupt Flag':

"Alternatively, the SPIF bit is cleared by first reading the SPI Status 
Register with SPIF set, then accessing the SPI Data Register (SPDR)."
Gast #6421882
Lesenswert?

Maxim B. schrieb:
> Aber bei mir arbeitete Funktion ohne Lesen von SPDR nicht. Und, wie ich
> noch erinnern kann, hat jemand hier auf dem Forum über den Fehler
> gesagt. Ich habe korrigiert - und alles wurde gut.
Stimm ja auch. Nur klingen deine Beiträge so, als läge der Fehler im 
Quelltext. Das stimmt aber nicht. Der Fehler liegt im Compiler. Und dass 
man korrekten Quelltext ändert, um einen Fehler zu umgehen, ist eben 
keine Fehlerkorrektur, sondern eine Umgehungslösung ("workaround").
#6421883
Lesenswert?

Dussel schrieb:
> Stimm ja auch. Nur klingen deine Beiträge so, als läge der Fehler im
> Quelltext.

Wo sonst, wenn nach Quelltext-Korrektur alles funktioniert, wenigstens 
bei mir?

Man sagt: man sollte Menschen so lieben wie sie sind. Das Gleiche 
betrifft auch Compiler: man sollte Compiler so lieben, wie der ist. :) 
Wir dürfen den Compiler verwenden oder nicht verwenden. Sein Verhalten 
zu ändern können wir ihn nicht zwingen.
Gast #6421889
Lesenswert?

Maxim B. schrieb:
> Wo liege ich falsch?

Maxim B. schrieb:
> Ohne Lesen von SPDR nach der Übertragung funktioniert das alles nicht.

Du bist jetzt mehrfach darauf hingewiesen worden, dass das Unsinn ist.
Bearrst aber darauf.
Damit ist das für mich eine Lüge.

Auch meinst du mich anhand meines Arduino Bekenntnis beurteilen zu 
dürfen.
z.B. ich würde ohne die Arduinolibs verhungern, oder so..
Oder könnte nicht exakt den Code aus dem Eingangsposting probefahren und 
das Resultat im generierten Code sehen.
Das ist Denunziantentum, oder Verleumdnung.
Such dir das schönste davon aus aus.
Gast #6421892
Lesenswert?

Maxim B. schrieb:
> Wo sonst, wenn nach Quelltext-Korrektur alles funktioniert, wenigstens
> bei mir?
Im Compiler. Wenn der Compiler korrekten Quelltext falsch übersetzt, ist 
es ein Fehler des Compilers. Daran ändert sich auch nichts, wenn man 
einen anderen korrekten Quelltext findet, den der Compiler fehlerfrei 
übersetzt.
#6421894
Lesenswert?

S. Landolt schrieb:
> Maxim B. meint vermutlich diesen Mechanismus, aus dem Datenblatt zu
> 'SPSR – SPI Status Register, • Bit 7 – SPIF: SPI Interrupt Flag':
>
> "Alternatively, the SPIF bit is cleared by first reading the SPI Status
> Register with SPIF set, then accessing the SPI Data Register (SPDR)."

Ja, wahrscheinlich genau das. Ich habe mir seit dem Fall einfach als 
Regel festgelegt: SPI immer voll anzusprechen (Schreiben und Lesen) und 
dummi-byte am Anfang schicken, bei Init. Solange ich das mache, bekomme 
ich kein Problem. Wozu sollte ich was besseres suchen, wenn das gut 
arbeitet?

Auch jetzt bei dem Experiment: das Programm blieb auf SPSR-Prüfung 
hängen. Ich habe return SPDR geschrieben - und alles läuft. So einfach.
#6421898
Lesenswert?

Dussel schrieb:
> Wenn der Compiler korrekten Quelltext falsch übersetzt, ist
> es ein Fehler des Compilers.

Ja, aber ich benutze, wie auch TO, diesen Compiler. Ich habe keinen 
anderen. Ich muß also den Text so schreiben, daß Compiler mich versteht. 
Schreibe ich so, daß Compiler mich nicht versteht, dann ist absolut 
egal, wer von uns Recht hat: ich oder Compiler. Ich brauche das 
Programm, für Compiler ist das egal.
Gast #6421901
Lesenswert?

Dussel schrieb:
> Der Fehler liegt im Compiler.
Nein, das ist nicht wahr.
Das Oszi war/ist kaputt.

Maxim B. schrieb:
> Auch jetzt bei dem Experiment: das Programm blieb auf SPSR-Prüfung
> hängen. Ich habe return SPDR geschrieben - und alles läuft. So einfach.
Auch hier unterstelle ich dir eine dreiste Lüge.
Da im Beispiel keine ISR/InterruptFlag zum Einsatz kommt, kann ein 
solcher Fehler auch nicht auftreten.

Wie schon gesagt...
Mit einem halben Dutzend AVR Gcc Toolchains getestet.
Gast #6422027
Lesenswert?

Maxim B. schrieb:
> Jetzt erinnere ich: einmal habe ich gleiche Fehler gemacht. Ich dachte:
> wozu muß ich noch die Zeit vergeuden, und SPDR lesen, wenn ich nur
> senden möchte?

Bei SPI gibt es kein "nur senden". Bei einem Transfer über SPI wird vom 
Master immer ein Byte über MOSI raus geschoben und gleichzeitig eins 
über MISO eingelesen.
Gast #6422034
Lesenswert?

>Also kann es ja doch nicht daran liegen, dass ich das Datenregister
>nicht auslese.

Im Datenblatt steht ja auch nicht dass man das Register "Lesen" muss.
Dort steht dass man auf SPDR zugreifen muss um SPIF zu löschen.
Schreiben ist auch ein Zugriff, und das machst du ja auch.
Gast #6422098
Lesenswert?

> ... Schreiben ist auch ein Zugriff ...

Genau; deshalb funktioniert das von Dussel gezeigte 
Atmel-Programmbeispiel ja auch, für sich betrachtet. Allerdings bleibt 
außerhalb der Routine das SPIF gesetzt (was wohl bei Maxim B. irgendwann 
zu Problemen geführt hatte).

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