www.mikrocontroller.net

Forum: PC-Programmierung code funktioniert nicht


Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#include <stdlib.h>



#include <util/delay_basic.h>


unsigned char x;




void warte(unsigned char zahl)            //warteschleife. warte ist 
100µsek. * zahl

{


  do
  {
    _delay_loop_1(0x00AA);
     --zahl;                  //1 von der Variable Zahl abziehen...





  }
   while (zahl >0);              // solange zahl > 0

}






int main(void)
{
  DDRD = 0xff;
  DDRB = 0xff;
  DDRA = 0x00;
  while(1)
  {






    SPCR = 0xD2;  // Spi Kontrollregister setzen

    warte(30);




    SPDR = 0xFA;  // Ausgabe an das Spi interface


warte(25);



warte(255);






}

}









hallo,
kann mir jemand sagen wiso folgender code, zur ansteuerung der spi 
schnittstelle nicht funktioniert?

habe den 8535 von atmel benutzt

danke

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Formatieren von Quelltext im Forum scheint auch nicht mehr zu 
funktionieren?
So ist das nicht schön zu lesen.

Die Fehlerbeschreibung ist mir auch grottig.
Steige aus, danke.

Autor: Igmer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
int test;

void main (bla, blubb)
{
...
return keine_antwort;
}

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
war mal so gnädig, bitte die Änderungen ansehen, die ich gemacht hab, 
und beim weiteren proggen übernehmen :-)
#include <avr/io.h>
#include <stdlib.h>


#include <util/delay_basic.h>

unsigned char x;      // hier kannste eh nie <0 bekommen!

void warte(unsigned char zahl)           //warteschleife. warte ist 100µsek. * zahl
{
  do
  {
    _delay_loop_1(0x00AA);
  } while (zahl--);              // solange zahl > 0
}


int main(void)
{
  DDRA = 0x00;
  DDRB = 0xff;
  DDRD = 0xff;  
  
  while(1)
  {
    SPCR = 0xD2;  // Spi Kontrollregister setzen
    warte(30);
    SPDR = 0xFA;  // Ausgabe an das Spi interface
    warte(25);
    warte(255);
  }
}

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm ... muss alternate function aktiviert werden für SPI?

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen dank thorsten für deine super schnelle hilfe!
und sorry für die schlechte beschreibung/ formatierung.
mfg

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Random ... schrieb:
> void warte(unsigned char zahl)           //warteschleife. warte ist
> 100µsek. * zahl
> {
>   do
>   {
>     _delay_loop_1(0x00AA);
>   } while (zahl--);              // solange zahl > 0
> }

Könntest du mir noch den Sinn hiervon erklären?

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm ... sieht auf den ersten blick korrekt aus.

Das delay ist ne avr standard-funktion, die irgendwie konfiguriert wohl 
100us wartet (mit dem parameter). Das ganze mal zahl, also z.b. 300us.

Ich habs nur reduziert, unsigned char kann nicht negativ werden kann, 
und es ist hier einfacher, zahl auf != 0 zu prüfen und dann ggf. zu 
dekrementieren.

Man könnte jetzt streiten, da zahl=0 auch 100us wartet. Aber keiner 
würde die fkt mit 0 aufrufen :-)

while(zahl--) delay(0xaa);

oder so ähnlich.


VG,
/th.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und jetzt erklärst du bitte noch, warum du nicht einfach

  _delay_us

benutzt.

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <avr/io.h>
#include <stdlib.h>


#include <util/delay_basic.h>

unsigned char x; 
unsigned char y;     

void warte(unsigned char zahl)           //warteschleife. warte ist 100µsek. * zahl
{
  do
  {
    _delay_loop_1(0x00AA);
  } while (zahl--);              // solange zahl > 0
}


int main(void)
{
  DDRA = 0x00;
  DDRB = 0xff;
  DDRD = 0xff;  

  while(1)
  {



        SPCR = 0xD7;  // Spi Kontrollregister setzen

    
  
  
    PORTD &=~(1<<PD0); // FSYNC LOW           
    SPDR = 0x40 ;  // Ausgabe an das Spi interface
       while(SPIF == 0);
      {
      y++;
      }
 
    SPDR = 0x00;  // Ausgabe an das Spi interface      config  
      while(SPIF == 0);
      {
      y++;
      }      //                   /

 
      SPDR = 0x40;  // Ausgabe an das Spi interface     
      while(SPIF == 0);
      {
      y++;
      }
 ;
        SPDR = 0xAA;  // Ausgabe an das Spi interface      FREQU-0
      while(SPIF == 0);
      {
      y++;
      }      //                    /


    warte(9);
  }
}
 


Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hab schon wieder ein problem...
und zwar sendet die spi nur das 1. word. also ox40

wie gehabt, avr atmega 8535

kann mir jmnd helfen??

danke im vorraus!

mfg christoph

Autor: Random ... (thorstendb) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Und jetzt erklärst du bitte noch, warum du nicht einfach
>
>   _delay_us
>
> benutzt.

öhm ... hallo?
Da ist man so nett und formatiert den Code um, und kassiert gleich 
prügel.

Ich benutze solche delays eh nicht, weiss deshalb auch nicht, wie sie 
parametrisiert werden und welche Fkt. es da zum delay gibt. So was regel 
ich lieber über Timer interrupts, oder kleinere delay-schleifen wenns 
nicht anders geht.

Bin eh z.Zt. nur noch mit RTX auf STM32E unterwegs.


VG,
/th.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Random ... schrieb:
> Karl heinz Buchegger schrieb:
>> Und jetzt erklärst du bitte noch, warum du nicht einfach
>>
>>   _delay_us
>>
>> benutzt.
>
> öhm ... hallo?
> Da ist man so nett und formatiert den Code um, und kassiert gleich
> prügel.

Entschuldigung.
Ich hab nicht bemerkt, dass du nicht der TO bist.
Der sollte sich angesprochen fühlen, nicht du.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stein schrieb:
> ich hab schon wieder ein problem...
> und zwar sendet die spi nur das 1. word. also ox40

Da wird wohl SPIF nie 0 werden.

Übrigens:

       while(SPIF == 0);

siehst du den ; da am Zeilenende?
Überleg mal, was der wohl für deinen vermeintlichen Schleifenrumpf 
bedeutet.

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dummer fehler..
danke für die verbesserung!
im quellcode hatte ich natürlich 0x40 geschrieben.
Aber im neuen quellcode funktioniert es auch ohne simikolon hinter der 
schleife nicht...

fehler wie gehabt, die spi sendet nur das 1. wort

danke für verbesserungen!
#include <avr/io.h>
#include <stdlib.h>


#include <util/delay_basic.h>

unsigned char x; 
unsigned char y;     

void warte(unsigned char zahl)           //warteschleife. warte ist 100µsek. * zahl
{
  do
  {
    _delay_loop_1(0x00AA);
  } while (zahl--);              // solange zahl > 0
}


int main(void)
{
  DDRA = 0x00;
  DDRB = 0xff;
  DDRD = 0xff;  

  while(1)
  {



        SPCR = 0xD7;  // Spi Kontrollregister setzen

    
  
  

    SPDR = 0x40;  // Ausgabe an das Spi interface
       while(SPIF == 0)
      {
      y++;
      }
 
    SPDR = 0x00;  // Ausgabe an das Spi interface      config  
      while(SPIF == 0)
      {
      y++;
      }      //                   /

 
      SPDR = 0x40;  // Ausgabe an das Spi interface     
      while(SPIF == 0)
      {
      y++;
      }

        SPDR = 0xAA;  // Ausgabe an das Spi interface      FREQU-0
      while(SPIF == 0)
      {
      y++;
      }      //                    /


    warte(9);
  }
}
 


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stein schrieb:

> fehler wie gehabt, die spi sendet nur das 1. wort

Wie schon gesagt.
Da wird wohl SPIF niemals 0 werden.

<Sarkasmus ein>
Das mag wohl auch daran liegen, dass SPIF kein Register ist, sondern ein 
Makro, welches die Bitnummer des SPIF-Bits im SPSR Register angibt. Und 
auch wenn du darauf wartest, die Bitnummer dieses Status-Bits wird sich 
wohl in der Lebenszeit dieses Universums in diesem Register nicht mehr 
ändern.
<Sarkasmus aus>

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
du kannst doch nicht so schnell die Lösung präsentieren, wo bleibt denn 
da der Spaß?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> du kannst doch nicht so schnell die Lösung präsentieren, wo bleibt denn
> da der Spaß?

Na ja.
Er hat immerhin seit gestern Nachmittag immer noch nicht geschnallt, 
dass die Lösung all seiner Probleme lautet: Im Datenblatt nachschauen.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber er kennt die Formatierung mit
[c]
...
[/c]
schon. Mit ein bißchen Nacheinrücken etc. wird es ja fast lesbar...

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich habe im buch über die spi schnittstelle gelesen, dass das spif 
bit anzeigt das das wort von der spi versand wurde.
Also wollte ich nun darauf pollen, bis die spi wieder bereit ist.
WO IST DER FEHLER???

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stein schrieb:
> WO IST DER FEHLER???

Der Fehler ist ... das du dich standhaft weigerst im Datenblatt 
nachzusehen in welchem Register das SPIF Bit beheimatet ist und dann 
eine korrekte Abfrage eines Bits in einem Register zu programmierern

   if( Register & ( 1 << BitNummer ) )
     Bit ist gestzt
   else
     Bit ist nicht gesetzt

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für die antwort.

ich dachte das man mit einer while auch einzelne bits abfragen kann.
das das nur ein bit ist weis ich, das es im spsr reg ist auch.

Autor: Skua (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. Aber "wo" ist das Bit?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst in einer while-Bedingung auch auf Bits testen.

Vielleicht liegt das Problem nur darin, daß du vermutest,
daß SPIF das Bit im richtigen Register bezeichnen würde.
Tut es aber nicht, es ist nur die Nummer - z.B. 7.
SPIF ist nur die Nummer des Bits. Erst in Kombination mit einem
Register wird daraus das Bit im Register.

Das SPIF-Bit bekommst du also nicht mit "Nummer 7", sondern
erst mit "Nummer 7 im Register SPSR".

Also nicht: while( SPIF !=0 )...
Sondern: while( (SPSR & (1<<SPIF)) !=0 ) ...

SPIF (also die 7) könnte man genauso gut auf alle anderen
Register anwenden, es ist genau das Gleiche wie PA7 und PB7
und PC7 ...

Ich fand es am Anfang auch verwirrend, jetzt zumindest unelegant.
Aber was will man machen.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und warum ist dieser Warteschleifen-Verschnitt immer noch drin?

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
a ok danke karl heinz, jetzt hab ich es verstanden!

Autor: Stein (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannst du mir noch sagen wie der code dazu aussieht?

mit
while( (SPSR & (1<<SPIF)) !=0 )
hat es leider nicht funktioniert.

Autor: Siegfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ursprüngliche Code besaß mehrere aufeinander folgende Blöcke mit 
etwa folgendem Inhalt:

    SPDR = 0x40;  // Ausgabe an das Spi interface
    while(SPIF == 0)
    {
      y++;
    }
--------------------------
Herr Klaus Wachtler  hatte dieses korrigiert mit den Worten :

Also nicht: while( SPIF !=0 )...
Sondern: while( (SPSR & (1<<SPIF)) !=0 ) ...

--------------------------
Der Hersteller ATMEL stellt das folgende Dokument zur Verfügung:
http://www.atmel.com/dyn/resources/prod_documents/...

und darin das Beispiel:

void SPI_MasterTransmit(char cData)
{
  /* Start transmission */
  SPDR = cData;

  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)))
  ;
}

Da das SPIF-Bit im SPSR-Register erst NACH dem Versenden auf den Wert 1 
gesetzt wird, wird wohl  „while( 0 == (SPSR&(1<<SPIF)) );“  dem 
ursprünglichem Gedanken, den ich mit den Worten umschreiben möchte: „ich 
trete auf der Stelle bis das Byte gesendet ist“, am ehesten entsprechen.

Leider verstehe ich den Sinn der „y++;“ innerhalb der vielen „while()“ 
nicht. Ich weiß wohl, das y stets um 1 incrementiert wird, aber ich 
frage mich „warum?“

In Abhängigkeit der „SPI Clock Rate“, siehe hierzu die Beschreibung der 
Bits SPI2X, SPR1 und SPR0, werden alle „while()“ und somit auch ihre 
jeweiligen „y++“ in jedem Fall mehr als nur einmal bearbeitet. Zudem ist 
die Anzahl der Durchläufe von der Qualität des Compilers, hier 
insbesondere durch die Übersetzung des while() in den Assemblercode, 
bestimmt und die Portabilität geht verloren. Ich erwarte hier 
interessante Effekte, wenn das Projekt an Umfang gewinnt und irgendwann 
Interrupts ins Spiel kommen: der Endwert des y wird dann einem 
Zufallszahlengenerator entsprechen.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Da das SPIF-Bit im SPSR-Register erst NACH dem Versenden
> auf den Wert 1 gesetzt wird, wird wohl
> „while( 0 == (SPSR&(1<<SPIF)) );“  dem
> ursprünglichem Gedanken, den ich mit den Worten umschreiben
> möchte: „ich trete auf der Stelle bis das Byte
> gesendet ist“, am ehesten entsprechen.

Das ist soweit korrekt, aber ineffizient, weil nach dem Absenden* eines 
Bytes eine komplette Bytezeit gewartet wird.

Sinnvoller ist es, vor dem Absenden* das Bit zu überprüfen und 
gegebenenfalls zu warten, bis es gesetzt wird. Dann nämlich kann das 
Programm sofort nach dem Absenden* weiterlaufen und die Rechenzeit 
sinnvoll nutzen. Wenn sofort danach ein weiteres Byte übertragen werden 
soll, dann muss natürlich gewartet werden, bis das Bit gesetzt ist, wenn 
aber zunächst irgendwelche Berechnungen o.ä. angestellt werden müssen, 
und danach erst ein weiteres Byte zu senden ist, können diese angestellt 
werden, derweil das vorhergehende Byte noch übertragen wird.

*) Beschreiben von SPDR

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.