Forum: Mikrocontroller und Digitale Elektronik AVR USART im SPI Mode Daten empfangen


von Steffen (Gast)


Lesenswert?

Hallo,

ich beschäftige mich gerade weiterhin mit dem USART des AVR. Ich habe 
diesen als MSPI konfiguriert und möchte damit nun Daten empfangen.

Habe ich das richtigen verstanden, dass in diesem Fall erst Daten 
gesendet werden müssen?


Beispiel:
Ich möchte z.B. 16 Bit aus einem Sensor auslesen:
1
while (!( UCSR1A & (1<<UDRE1)));    // Warten Empfangs-Puffer leer
2
UDR1= (char)(in >> 8);  
3
while (!(UCSR1A & (1<<RXC1)));      // Warten bis Daten empfangen
4
sensor= (UDR1<<8);        // Ersten 8 Bit MSB
5
while (!( UCSR1A & (1<<UDRE1)));    // Warten Empfangs-Puffer leer
6
UDR1= (char)in;
7
while (!(UCSR1A & (1<<RXC1)));      // Warten bis Daten empfangen
8
sensor+= UDR1;

Mir ist dabei noch nicht ganz klar, was die Zeilen

UDR1= (char)(in >> 8);

und

UDR1= (char)in;

bedeuten.

Für "in" wird folgendes übergeben in= 0x1001;

Ausgelesen werden soll übrigens ein ADT7301.

Wäre klasse, wenn mir da jemand auf die Sprünge helfen könnte.
Grüße
Steffen

von Karl H. (kbuchegg)


Lesenswert?

Steffen schrieb:

>
> Für "in" wird folgendes übergeben in= 0x1001;

Also 16 Bit.

Jetzt nimmst du mal deine 16 Bit und schiebst die um 8 Bit nach rechts. 
Was kommt raus?
Und was hat das damit zu tun, dass das UDR Register 8 Bit breit ist?

von Steffen (Gast)


Lesenswert?

Hallo,

> Jetzt nimmst du mal deine 16 Bit und schiebst die um 8 Bit nach rechts.

Dann bekomme ich links 8 Nullen rein und rechts fallen die LSB raus:


z.B. 1111 1111 0000 0000 >> 8 => 0000 0000 1111 1111

hier dürfte das dann sein:
in:   0001 0000 0000 0001 >> 8 => 0000 0000 0001 0000


> Und was hat das damit zu tun, dass das UDR Register 8 Bit breit ist?

Da ich 16 Bit lesen will, muss ich das eben auf zwei mal machen, weil 
das UDR Register eben nur 8 Bit packt.

Deswegen eben auch dies hier "sensor= (UDR1<<8); sensor+= UDR1;" Damit 
werden eben die 16 Bit in Sensor geschrieben. 8 Bit nach Links, weil 
zuerst die MSB aus dem Sensor gelesen werden.

Nur verstehe ich immer noch nicht, warum man auf diese Weise in das UDR 
Register schreiben muss.

Grüße
Steffen

von Timmo H. (masterfx)


Lesenswert?

Damit der SPI clockt musst du in das Senderegister etwas reinschreiben 
(üblicherweise die Adresse oder Befehl). Und da du eben zwei Bytes lesen 
willst musst du das zwei mal machen.
Darum ist das im Datenblatt auch so gemacht:
1
MSByte = SPI_Read(0);                      //The first byte is clocked in.
2
LSByte = SPI_Read(0);                      //The second byte is clocked in.
Wenn das dritte Bit vom ersten Byte beim Senden kann den ADT7301 dann in 
den Power-Down mode versetzen.

von Steffen (Gast)


Lesenswert?

Also weil ich zwei Byte lsen will, muss ich zwei Byte senden, weil durch 
das Senden die Clock des SPI gestartet wird quasi. Der EIngang des ADT 
ist nicht angeschlossen, da der PowerDown Modus nicht benötigt wird.

Somit wäre es dann hier egal, was ich an der Stelle

UDR1= (char)(in >> 8);

und

UDR1= (char)in;

schreibe, Hauptsache ist, dass ich was schreibe, damit die Clock 
läuft!?!

Wenn der DataIn des ADT angeschlössen wäre, wäre es dann auch wichtig 
was gesendet wird, weil man dann eben die Möglichkeit hätte, den Sensor 
in den PowerDown Modus zu schicken...!?

So richtig oder hab ich da noch was falsch verstanden?

Grüße
Steffen

von Timmo H. (masterfx)


Lesenswert?

Steffen schrieb:
> Also weil ich zwei Byte lsen will, muss ich zwei Byte senden, weil durch
> das Senden die Clock des SPI gestartet wird quasi. Der EIngang des ADT
> ist nicht angeschlossen, da der PowerDown Modus nicht benötigt wird.
>
> Somit wäre es dann hier egal, was ich an der Stelle
>
> UDR1= (char)(in >> 8);
>
> und
>
> UDR1= (char)in;
>
> schreibe, Hauptsache ist, dass ich was schreibe, damit die Clock
> läuft!?!
Richtig. Was du sendest ist aber nicht immer Egal, denn wie bereits 
geschrieben wird meist ein Befehl oder die Adresse gesendet, und der 
SPI-Master antwortet im ersten Byte erstmal gar nicht sondern erst beim 
zweiten weil er dann ja erst die Adresse des Registers weiß. In diesem 
Fall ist es eben anders. Er fängt wohl sofort an zu senden und ignoriert 
bis auf das dritte Bit vom erstem Byte alle geschriebenen Daten.
Du kannst also schreiben was du willst, nur wenn du nicht den Power-Down 
Mode versehendlich aktivieren willst solltest du eben das dritte bit auf 
0 lassen.

Du kannst genauso gut schreiben:
1
in = 0;
2
while (!( UCSR1A & (1<<UDRE1)));    // Warten Empfangs-Puffer leer
3
UDR1= in;  
4
while (!(UCSR1A & (1<<RXC1)));      // Warten bis Daten empfangen
5
sensor= (UDR1<<8);        // Ersten 8 Bit MSB
6
while (!( UCSR1A & (1<<UDRE1)));    // Warten Empfangs-Puffer leer
7
UDR1= in;
8
while (!(UCSR1A & (1<<RXC1)));      // Warten bis Daten empfangen
9
sensor+= UDR1;

Es gibt auch Bausteine die erwarten erstmal einen 8 Bit Befehl worauf 
sie dann mit einem 16 Bit-Wert Antworten. Hier schreibt man also erstmal 
die 8-Bit Befehl und danach zwei Dummy-Bytes (welche durch den Baustein 
ignoriert werden) um die zwei 8-BitWerte auszulesen.

von Steffen (Gast)


Lesenswert?

Hallo,

vielen Dank für die Hilfe!

So langsam wird einiges klarer. An dieser Stelle ist es eben einfacher, 
da der ADT keine Befehle erwartet, sondern einfach was raushaut.

Vielen Dank!

Gruß
Steffen

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.