Forum: Mikrocontroller und Digitale Elektronik Chip Select SPI


von Dirk (Gast)


Lesenswert?

Hi,

ich nutze am HW SPI meines Mega8 ein LCD Display.
Damals hatte ich den CS Pin Hardwaremaessig auf Masse gelegt somit war
das LCD Display immer aktiv. Nachdem ich mir eine neue Platine geaetzt
habe spreche ich den CS Pin des Display's per I/O Pin an. Jetzt fangen
damit meine Probleme an.

Der CS Pin vom Display liegt ueber ein Pull Up Widerstand von 10k auf
5V.

Lege ich meine Aktivierung des Display's  mit in die SPI Sende Routine
funktioniert es nicht und das Display wird nicht angesprochen.

Setzte ich den I/O Pin vor den LCD Routinen auf LOW geht es. Leider
finde ich im Datasheet auch keine Angabe wie frueh ich den CS Pin auf
Low ziehen muss bevor ich Daten sende und wielange der Pin nach der
Uebertragung LOW bleiben muss.

Gibt es da Richtwerte?

Ich hoffe jemand kann mir ein Rat geben. Ich wollte mich nicht immer
extra um die Aktivierung des CS Pin's kuemmern, sondern diese einmal
in meine SPI Sende Routine einbauen.

Mfg
Dirk

So funktionert es:

PORTLCD &= ~(1<<CS_LCD); /* SS Pin low */
lcd_init();
lcd_clear();
lcd_chr('o');
PORTLCD |= (1<<CS_LCD); /* SS Pin high */

so funktionert es leider nicht

void SPI_sende (unsigned char aData)
{
  PORTLCD &= ~(1<<CS_LCD); /* SS Pin low */
  SPDR = aData;              while(!(SPSR & (1<<SPIF))); 
PORTLCD |=
(1<<CS_LCD); /* SS Pin high */
}

von Hagen (Gast)


Lesenswert?

Ein ähnliches, wenn nicht sogar das gleiche Problem hatte ich bei der
Ansteuerung des Nokia LCDs. Es ist nämlich aus Sicht der EMV wichtig
das das LCD nur solange aktiv ist wie Daten übertragen werden, da
ansonsten die Wahrscheinlichkeit sehr ansteigt das man Fehler in der
Datenübertragung bekommt und der Controller des LCDs nicht mehr
anspricht.

Ich benutze grundsätzlich den SPI Interrupt. Dieser zieht nach dem
Senden das CS auf High und deaktiviert das SPI. Vor dem Senden eines
Bytes wird nun überprüft ob CS High ist. Falls ja wird CS aktiviert,
sprich das LCD aktiviert. Falls CS schon auf Low liegt wird einfach
darauf gewartet das die vorherige SPI Übertragung ready. Danach wird
das nächste Byte gesendet.

Somit hat man zwei Fliegen mit einer Klappe erschlagen:
1.) die Senderoutine kann direkt überprüfen ob sie auf die Beendigung
einer vorherigen Datenübertragung warten muß. Danach aktiviert diese
Routine CS.
2.) nach erfolgreicher Übertragung eines Bytes per SPI wird automatisch
im Hintergrund per Interrupt das CS des LCD's wieder deaktiviert. Somit
muß man sich darum nicht mehr explizit kümmern und die Zeitspanne der
Aktivierung des LCDs ist so kurz wie nötig.

Die SPI-ISR sieht so aus:

        sbi     LCD_PORT, LCD_CS     // deaktiviere LCD ~CS
        cbi     LCD_SPCR, SPE        // deaktiviere SPI
        reti

Die 1 Byte Senderoutine sähe so aus:

glcdDispSend:
        sbic    LCD_SPCR, SPE        // warte bis SPI deaktiv
        rjmp    glcdDispSend

        cbi     LCD_PORT, LCD_CS     // ~CS auf Low, LCD aktiv
        sbi     LCD_SPCR, SPE        // SPI aktivieren
        out     LCD_SPDR, DATA       // Daten senden
        ret


Gruß Hagen

von Dirk (Gast)


Lesenswert?

Hi,

ok ist klar wieso man den Teilnehmer nur solange atkiviert solange
Daten uebertragen wird.
Desto weniger ist mir klar wieso diese Funktion nicht funktioniert.
Es wird naemlich vor der Uebertragung das LCD aktiviert. Dann die Daten
rausgeshiftet solange bis SPIF != 1 ist und dann wird das LCD wieder
deaktiviert.

Sehr komisch :/

Mfg
Dirk


void SPI_sende (unsigned char aData)
{
 PORTLCD &= ~(1<<CS_LCD); /* SS Pin low */
 SPDR = aData;
 while(!(SPSR & (1<<SPIF)));
 PORTLCD|=(1<<CS_LCD); /* SS Pin high */
}

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.