www.mikrocontroller.net

Forum: GCC Problem beim Multiplexen von Siebensegmentanzeigen


Autor: Matthias R. (recki)
Datum:
Angehängte Dateien:

Hallo zusammmen,


Ich habe eine Problem beim Multiplexen von Siebensegmentanzeigen.

Anbei oben die Schaltung der DIP in der Schaltung wäre der Anschluss für
meinen Atmega 128.

Problem:

Auf den Anzeigen schimmern immer schwach die Zahlen der anderen Segmente
durch. Wenn ich über all die selbe Zahl hinschicke sieht alles gut aus
nur sobald ich verschiedene Zahlen Anzeige sehen ich immer die segment
schwach von der anderen mit. Vll hat jemand ne idee.

Danke schonmal

Gruß

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

Matthias R. schrieb:

> Auf den Anzeigen schimmern immer schwach die Zahlen der anderen Segmente
> durch. Wenn ich über all die selbe Zahl hinschicke sieht alles gut aus
> nur sobald ich verschiedene Zahlen Anzeige sehen ich immer die segment
> schwach von der anderen mit. Vll hat jemand ne idee.

Programmfehler in der Multiplexroutine.
Du musst die Stellentreiber (rechts im Schaltplan) komplett abschalten,
ehe du die neue Segmentbelegung mit dem linken Schaltplanteil ausgibst.
Autor: Matthias R. (recki)
Datum:

Hier ist die Routine dafür schalte ich sie damit nicht gleich aus?
void Anzeige(void)
{  
  //Variablen zum Multiplexen der 7 Segmentanzeigen  
  int i;
  int segmentp=0;                      // Variablen um das anzusteuerde Segment umzuschalten 
  int segmentu=0; 
  int stellep[]={1000,100,10,1};              //Arrays für die Spaltentreiber 
  int stelleu[]={1000,100,10,1};
  for(i=0; i<=3; i++)
  {
    PORTB=((punkte/stellep[segmentp])%10)|(16<<segmentp);  //Anzuzeigende Zahl und Segmentnummer filtern und in Port schieben
    PORTC=((uhr/stelleu[segmentu])%10)|(16<<segmentu);
    _delay_ms(4);
    segmentp=(segmentp+1)&3;                //erhöhen der für das nächste Segment
    segmentu=(segmentu+1)&3;
                          //Warteschleife
  }
 }
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Matthias R. schrieb:
> Hier ist die Routine dafür schalte ich sie damit nicht gleich aus?

Probiers mal so

...
>   for(i=0; i<=3; i++)
>   {
      PORTB = 0;   // alles aus
      PORTC = 0;   // alles aus

>     PORTB=((punkte/stellep[segmentp])%10)|(16<<segmentp);
> //Anzuzeigende Zahl und Segmentnummer filtern und in Port schieben
>     PORTC=((uhr/stelleu[segmentu])%10)|(16<<segmentu);
>     _delay_ms(4);
>     segmentp=(segmentp+1)&3;                //erhöhen der für das
> nächste Segment
>     segmentu=(segmentu+1)&3;
>                           //Warteschleife
>   }
>  }
> [/C]

wenn das nicht reicht, dann könntest du noch versuchen eine kleine Pause
zwischen ausschalten und neu einschalten einzulegen. Die Fets brauchen
auch ein wenig Zeit um abzuschalten!

PS: dieser Multiplex ist Mist. Du brauchst eine Timer-ISR, die
regelmässig aufgerufen wird. Und in der schaltest du bei jedem
ISR-Aufruf um 1 Stelle weiter. Gewöhn dir besser gleich jetzt auf der
Stelle ab, _delay_ms zu verwenden. Am besten vergisst du gleich wieder,
dass es diese Funktion gibt. Sie führt bei Leuten, die damit nicht
umgehen können fast immer zu schlechtem Programmdesign. (Soll heißen:
Man kann sie verwenden, muss aber wissen was man tut)
Ganz zu schweigen von der unnötigen Rechnerei während des Multiplexens.
Autor: Matthias R. (recki)
Datum:

Hmm ja das war jetzt auch mein gedanke wo das mit dem ausschalten kam.
Ja mit nem Interrupt wäre bestimmt besser aber ich bin noch ziemlicher
Anfänger daher wollte ich es erstmal auf eine relativ einfache art
lösen.
Falls es nicht klappt muss ich es wohl anders versuchen

Danke schonmal
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Matthias R. schrieb:
> Hmm ja das war jetzt auch mein gedanke wo das mit dem ausschalten kam.
> Ja mit nem Interrupt wäre bestimmt besser aber ich bin noch ziemlicher
> Anfänger daher wollte ich es erstmal auf eine relativ einfache art
> lösen.

FAQ
ganz unten, letztes Kapitel - Timer.
Ist einfacher als du denkst. Und irgendwann musst auch du ins kalte
Wasser springen. Also, warum nicht hier. Zumal das nur Vorteile hat.
Autor: Karl Heinz Buchegger (kbuchegg) (Moderator)
Datum:

Ach, da seh ich noch was.

Du verwendest exzessiv int.
Tu das nicht! int ist auf deinem AVR 16 Bit gross, d.h. du jagst deinen
AVR in unnötige 16 Bit Arithmetik rein. Kostet nur Rechenzeit, bringt
dir aber nix.

Für zb
   for( i = 0; i < 3; i++ )

sind 8 Bit (0 bis 255) völlig ausreichend. Mehr braucht es nicht.

ALso: überlegen welchen Wertebereich Variablen haben können/sollen und
dann dementsprechend den Datentyp festlegen

  uint8_t       8 Bit ohne Vorzeichen  ( 0 .. 255 )
  int8_t        8 Bit mit Vorzeichen   ( -128 ... 127 )
  uint16_t     16 Bit ohne Vorzeichen  ( 0 .. 65535 )
  int16_t      16 Bit mit Vorzeichen   ( -32768 ... 32767 )

Und plain vanilla int streichst du gleich mal aus deinem Wortschatz.

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




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net