Forum: Mikrocontroller und Digitale Elektronik Probleme mit Schieberegister


von Hugoderwolf (Gast)


Lesenswert?

Ich habe ein paar Datenleitungen zu meinem LCD über ein Schieberegister
geführt zwecks Leitungssparen. Es sollen also die 8 Bit nacheinander
ins Schieberegister eingegeben werden. Mein Programm (im AVR8515) setzt
als bit 7 an den Eingang, schickt einen Puls und macht mit Bit6 weiter
bis Bit0. Schön. Dummerweise klappt das nicht... :(
Nach einigen Messungen scheint am Schieberegister an allen Ausgängen
ständig der Pegel am Eingang anzuliegen! Kaputt ist es nicht, habe
mehrere davon die sich alle gleich verhalten.
Es handelt sich um einen 4015 bei dem ich die beiden 4bit-register
gekoppelt habe, um ein 8Bit-Shiftreg zu bekommen. Kann es daran liegen?
Bit 4 vom ersten an den Eingang vom zweiten und beide Clocks
gleichzeitig angesteuert mit einem Pin vom µC.

Bin mit meinem Latein leider am Ende. :(

Danke schonmal,
Christian

von Manfred Glahe (Gast)


Lesenswert?

Hallo

Nein, daran kann es nicht liegen! Bevor sich der Ausgang ändern kann
(typ 30 nS), ist er schon im 2. Reg. eingelesen (HoldTime typ 10 nS).
Selbst unter den schlechtesten Umständen muß das funktionieren!
Ist MR verschaltet? Stimmt die Betriebsspannung?

MfG  Manfred  Glahe

von OldBug (Gast)


Lesenswert?

Poste mal Schaltplan und Code, hab da so die Vermutung, daß Du nach
jedem Bit die Daten auf den Ausgang gibst...

Gruß,
Patrick...

von Hugoderwolf (Gast)


Lesenswert?

Master Reset ist laut Datenblatt Active High, also habe ich den auf GND
gelegt, das müsste doch richtig sein oder? Einen richtigen Schaltplan
habe ich nicht gezeichnet. Die Schaltung ist nicht allzu komplex und
auf Lochraster aufgebaut.

An einem Pin liegt D1, am anderen Pin CP1 und CP2. Die Ausgänge Q1_0
bis Q1_3 und Q2_0 bis Q2_3 gehen ans Display, Q1_3 geht zusätzlich noch
an D2. Versorgungsspannung 5V geregelt.

Den Original-Code müsste ich jetzt erst von meinem PC runterziehen,
aber geht ja schnell. Sollte ziemlich genau der hier sein:

// Den Eingang D7 vom LCD habe ich am Shiftregister vorbeigeführt, um
das Busy-Flag lesen zu können. LCD_PORT, LCD_D7, SR_DI und SR_CP sind
entsprechend der Pin-Konfiguration definiert.

  int i;
  char test = 0xAA;

  if((test >> 7) & 1)
    sbi(LCD_PORT, LCD_D7);
  else
    cbi(LCD_PORT, LCD_D7);

  for(i=6;i>=0;i--) {
    if((test >> i) & 1)
      sbi(LCD_PORT, SR_DI);
    else
      cbi(LCD_PORT, SR_DI);
        sbi(LCD_PORT, SR_CP);
        cbi(LCD_PORT, SR_CP);
  }

Ich hoffe, das ist aufschlussreich...

von Manfred Glahe (Gast)


Lesenswert?

@Hugoderwolf

Beide MR auf GND ist richtig. Ich hatte noch nach der Betriebsspannung
gefragt. Ist die richtig zur Platine verdrahtet? Ansonsten können Deine
Angaben nicht stimmen!
Nimm nur die Platine, erzeuge mit einem Schalter den Takt und ändere
den Eingang (Schalterprellen macht hier nichts aus) von 0 auf 1 und
umgekehrt. Was tut sich am 1. Q- Ausgang?

MfG  Manfred Glahe

von crazy horse (Gast)


Lesenswert?

naja - am Takteingang macht Prellen schon was aus, das geht nicht mit
einem einfachen Schalter/Taster.

von Manfred Glahe (Gast)


Lesenswert?

@crazy horse

Es geht hier nur darum auszuprobieren ob sich der Ausgang Q ändert! Und
dabei ist es egal ob ers beim ersten oder zweiten mal tut. Er muß nur
zur Kontrolle wechseln.

MfG  Manfred Glahe

von Rahul (Gast)


Lesenswert?

wie wäre es mit einem NE555 als Taktgenerator? Wenn der schön langsam
klickert, kann man die Ausgänge sogar mit einem Multimeter beobachten.

von Matthias (Gast)


Lesenswert?

Hi

Nebenbemerkung:
Deine Ausgaberoutine ist etwas unelegant. Das könnte man auch so
machen:

void debug_lcd_send_dat(unsigned char dat)
{
  unsigned char i;

  for(i=8;i>0;i--)
  {
    if(dat&0x80) LCD_DAT_ON;
    else  LCD_DAT_OFF;

    LCD_CLK_ON;
    LCD_CLK_OFF;

    dat<<=1;
  }

  LCD_RS_DAT;
  LCD_E_ON;
  LCD_E_OFF;
}

Matthias

von Hugoderwolf (Gast)


Lesenswert?

"Beide MR auf GND ist richtig. Ich hatte noch nach der
Betriebsspannung
gefragt. Ist die richtig zur Platine verdrahtet? Ansonsten können
Deine
Angaben nicht stimmen!"

Wie gesagt, Betriebsspannung ist 5V, erzeugt mit 'nem Steckernetzteil
12V am 7805. Was meinst du mit "richtig zur Platine verdrahtet"?
Könnte ein Abblockkondensator helfen? Bin mir immer nicht sicher ob und
warum der nötig ist. Vielleicht kann mir das jemand noch erklären?
Das mit dem Taster muss ich mal ausprobieren, aber vielleicht hilft
schon ein Tipp, was man beim Anschluss noch falsch machen kann.

von Stephan Schwarz (Gast)


Lesenswert?

Hallo Hugo v der Wolf

ich möchte auch ein Schieberegister einsetzten um Ports zu sparen.
Dein Vorgehensweise hatte ich dabei auch im Kopf.
Bin mir nur noch nicht sicher ob es nicht auch Bausteine gibt, bei
denen das noch leichter geht als bei einem Schieberegister.
Da gibt es doch auch noch so LCD Treiber Ic`s mit I²C Bus Ansteuerung,
aber das werde ich noch rausfinden, nächste Woche.

Ich hab aber ein Problem deinen Quelltext zu verstehen, wäre nett, wenn
du kurz dazu eine Paar Kommentare schreiben würdest. Damit würdest du
mir sehr helfen.

Dann werde ich wohl demnächst die Scaltung auch so aufbauen, wie du Sie
schon hast. Dann kann man sich auch gut austauschen.

Das wird aber wohl noch 2 Wochen dauern. Muss erst noch die Teile
bestellen.

von Manfred Glahe (Gast)


Lesenswert?

@Hugoderwolf

"Was meinst du mit "richtig zur Platine verdrahtet"?"

Werden µP und Schieberegister aus einem Netzteil versorgt? Wenn nicht,
ist die GND Verbindung zwischen µP und Reg. hergestellt?
Diese Registeransteuerung ist derart einfach, daß da eigentlich nichts
schiefgehen kann. Es stellt sich dann meistens heraus, daß GND Probleme
dafür verantwortlich waren.
Sind die Logiklevel zur Ansteuerung ausreichend? Wird tatsächlich immer
nur ein Takt erzeugt?

MfG  Manfred Glahe

von Hugoderwolf (Gast)


Lesenswert?

"Werden µP und Schieberegister aus einem Netzteil versorgt? Wenn
nicht,
ist die GND Verbindung zwischen µP und Reg. hergestellt?"

Sowohl als auch. Versorgung erfolgt wie gesagt über ein Netzteil und
Spannungsregler. GND ist quasi in einer Kette von Spannungsregler zu
Register zu Controller usw. verbunden, also sollte überall brav der
gleiche GND-Level vorhanden sein.
Die Logiklevel sollten mit ebenfalls 5V ja auch ausreichend sein. Was
für ein Takt erzeugt wird siehst du ja am Quellcode.

von Manfred Glahe (Gast)


Lesenswert?

@Hugoderwolf

"Nach einigen Messungen scheint am Schieberegister an allen Ausgängen
                  ständig der Pegel am Eingang anzuliegen! Kaputt ist
es nicht, habe"

Wenn Du mißt, bekommst Du ein eindeutiges Ergebnis. Was meinst Du mit
"scheint"?

"also sollte überall brav der
                  gleiche GND-Level vorhanden sein."

Bei einem solchen Problem mußt Du absolut sicher sein welche
Meßergebnisse Du vorliegen hast. So wie Du es schilderst, kann es
definitiv nicht sein, denn dann würde das Register vorschriftsmäßig
arbeiten. Wenn Du also nochmal nachfragst, dann bitte mit eaxten
Messungen, ohne die ist alles vertane Zeit.

MfG  Manfred Glahe

von Hugoderwolf (Gast)


Lesenswert?

Wenn ich alle GND-Stellen mit 'nem Durchgangsprüfer messe sind alle
verbunden. Mit 'nem Voltmeter ist zwischen allen auch 0V Spannung.
Als ich gemessen habe war grundsätzlich an allen Ausgängen der Level
dran, der am Eingang lag. Also in dieser Anwendung das letzte Bit das
geschickt wurde. Habe testweise 0xAA geschickt, wo das letzte Bit 0
ist, da war auch alles 0, bei 0xAB war alles 1.
Auf Kurzschlüsse habe ich auch alles überprüft, auch nix zu finden.

So, nun habe ich mal mein altes GameBoy-Oszilloskop ausgegraben und
unter Mühen ein paar weiter Messungen angestellt. Zunächst war kaum
eine Bewegung messbar, weshalb ich in den Code ein paar Warteschleifen
eingebaut habe. Der sieht jetzt so aus:

void lcd_databus(char databyte) {
    char i;
    unsigned int i2;

    if((databyte >> 7) & 1)
        sbi(LCD_PORT, LCD_D7);
    else
        cbi(LCD_PORT, LCD_D7);

    for(i=6;i>=0;i--) {
        if((databyte >> i) & 1)
            sbi(LCD_PORT, SR_DI);
        else
            cbi(LCD_PORT, SR_DI);

        for(i2=0;i2<=30000;i2++)
            asm volatile ("nop");

        sbi(LCD_PORT, SR_CP);

        for(i2=0;i2<=30000;i2++)
            asm volatile ("nop");

        cbi(LCD_PORT, SR_CP);

        for(i2=0;i2<=30000;i2++)
            asm volatile ("nop");
    }
}

Die Funktion wird mit 0xAB aufgerufen. Am Oszilloskop kann ich deutlich
sehen, wie am DI-Ausgang 0101011 gesendet wird, was 0xAB ohne das
höchstwertige Bit entspricht, welches ja anderweitig ausgegeben wird.
Am CP-Ausgang sehe ich 7 deutliche Pulse. Die Ansteuerung ist also auf
jeden Fall richtig. Wie oben erwähnt habe ich Anschlusstechnisch auch
nach wie vor keine Fehler finden können. Bin mit meinem Latein jetzt
wirklich absolut am Ende. :(

von Manfred Glahe (Gast)


Lesenswert?

@Hugoderwolf

ich kann nur was mit Assembler anfangen. Aber eines möchte ich noch mal
nachfragen da Du mit dem Scope messen kannst: Du mußt erst auf dem
einen PortBit das Datenbit setzen und halten. Dann mußt Du auf einem
anderen PortBit das Taktbit auf 1 setzen (vorher muß es auf 0 gewesen
sein), wobei das Datenbit sich selbstverständlich nicht ändern darf!
Nun das Taktbit wieder auf 0 setzen. Das 1. Datenbit ist im Register.
Alle anderen ebenso rausschieben. Wenn Du das so machst MUß es laufen!
Ansonsten kann ich Dir von hier auch nicht mehr weiterhelfen.

MfG  Manfred Glahe

von Hugoderwolf (Gast)


Lesenswert?

OK, hier der Code nochmal kommentiert:

DI = Datenbit
CP = Taktbit

    for(i=6;i>=0;i--) {             // Schleife für einzelne Bits
        if((databyte >> i) & 1)     // Wenn Bit = 1
            sbi(LCD_PORT, SR_DI);   // DI auf High setzen
        else                        // andernfalls
            cbi(LCD_PORT, SR_DI);   // DI auf Low setzen

        for(i2=0;i2<=30000;i2++)    // Warten für 30000 Zyklen
            asm volatile ("nop");

        sbi(LCD_PORT, SR_CP);       // CP auf High setzen

        for(i2=0;i2<=30000;i2++)    // Warten für 30000 Zyklen
            asm volatile ("nop");

        cbi(LCD_PORT, SR_CP);       // CP auf Low setzen

        for(i2=0;i2<=30000;i2++)    // Warten für 30000 Zyklen
            asm volatile ("nop");
    }                               // Wieder von vorne

Ist also so gemacht, wie von dir beschrieben. Normalerweise sollten die
Warteschleifen auch nicht nötig sein, da das Register laut Datenblatt
eine Taktfrequenz von mindestens 70 oder mehr MHz verträgt. Aber da
mein GameBoy-Oszilloskop
(http://mitglied.lycos.de/hobbyelec/spannung-messen/gbdso_de.pdf)
ziemlicher Schrott ist, konnte ich anders die Pulse überhaupt nicht
richtig sehen.

Hab vorhin auch noch 'nen Abblockkondensator zwischen Vcc und GND beim
Register gelötet und immerhin sieht die Versorgung jetzt besser aus.
Vorher waren immer so 4,9 V angezeigt, wie mir auffiel. Jetzt isses
stabil bei 5,0V, funktionieren tut's aber immer noch nicht... :(

von Manfred Glahe (Gast)


Lesenswert?

Hallo,

ohne schnellen Abblockkondensator 0.1µ und einem 1µ Tantal (wenn die
Leitungswege länger als 10 cm sind) fange ich gar nicht erst an zu
testen, da kann eigentlich alles passieren.
Aber da Du das nun behoben hast kann es da ja nicht mehr drann liegen.
Von hieraus kann ich Dir nun auch nicht mehr weiterhelfen.
Ich bezweifele allerdings immer noch die Meßergebnisse, noch mehr
nachdem ich weiß womit Du gemessen hast. Das kann eigentlich alles gar
nicht sein.
Benachrichtige mich bitte wenn Du etwas gefunden hast, daß interessiert
mich nun wirklich mal. Wenn Du eine Tür weitersitzen würdest könnte
ich's mir selbst mal anschauen.

MfG  Manfred Glahe

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.