mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Habe ich einen Fehler gemacht?


Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich kenne mich mit Bitoperationen noch nicht so gut aus.
Folgendes Problem:

Über SPI sollen mit einem Atmega32 3 Integer-Variablen gesendet werden.
Damit die jeweils in das SPDR passen, habe ich folgende Operationen 
programmiert (SPI_send ist die Sendefunktion. Die funktioniert!):
for (i = 0; i < 4; i++)
{
 // Low-Byte senden
 send_SPI(((unsigned char) (control[i] & 0x00ff)));
 // High_Byte senden
 send_SPI(((unsigned char) (control[i] >> 8)));
}

Der Slave-Controller (ebenfalls Atmega32) geht mit dem empfangenen 
Ergebnis wie folgt um:
SIGNAL(SIG_SPI)
{
 // count zählt die empfangenen Bytes (0-5)
 letter[count] = SPDR;
 if (count == 5)
 {
  count = 0;
 }
}

int main()
{
 // Laufvariable auf null
 a = 0;

 // gesendete Abstände wieder zusammensetzen...
 for (i = 0; i < 6; i = i + 2)
 {
   // gesendet wurde erst Low-Byte dann High-Byte
   gap[a] = (((unsigned int) (letter[(i + 1)] << 8)) | ((unsigned int)  letter[i]));
   a++;
 }

Hab ich die Umwandlungen richtig gemacht?

Viele Grüße und Danke für jeden Hinweis!!!

Dennis

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

irgendwie verstehe ich Bahnhof...

SIGNAL(SIG_SPI)
{
 // count zählt die empfangenen Bytes (0-5)
 letter[count] = SPDR;
 if (count == 5)
 {
  count = 0;
 }
}

wer oder was ist count, wer ändert count und wo und warum?

Gruß aus Berlin
Michael

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
count wird außerhalb von der Endlosschleife ein Mal auf Null gesetzt und 
ist dann dafür da, die Anzahl der empfangenen Bytes zu senden.

Da 3 Int-Werte geschickt werden, muss 6x gesendet werden, bis die SPI 
alles verschickt hat. Und count zählt durch und steuert das Schreiben 
der Werte in das Feld letter...

Autor: Uwe ... (uwegw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wann wird count hochgezählt?

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach mist,

ich habe Euch die falsche SPI-Interrupt-Service-Routine geschickt...
Der Rest ist korrekt!
SIGNAL(SIG_SPI)
{
 letter[count] = SPDR;
 SPDR = 0x44;
 if (count == 5)
 {
  TIMSK &= (~(1 << TOIE0));
 }
 else
 {
  count++;
 }
}

Autor: Jean Player (fubu1000)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dennis schrieb:
> Hallo zusammen,

Ja hallo.


> Über SPI sollen mit einem Atmega32 3 Integer-Variablen gesendet werden.
> Damit die jeweils in das SPDR passen, habe ich folgende Operationen
> programmiert (SPI_send ist die Sendefunktion. Die funktioniert!):
>
>
> for (i = 0; i < 4; i++)
> {
>  // Low-Byte senden
>  send_SPI(((unsigned char) (control[i] & 0x00ff)));
>  // High_Byte senden
>  send_SPI(((unsigned char) (control[i] >> 8)));
> }
> 

Du sendest aber 4 Integer raus !


> Der Slave-Controller (ebenfalls Atmega32) geht mit dem empfangenen
> Ergebnis wie folgt um:
>
>
> SIGNAL(SIG_SPI)
> {
>  letter[count] = SPDR;
>  SPDR = 0x44;
>  if (count == 5)
>  {
>   TIMSK &= (~(1 << TOIE0));
>  }
>  else
>  {
>   count++;
>  }
> }
> 

Ziemlich unklar, warum läuft da nen Timer und wofür ?


>
> int main()
> {
>  // Laufvariable auf null
>  a = 0;
> 
>  // gesendete Abstände wieder zusammensetzen...
>  for (i = 0; i < 6; i = i + 2)
>  {
>    // gesendet wurde erst Low-Byte dann High-Byte
>    gap[a] = (((unsigned int) (letter[(i + 1)] << 8)) | ((unsigned int)
> letter[i]));
>    a++;
>  }
> 

Wasn dat. Das kann gar nit gehen du packst ständig irgend etwas in deine 
tolles Array gap. Zeige mal deinen ganzen aktuellen Code mit dem Mist 
kann keiner was anfangen !

Gruß

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ja hallo.


> Über SPI sollen mit einem Atmega32 3 Integer-Variablen gesendet werden.
> Damit die jeweils in das SPDR passen, habe ich folgende Operationen
> programmiert (SPI_send ist die Sendefunktion. Die funktioniert!):
>
>

> for (i = 0; i < 4; i++)
> {
>  // Low-Byte senden
>  send_SPI(((unsigned char) (control[i] & 0x00ff)));
>  // High_Byte senden
>  send_SPI(((unsigned char) (control[i] >> 8)));
> }
>

> Du sendest aber 4 Integer raus !

Is klar! Die Schleife läuft solange kleiner 4 und es werden pro 
Schleifendurchlauf 2 Bytes gesendet. Also werden drei Durchläufe gemacht 
mal zwei Bytes sind sechs Bytes, also drei Integer.


>

> int main()
> {
>  // Laufvariable auf null
>  a = 0;
>
>  // gesendete Abstände wieder zusammensetzen...
>  for (i = 0; i < 6; i = i + 2)
>  {
>    // gesendet wurde erst Low-Byte dann High-Byte
>    gap[a] = (((unsigned int) (letter[(i + 1)] << 8)) | ((unsigned int)
> letter[i]));
>    a++;
>  }
>

> Wasn dat. Das kann gar nit gehen du packst ständig irgend etwas in deine
> tolles Array gap. Zeige mal deinen ganzen aktuellen Code mit dem Mist
> kann keiner was anfangen !

Ah so. Nur weil etwas ständig gemacht wird, geht es also nicht.
Und überhaupt: Was gibst Du hier für nen Mist von Dir? Du musst ihm 
nicht helfen, und wenn Du es nicht kannst, dann brauchst Du hier auch 
nicht so nen Senf von Dir zu geben, OK?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan schrieb:

>> for (i = 0; i < 4; i++)

> Is klar! Die Schleife läuft solange kleiner 4 und es werden pro
> Schleifendurchlauf 2 Bytes gesendet. Also werden drei Durchläufe gemacht

Au weh. Noch keinen Kaffee gehabt? Versuch's lieber nochmal.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schlechte Stimmung am Montagmorgen? :)

Vielen Dank, das mit der FOR-Schleife ist der Fehler.
Sollte i<3 heissen! Also wird auch immer einer zu viel gesendet, was 
begründet, warum die Karre nicht so tut wie sie soll!


Danke an ALLE Beteiligten ;) Und das nächste Mal poste ich besser den 
ganzen Code!


Viele Grüße!

D.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und das nächste Mal poste ich besser den ganzen Code!
Ja, denn ein Fragezeichen bleibt bei mir noch:
gap[a] = (((unsigned int) (letter[(i + 1)] << 8)) | ((unsigned int) letter[i]));
Wenn ich mir das High-Byte so anschaue, dann sitzen da die Klammern 
falsch :-o

Angenommen letter wäre ein char-Array, dann ergibt
(letter[(i + 1)] << 8)
immer 0. Da hilft dann das anschliessende Casten nicht mehr viel:
(unsigned int) (letter[(i + 1)] << 8)
Kann sein, dass das geht, es muß aber nicht... :-/

Zuverlässiger (und beabsichtigt) ist das wohl eher so:
gap[a] = (((unsigned int) letter[i+1]) << 8) | ((unsigned int) letter[i]);

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:

> Angenommen letter wäre ein char-Array, dann ergibt
(letter[(i + 1)] << 8)
> immer 0.

Keineswegs. Nur wenn sich der Compiler nicht an den Standard hält. Der 
schreibt nämlich vor, dass alle ganzzahligen Rechnungen mindestens als 
"int" oder "unsigned" durchgeführt werden.

Folglich darf man das in korrektem C auch so schreiben:
gap[a] = (letter[i+1] << 8) | letter[i];

Es gibt allerdings ein paar Compiler für 8-Bitter, die in einer 
bestimmten Compilereinstellung diese Regel verletzen um besseren Code 
erzeugen zu können.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
C99 -- Committee Draft -- May 6, 2005 ISO/IEC 9899:TC2

Seite 42f:
The following may be used in an expression wherever an int or unsigned int may
be used:
-- An object or expression with an integer type whose integer conversion rank is less
    than or equal to the rank of int and unsigned int.
-- A bit-field of type _Bool, int, signed int, or unsigned int.
If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the integer
promotions.48) All other types are unchanged by the integer promotions.
The integer promotions preserve value including sign. As discussed earlier, whether a
``plain'' char is treated as signed is implementation-defined.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zuverlässiger (und beabsichtigt) ist das wohl eher so:

>gap[a] = (((unsigned int) letter[i+1]) << 8) | ((unsigned int) letter[i]);

Also die runden Klammern bei letter[i+1] weglassen?
Ich programmiere mit AVR Studio 4.0 ... falls die Info zur Lösung des 
Problems beiträgt!

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Btw: In Deiner Main bearbeitest Du bereits Eingaben, ohne zu prüfen, ob 
alle Daten angekommen sind. Du solltest erst dann loslegen, wenn count 
die 6 (!) erreicht hat - erst dann sind alle benötigten Daten da.

Was Du in SIGNAL(SIG_SPI) mit dem Timer-Interrupt machen willst, ist mir 
dabei immer noch unklar. Oder wolltest Du den SPI-Interrupt abschalten?

Wenn nein, könnte es sein, dass letter einen Speicherüberlauf ergibt, 
falls noch weitere Daten per SPI folgen.

Also zumindest SPI-Interrupt abschalten und nach der Datenverarbeitung 
count auf 0 sowie SPI-Interrupt wieder einschalten.

Beachte aber auch, dass SPI-Eingaben verschwinden können, wenn wärend 
der Datenverarbeitung mehrere Daten eingehen.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was Du in SIGNAL(SIG_SPI) mit dem Timer-Interrupt machen willst, ist mir
> dabei immer noch unklar. Oder wolltest Du den SPI-Interrupt abschalten?

Nein, da wird und soll tatsächlich der Timer abgeschaltet werden. Das 
Programm macht noch mehr, als ich hier geschrieben habe. Das nächste Mal 
lege ich einfach alles ab.

> Wenn nein, könnte es sein, dass letter einen Speicherüberlauf ergibt,
> falls noch weitere Daten per SPI folgen.

Ich frage ab, ob sechs Bytes angekommen sind:
SIGNAL(SIG_SPI)
{
 letter[count] = SPDR;
 SPDR = 0x44;
 if (count == 5)
 {
  TIMSK &= (~(1 << TOIE0));
 }
 else
 {
  count++;
 }
}


> Also zumindest SPI-Interrupt abschalten und nach der Datenverarbeitung
> count auf 0 sowie SPI-Interrupt wieder einschalten.

Wenn ich den SPI-Interrupt abschalte, sendet der Master ja trotzdem 
weiter, oder? Also könnten doch Daten verloren gehen, bzw in der 
falschen Reihenfolge eintreffen, korrekt?

> Beachte aber auch, dass SPI-Eingaben verschwinden können, wenn wärend
> der Datenverarbeitung mehrere Daten eingehen.

Das musst Du mir bitte erklären!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.