Forum: Compiler & IDEs Problem beim Multiplexen von Siebensegmentanzeigen


von Matthias R. (recki)


Angehängte Dateien:

Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Matthias R. (recki)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Matthias R. (recki)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

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.