mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit SPI (Mega16)


Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen, allerseits.

Habe ein Problem mit meiner SPI Schnittstelle, diese funktioniert nur 
sporadisch. Nach mehrmaligen resetten funktioniert es dann mit Glück 
mal.

Ich steuere 2 74HC595 Schieberegister darüber an, initialisiert wird wie 
folgt:

SS/ wird als Enable-Leitung für die Schieberegister benutzt und is wie 
unten zu sehen als Ausgang definiert.
//SPI INIT
SPCR |= (1<<SPE) | (0<<DORD) |(1<<MSTR) | (1<<CPHA) | (1<<CPOL) | (1<<SPR0);
SPSR |= (1<<SPI2X);
DDRB |= (1<<PB5) | (1<<PB7) | (1<<PB4);
  
SPDR = 0x01;

Sende und Enable Funktion sehen wie folgt aus:
void SR_enable()
{
  SR_On;
  
  SR_Off;
}

void SR_Out(uint16_t cData)
{
  SPDR = (cData & 0xFF00) >> 8; //Oberes Nibble übergeben
  while(!(SPSR & (1<<SPIF)))
    {;}
  SPDR = (cData & 0x00FF);  //Unteres Nibble übergeben
  while(!(SPSR & (1<<SPIF)))
    {;}

  SR_enable();
}

Vor allem die Tatsache das es mal funktioniert und dann wieder nicht 
macht mich ratlos ....

Immoment schalte ich damit testweise eine 6x3 LED-Matrix an um die 
Funktion von SPI usw. zu lernen.

Ich benutz das Pollin Eval-Board mit einer Zusatzplatine...
Hardwareseitig hab ich nicht sehr auf terminierung geachtet. Mit 
geringerer SPI Clock ist aber das selbe Problem festzustellen.

Wäre toll wenn mir jemand Tipps oder Lösungsvorschläge geben könnte :)

Gruß,
Christian

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Chris (Gast)

>SS/ wird als Enable-Leitung für die Schieberegister benutzt und is wie
>unten zu sehen als Ausgang definiert.

>//SPI INIT
>SPCR |= (1<<SPE) | (0<<DORD) |(1<<MSTR) | (1<<CPHA) | (1<<CPOL) | >(1<<SPR0);
>SPSR |= (1<<SPI2X);
>DDRB |= (1<<PB5) | (1<<PB7) | (1<<PB4);

Sieht gut aus.

>Sende und Enable Funktion sehen wie folgt aus:

>void SR_enable()
>{
>  SR_On;
>
>  SR_Off;
>}

Erzeugt wahrscheinlich eine steigende Flanke an RCK. Kann man aber ohne 
die Makrodefinition nicht sagen.

>void SR_Out(uint16_t cData)
>{
>  SPDR = (cData & 0xFF00) >> 8; //Oberes Nibble übergeben

Das ist ein Bytes, kein Nibble (4Bit). Da muss nix maskiert werden, 
schieben reicht.

Sieht eigentlich OK aus. Hmmm.

>Ich benutz das Pollin Eval-Board mit einer Zusatzplatine...

Ich hoffe du hast auch Masse verbunden. Und 100nF an den 
Schieberegistern.

MfG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, das mit dem maskieren kann ich mir dann sparen.

Wie du richtig erkannt hast erzeugt die SR_Enable eine steigende Flanke 
an RCK:
#define SR_On    PORTB |= (1<<PB4);
#define SR_Off    PORTB &=~(1<<PB4);

An den Schieberegistern sind jeweils 100nF und Masse ist 100%ig 
verbunden :)
Sonst würde garnichts gehen.
Wie gesagt, mal geht es mal nicht, nach mehreren Resets kann es dann mal 
gehen, wenn man nochmals resettet gehts vll. schon nicht mehr. Ganz 
komisch :-/
Könnten bei dieser sache evtl. Interrupts reinpfuschen? Ich habe ein 
Timerinterrupt der jede 10ms Tasten abfrägt (Aus der Code Sammlung).

Gruß,
Christian

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

Bewertung
0 lesenswert
nicht lesenswert
Habe mal den Quelltext angehängt, vielleicht liegt der Fehler woanders 
und ich sehe ihn nicht.

gruß,

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste mal deinen kompletten Quelltext. Als Anhang.

MFG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab ein paar sachen rausgenommen die eh nicht benutzt worden sind, sieht 
ein bisschen unaufgeräumt aus ...

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

Bewertung
0 lesenswert
nicht lesenswert
So würde dann das Kernprogramm aussehen :)
Hab ein extra Projekt angelegt, der Fehler is der gleiche...
Wenn ich das Zusatzboard abtrennt, den AVR im reset halte und 
währrendessen das Board wieder einstecke und den Reset loslasse, 
funktionierts ....
Hab extra darauf geachtet dass das Verbindungskabel nicht lang ist, ist 
ein 5cm Flachbandkabel, übertragungsstrecke dürfte insgesamt ca. 10cm 
sein.
Werd nacher mal mitm Oszi dran gehen ...

Gruß,

Autor: Michael H* (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich hätte die vermutung, dass deine impulse am SS zu kurz sind. setz 
doch in deine void SR_enable() ein paar nops rein.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man, das wars. Ich krach ab =)
Hab mich wohl im Datenblatt verlesen....
Danke vielmals :)

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Oh man, das wars.

Man verwendet ja für sowas auch keine Nadelimpulse!

Wie wäre es etwa so:
// slave aktivieren
SR_Off
//Oberes Nibble übergeben
SPDR = (cData & 0xFF00) >> 8; 
while(!(SPSR & (1<<SPIF)));
//Unteres Nibble übergeben
SPDR = (cData & 0x00FF);    
while(!(SPSR & (1<<SPIF)));

// übernehmen
SR_On


Autor: Michael H* (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja genau, das wäre die typische spi. nur bei schieberegistern braucht 
man halt eher einen acknowledge puls. am besten einen nicht zu kurzen ^^

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, das andere war um Welten umständlicher :P

Danke nochmals

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>halt eher einen acknowledge puls

Hm.. Der 595er braucht ne positive Flanke zum übernehmen, was ds SIgnal 
dann macht, spielt keine Rolle.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Matthias Lipinsky (lippy)

>Man verwendet ja für sowas auch keine Nadelimpulse!

Käse. Wo ist das ein Nadelimpuls? Der Puls ist min. zwei Takte lang, 
macht selbst bei 16 MHz schnarchlangsame 125ns. In der Zeit schaltet der 
74HC595 zehnmal! Ich tippe mal eher auf wildes Klingeldrahtvehau, das 
tierische Resonzanzen erzeugt. Dann ist es klar dass ein so kurzer Puls 
Probleme hat, das Ende der Leitung halbwegs sauber zu erreichen.

MFG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf Verdrahtung hab ich weniger Wert gelegt, ist aber ne gefräste 
Platine. Nicht von Hand verdrahtet, aber nun gehts und ich kann mal 
weiter machen.
Danke nochmals :)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Chris (Gast)

>Auf Verdrahtung hab ich weniger Wert gelegt, ist aber ne gefräste
>Platine.

Und die Verbindung vom Pollinboard zu der Platine?
Mach mal bitte ein Bild von deinem Aufbau, zwecks Studien und 
Fehlerdiskussion. Aber bitte unter Beachtung der Bildformate.

MfG
Falk

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>schnarchlangsame 125ns

>ein so kurzer Puls


Na, was denn nun ;-)

Aber mit meinem Vorschlag tritt das problem nicht auf...


**duck und weg**

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

Bewertung
0 lesenswert
nicht lesenswert
So hab mal versucht ein Bild zu machen g
Werde morgen bei Bedarf ein besseres machen. Wäre nett wenn ihr mir 
Tipps zur Leitungsführung geben könntet, später wird nämlich daraus ein 
kommerzielles Produkt (umfangreicher aber auch mit SPI).
Immerhin funktionierts jetzt mehr oder weniger, ab und an setzts 
immernoch aus, werde noch ein bisschen rumprobieren...

gruß,

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ein kommerzielles Produkt?

Dann kostet mein Codeschnipsel aber mindestens eine Flasche Schnaps ;-)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Chris (Gast)

>Immerhin funktionierts jetzt mehr oder weniger, ab und an setzts
>immernoch aus, werde noch ein bisschen rumprobieren...

MESSEN! Mit den Scope am Schieberegister. Ordentlichen Tastkopf 
verwenden, 10:1, Masse DIREKT an der Spitze (der Metallring) auf Masse 
legen.

MfG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weis wie man mit nem oszi umgeht :)
Ich werd morgen mal messen, hab aber das Gefühl das es einfach mit dem 
Layout in Verbindung steht. Wenn an RCK keine saubere Flanke anstehen 
würde, würde es garnicht funktionieren. Wenn es mal funktioniert, 
funktioniert es bis ich wieder resette, von daher glaub ich weniger das 
es mit SS/ bzw. RCK zu tun hat. Werde morgen aber mal messen und 
testweise ein delay nach dem Senden der Daten und vor dem RCK einbauen. 
Ich melde mich morgen dann wieder nach den testen.

Danke nochmals.
Gruß,

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Morgen, also wenn die Schaltung nicht funktioniert, was sie immernoch 
nicht zuverlässig macht, habe ich weder eine SPI Clock noch Daten auf 
MOSI oder Enable Flanken an RCK. Könnte es sein das der Mega16 ne Macke 
hat?
Womit das ganze geringfügig besser läuft ist wenn ich nach der 
Steigenden RCK Flanke 1ms Pause mache und dann erst wieder auf low 
ziehe.
Ich werde gleich mal ein anderen Mega16 probieren...
Melde mich später wieder.

gruß,

Autor: W. Bl (wb1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig sehe, benutzt du Flachkabel.
Mein Vorschlag:
baue das kabel so um, das du jeweils zwischen einer Signalleitung eine 
Masseleitung hast.
Ich glaube, die Leitungen übersprechen. Durch die zusätzliche 
Masseleitung zwischen den Signalleitungen bekommst du eine Abschirmung

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ W. Bl (wb1)

>baue das kabel so um, das du jeweils zwischen einer Signalleitung eine
>Masseleitung hast.

Naja, das ist die Luxusvariante. Zwei Masseleitungen jeweils genau neben 
den Takten sollten reichen.

Wellenwiderstand

>Ich glaube, die Leitungen übersprechen. Durch die zusätzliche
>Masseleitung zwischen den Signalleitungen bekommst du eine Abschirmung

Naja, das ist die stark vereinfache Erklärung ;-)
Die induktive Kopplung ist wesentlich problematischer als die 
kapazitive.

MFG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab jetzt mit Hilfe von Debug LEDs herrausgefunden das es garnichts mit 
dem Enable der Schieberegister zu tun hat. Der Controller ist auch ok.
Die Initialisierung läuft einwandfrei ab, beim Senden scheint er sich 
aber zu verabschieden:
void SR_Out(uint16_t cData)
{
  Debug1_on;
  //Slave aktivieren
  SR_Off;
  
  //Oberes Byte übergeben
  SPDR = cData >> 8; 
  while(!(SPSR & (1<<SPIF)))
    {;}
  Debug2_on;

  //Unteres Byte übergeben
  SPDR = cData ;
  Debug3_on;
      
  while(!(SPSR & (1<<SPIF)))
    {;}
      
  //übernehmen
  SR_On;
  
}
Debug LED 2 leuchtet noch, Debug 3 nicht mehr.
Das es mit den Leitungen zutun hat kann ich mir nicht vorstellen, denn 
wenn es funktioniert ist egal welche SPI Clock ich habe (max. /4 
probiert). Wenn es nicht funktioniert gibt es kein einziges Signal am 
Schieberegister.
Es muss was software technisches sein aber ich komm grad nicht drauf...

Gruß,

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht es eigentlich mit der Initialisierung aus, man sollte doch ein 
Dummy Bate senden, ist das richtig so:
//SPI INIT
  SPCR |= (1<<SPE) | (0<<DORD) |(1<<MSTR) | (1<<CPHA) | (1<<CPOL) | (0<<SPR0);
  SPSR |= (0<<SPI2X);
  DDRB |= (1<<PB5) | (1<<PB7) | (1<<PB4);
  
  SPDR = 0x01;
Oder muss ich danach noch SPIF manuell setzen?

Autor: Branko Golubovic (branko)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich benutze für HC595 aber SPI-Mode 2:
SPI MODE2 CPOL=1,CPHA=0 -> Sample(Falling), Setup(Rising)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Branko Golubovic (branko)

>Ich benutze für HC595 aber SPI-Mode 2:

>SPI MODE2 CPOL=1,CPHA=0 -> Sample(Falling), Setup(Rising)

Das ist ein wenig riskant. man solle 0 oder 3 wählen.

@ Chris (Gast)

>  while(!(SPSR & (1<<SPIF)))
>    {;}

das scheint mir etwas komisch. jaja, nach C wahrscheinlich OK, aber 
warum so? Probier mal

>  while(!(SPSR & (1<<SPIF)));


>Debug LED 2 leuchtet noch, Debug 3 nicht mehr.

Ich glaube du schreibst zu schnell nach der Initialisierung rein. 
Probiers mal so.

void SR_Out(uint16_t cData)
{
  Debug1_on;
  //Slave aktivieren
  SR_Off;
  
  //Oberes Byte übergeben
  while(!(SPSR & (1<<SPIF)));
  SPDR = cData >> 8; 
  Debug2_on;

  //Unteres Byte übergeben
      
  while(!(SPSR & (1<<SPIF)));
  SPDR = cData ;
  Debug3_on;
  
  while(!(SPSR & (1<<SPIF)));    
  //übernehmen
  SR_On;
}

MFG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal für eure Hilfe.
Mit deiner Funktion komm ich auch nicht an Debug3, sieht aus als ob er 
sich beim senden des ersten Bytes aufhängt. Wie sieht das mit dem Dummy 
Byte aus, hab ich das richtig gemacht ein was ins register zu schreiben 
und sonst nichts weiter zu tun?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Chris (Gast)

>sich beim senden des ersten Bytes aufhängt.

> Wie sieht das mit dem Dummy Byte aus, hab ich das richtig gemacht ein was > ins 
register zu schreiben

Ja

und sonst nichts weiter zu tun?

Nein. Bestenfalls auf das Ende der Übertragung warten.

MOMENT! Falsche Reihenfolge!

ERST die IOs konfigurieren, DANN SPI. Sonst spuckt dir ggf. das SS-Pin 
dazwischen!

http://www.mikrocontroller.net/articles/AVR-Tutori...
void init_avr()
{
  uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

  TCCR0 = (1<<CS02)|(1<<CS00);      // divide by 1024
    TIMSK = 1<<TOIE0;        // enable timer interrupt
  sei();

  // IO ZUERST konfigurieren!
  DDRB |= (1<<PB5) | (1<<PB7) | (1<<PB4);

  //SPI INIT
  SPCR |= (1<<SPE) | (0<<DORD) |(1<<MSTR) | (1<<CPHA) | (1<<CPOL) | (1<<SPR0);
  SPSR |= (1<<SPI2X);  
  SPDR = 0x01;

MfG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wow falk, besten dank. Ich bin begeistert :)
Das ganze funktioniert auch bei 4MHz SPI-Takt .
Das es doch so einfach ist, hätte aber auch nicht gewusst was noch 
falsch sein kann.
Daaaanke :)

gruß,

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Chris (Gast)

>Daaaanke :)

De nada.

Dann geht wohl die von  Matthias Lipinsky beansspruchte Flasche Schnaps 
an mich. Martini Blanco wenns recht ist ;-)

MFG
Falk

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:-P
Das Projekt läuft nun 2 Tage, bis zu einem fertigen Produkt das wir in 
unsere Systeme einbauen wird noch ne Weile vergehen aber ich denk an 
euch :-)

gruß,
Christian

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Falk Brunner (falk)
>eansspruchte Flasche Schnaps an mich.
void SR_Out(uint16_t cData)
{
  //Slave aktivieren
  SR_Off;
  //Oberes Byte übergeben
...
  //Unteres Byte übergeben
...
  //übernehmen
  SR_On;
}

Moment.. Meine Anregung ist auc noch drin, also entweder je eine 
Flasche, oder brüderlich teilen:
Du die Flasche, ich den Inhalt..

hicks...

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.