www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Ansteuerung einer 7 Segmente-Anzeige


Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich versuche seit kurzem in Assembler eine 7-Segmente Anzeige 
anzusteuern. Das Programm soll auch bei einem Tastendruck die angezeigte 
Zahl um 1 erhöhen(Probeweise nur bis 2, bei der Zahl 3 wird der zähler 
wider auf 0 gesetzt). Jedoch wenn ich das Programm auf meinen ATmega32 
lade und den Taster drücke leuchten kurz alle LEDs auf und erlöschen 
sofort wieder.

Hier der Code:
;Ansteuern der Segmente und des Tasters
;PB1-PB7 sind für die Segmente (Ausgang) und PB0 ist für den Taster ;(Eingang) bestimmt.

.INCLUDE   "m32def.inc"     ;Deklaration für ATmega32
.EQU       takt = 16000000   ;Takt 16 MHz
.DEF    akku = r16    ;Arbeitsspeicher
.DEF    zaehler = r18    ;Zähler für Tastendruck
.CSEG          ;Programm-Flash  


start:          ldi r16,0xFE          
    out DDRB,r16   ;PB0 auf Eingang und PB1-PB7 auf Ausgang
    
    ldi r17,0x01
    out PORTB,r17    ;Pull-Up bei PB0 aktivieren
    
    ldi r16,0x7E   ;Am Anfang 0 anzeigen
    out PORTB,r16
      
    ldi r18, 0x00  ;Zähler am Anfang auf 0
    ldi r16, 0x01   ;Zählkonstante 1

loop:           sbic PINB, 0    ;Überspringt Befehl "rjmp", falls PB0==0
    rjmp loop            
    
    add r18,r16  ;zähler +1      
    
    cpi r18,1  ;Vergleichen
    breq zahl_1  
    brne kontrolle_2      

kontrolle_2:  cpi r18,2  
    breq zahl_2
    brne kontrolle_3        

kontrolle_3:  cpi r18,3
    breq loeschen

    rjmp loop            
    
zahl_1: ldi r19,0x0C         ;zahl 1 ausgeben
    out PORTB,r19
    rjmp loop

zahl_2: ldi r20,0xDA         ;zahl 2 ausgeben
    out PORTB,r19    
    rjmp loop

loeschen: clr zaehler        ;Zähler löschen 
      ldi r21,0xFE          
      out PORTB,r19     ; wieder Zahl 0 ausgeben
      rjmp loop




Kann mir jemand helfen?

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

Bewertung
0 lesenswert
nicht lesenswert
Dir ist hoffentlich klar, dass dein Hochzählen nicht erfolgt 'Wenn eine 
Taste gedrückt wird', sondern 'Solange eine Taste gedrückt ist'. Als 
Mensch wirst du es kaum schaffen, eine Taste kürzer als ein paar 
Millieskunden gedrückt zu halten. In dieser Zeit zählt dein Prozessor 
rasend schnell immer wieder und immer wieder durch.

Sieh dir mal an, welche 7-Segment Muster du in welches Register lädts, 
und welches Register du tatsächlich dann am Port ausgibst.

Sowas
    cpi r18,1  ;Vergleichen
    breq zahl_1                          ; <------------
    brne kontrolle_2                     ; <------------

kontrolle_2:  cpi r18,2  
ist ziemlich kontraproduktiv. Entweder 2 Zahlen sind gleich, oder sie 
sind es nicht. Wenn sie aber gleich sind, können sie nicht ungleich 
sein. D.h. der brne ist da ziemlich sinnfrei. Wenn der Prozessor zum 
brne kommt, dann steht bereits fest, dass r18 nicht gleich 1 sein kann. 
Sonst wäre der Programmlauf nicht an diese Stelle gekommen!

d.h deine 'Hauptschleife' kannst du kürzer auch so schreiben
loop: sbic PINB, 0    ; Überspringt Befehl "rjmp", falls PB0==0
    rjmp loop            
    
    add r18,r16     ; zähler +1      
    
    cpi r18,1       ; ist der Zähler 1?
    breq zahl_1     ; ja: 1 anzeigen

    cpi r18,2       ; Ist der Zähler 2?
    breq zahl_2     ; ja: 2 anzeigen

    clr zaehler     ; Weder 1, noch 2: Zähler löschen 
    ldi r19,0xFE          
    out PORTB,r19

    rjmp loop       ; und weiter gehts      

Grundsätzlich ist es nicht schlecht, ausführlich zu programmieren. Aber 
gerade in Assembler kann mans auch übertreiben. Und dann wirds nicht 
übersichtlicher sondern man legt sich selber Fallen, weil man vor lauter 
Anweisungen nicht mehr sieht, welche davon sinnlos sind, und welche 
nicht.


Dir ist hoffentlich auch klar, dass du hier

    ldi r19,0xFE
    out PORTB,r19

dadurch, dass PB0 gleich 0 ist, denn Pullup für den Taster abschaltest 
(Ditto bei den anderen Ausgaben)

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

einige Bemerkungen zur Systematik deines Programmes.

-) Verlagere das Auswerten der Taste in eine eigene Unterroutine. In 
dieser werde die taste etwa 10 ms abgefragt. Wenn 75 % der 
Abfrageresultate ergeben, daß der Tater 'zu' ist, wird ein TRUE 
zurückgegeben, sonst ein false.

-) Erst wenn ein TRUE zurückkommt, wird der Zähler incrementiert.

-) Für die Anzeigendecoduierung verwende eine Tabelle, auf die mit einem 
konstantem Pointer gezeigt wird (in c etwa const * unsigned char ). Das 
Auslesen des Wertes ergibt die Bits in der Anzeige. Auch das gehört in 
eine eigene Routine.

-) Überlege, was in einen Kommentar hineingehört und was nicht. Deine 
Kommentare 'Arbeitsspeicher', die 16 MHZ usw. können entfallen. Das 
Initialisierungsjedöns gehört in ein eigenes UP.

-)dein Programm kann dann im Hauptteil aussehen wie folgt (das ist jetzt 
VHIT, vom Hirn ins terminal, also ohne Test)

start:
       call init;;                    initialisierung
loop:  taste_auswerten;               result on TOS
       mov R01, TOS   ;
       jnz loop;                      warten bis Taste gedrückt

;; entry hier nur wenn tastendruck

       inc tastcount;
       ld R01 Tastcount + vector;      vector ist der og. 
Tabellenpointer
       mov 7SEGPORT, R01;
       jmp loop;


So. Ich hoffe, das hiolft erstmal weiter,

Gruss#

Robert

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde das Haus nicht mit dem Dach anfangen zu bauen, sondern mit dem 
Fundament.

Wenn also etwas auf Tastendruck passieren soll, programmiert man erstmal 
ne funktionierende Tastenroutine.
Z.B. ne LED mit Taste ein- und ausschalten.
Wenn das funktioniert, d.h. die LED wechselt zuverlässig und prellfrei 
bei jedem Tastendruck, gehts einen Schritt weiter.
Z.B. 2 Tasten und 2 LEDs unabhängig und gleichzeitig.
Dann weiß man, daß die Tastenroutine nicht blockierend ist, d.h. einen 
zu entwickelnden Programmablauf nicht behindert.
Usw.

Immer alle Probleme in kleine Häppchen aufteilen und diese lösen (teile 
und herrsche).


Peter

Autor: R. Freitag (rfr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
man Salami.

Gruss

Robert

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.