mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI unstabil


Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

ich bin gerade dabei, mir ein LCD-Modul zu basteln, was ich über I2C und 
über SPI ansteuern kann. Auf dem Modul sitzt ein ATmega8, angesprochen 
wird es auch von ATmegas.
I2C funktioniert schon, allerdings habe ich mit dem SPI Probleme...
Manchmal funktioniert die Übertragung schlecht, manchmal garnicht, 
manchmal bricht sie zusammen...
Habe schon öfter mit SPI gearbeitet, aber noch nie solche Probleme 
gehabt...
Habe die beiden Platinen mit einem Flachbandkabel verbunden, schon 2 
verschiedene Sender ausprobiert (um Hardwarefehler auszuschließen). Auf 
dem LCD-Modul sollte auch kein Hardware-Fehler sein, die Leitungen sind 
sauber von einander getrennt.

Ansteuerroutinen sind folgende (Ausschnitt)
Sender
void lcdSPIInit(uint8_t operation){ //1: save SPI-settings, Init lcd SPI; 0: restore SPI
  static uint8_t spcr;
  static uint8_t spiPort, spiDDR;

  if(operation == 1){
    spcr = SPCR;
    spiPort = SPI_PORT;
    spiDDR = SPI_DDR;

    CHIPSELECT_DDR |= (1<<CHIPSELECT_PIN);

    SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
    SPI_PORT |= (1<<MOSI_PIN) | (1<<SCK_PIN);
    SPI_DDR |= (1<<MOSI_PIN) | (1<<SCK_PIN);
    CHIPSELECT_PORT &= ~(1<<CHIPSELECT_PIN);
  }else if(operation == 0){
    CHIPSELECT_PORT |= (1<<CHIPSELECT_PIN);
    _delay_us(1);
    SPI_DDR = spiDDR;
    SPI_PORT = spiPort;
    SPCR = spcr;
  }

}

void lcdSPI_data(char data){   //Char ausgeben
  lcdSPIInit(1);
  SPDR = data;
  while(!SPI_READY);
  _delay_us(10);
  SPDR = 1;
  while(!SPI_READY);
  lcdSPIInit(0);
  _delay_ms(5);
}

void lcdSPI_string(char *data){    //Char-Array ausgeben
  lcdSPIInit(1);
  while(*data){
    SPDR = *data;
    while(!SPI_READY);
    _delay_us(20);
    data++;
  }
  SPDR = '\0';
  while(!SPI_READY);
  _delay_us(20);
  SPDR = 2;
  while(!SPI_READY);
  lcdSPIInit(0);
  _delay_ms(5);
} 


Empfänger:
int main(void){
  volatile char i;

  _delay_ms(10);
  extern char buf[17];
  SPIInit();
  TWIInit();
  lcd_init();
  DDRC |= 0x08;  //Hintergurndbeleuchtung
  PORTC &= ~0x08; //aus

  buf[16] = 0;  //absicherung, um ein unabgeschl. Array zu vermeiden

  sei();

  while(1){
    i++;
  }

  return 0;
}


void SPIInit(void){
  DDRB &= ~0x2C;  //SCK,MOSI,SS is Input
  DDRB |= 0x10;   //MISO Output

  SPCR = (1<<SPIE) | (1<<SPE);
}


ISR(SPI_STC_vect){
  extern uint8_t data, bufpos;
  extern char buf[17];

  data = SPDR;

  if(data <= 31 && data != 0){
    switch(data){
      case 1:
        lcd_data(buf[0]);
      break;
      case 2:
        lcd_string(buf);
      break;
      case 3:
        lcd_clear();
      break;
      case 4:
        lcd_set_cursor(buf[0]-40, buf[1]-40);
      break;
      case 5:
        PORTC |= 0x08;  //Hintergrundbeleuchtung an
      break;
      case 6:
        PORTC &= ~0x08;  //Hintergrundbeleuchtung aus
      break;
      default: lcd_string("SPI-ERROR!!");
    }
    bufpos = 0;
  }else if(bufpos < 16){
      buf[bufpos++] = data;
  }
}

Ich sitzt schon seit einigen Stunden an diesem Problem, komme dem Fehler 
aber nicht auf die schliche...

Sieht jemand vielleicht was?

Gruß, Yaro

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mit lcdSPI_data(char data) sende, kommt es seltener zu 
Störungen.
Wenn ich mit lcdSPI_string(char *data) "Hello World" sende, dann ist der 
häufigste Fehler, dass statt dem o ein y ankommt, und der 
zweithäufigste, dass statt dem l ein c kommt... Oder es kommt überhaupt 
kein String an...
Die Fehler sind zwar oft die selben, lassen sich aben nicht (nicht in 
der gleichen Reihenfolge) reproduzieren, sondern sind zufällig.

Gruß, Yaro

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bekomme das Problem ein wenig in Griff, wenn ich nach jedem Byte die 
SS-Leitung hoch und dann wieder runterziehe, um das SPI zu resetten. 
Dann verliere ich beim Senden zwar öfters mal einen Buchstaben, aber der 
Rest bleibt ok.
Trotzdem ist das doch kein wünschenswerter Zustand!
Ich hab mit SPI bisher noch nie solche Probleme gehabt! Es lief immer 
ohne Probleme!

Woran könnte sowas liegen?
Ich bin für jeden Tip dankbar!

Gruß, Yaro

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du mußt das SPI im Empfänger puffern, da das LCD langsam ist.
Besonders ein Clear ist grausam, sollte man aber eh nicht verwenden, da 
dann das LCD flackert.
Professioneller ist, immer den Text überschreiben.


Peter

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du "überfährst" den Empfänger wahrscheinlich einfach. Bedenke, dass dort 
Software die Bytes einzeln abholen muss. Und durch die LCD-Routinen im 
SPI-Interrupt ist es obendrein manchmal ziemlich langsame Software.

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich puffere den Empfänger. Auf das LCD gebe ich den Text erst dann aus, 
wenn das letzte Zeichen angekommen ist.
Ich schreibe zuerst alles in den Puffer, danach kommt dann das 
Steuerzeichen, mit dem das Modul weiß, was es mit den angekommenen Bytes 
tun soll.

Gruß,  Yaro

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe gerade mal den Prescaler verändert... ob ich ihn auf 16 oder auf 
128 habe, die Fehler sind die selben.

Autor: bensch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die SPI-Moden der beiden Teile nicht zusammenpassen, gibt's 
Timing-Probleme.

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ursache gefunden! Begründung nicht!
Wenn ich im LCD-Modul MISO nicht als Output deklariere, dann geht alles 
ohne Fehler... (benutze MISO sowieso nicht)
Wie kann das sein?

Gruß, Yaro

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schaltplan bitte :-)

Autor: Yaro (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Im Schaltplan ist eigentlich nix besonderes...
Hab die Anschlüsse nicht beschriftet, aber da da kaum was ist, sollte 
man es erkennen.

Gruß, Yaro

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem stimmen die Werte an den Kondensatoren nicht...
Hatte nicht geplant, diesen Schaltplan jemandem zu zeigen....*schäm*

Autor: Benjamin S. (recycler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltes Pullup- und Pulldown Widerstände verwenden. Dann schauts 
besser aus. Ausserdem auf das Timing achten.

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo sollen die Pullups und Pulldowns denn hin?
Ich dachte immer, SPI braucht keine externe Beschaltung.

Gruß, Yaro

Autor: Benjamin S. (recycler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Je schneller die Daten über den Bus gehen, umso mehr musst du an 
Beschaltung bzw. Layout machen. Bei MOSI MISO SCK nach GND und bei CS 
AUF VCC. Nimm mal 10k, wenn das zu viel ist, dann 1k. Das brauchst du, 
weil du immer Kapazitäten auf der Leitung hast.
Bei mir ging das bis 25 MHz gut, dann mochte der Controller nimmer.

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Werde ich beim nächsten Schaltplan berücksichtigen, danke!
Aber eine Antwort darauf, wieso  es mit MISO nicht geht und ohne schon.
Arbeite mit 16MHz, prescaler 16.

Gruß, Yaro

Autor: Yaro (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
EDIT: Aber eine Antwort darauf, wieso  es mit MISO nicht geht und ohne 
schon ...ist es nicht....
Sorry, bin im Moment echt ein bisschen gestresst....

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.