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


von Thomas (Gast)


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:
1
;Ansteuern der Segmente und des Tasters
2
;PB1-PB7 sind für die Segmente (Ausgang) und PB0 ist für den Taster ;(Eingang) bestimmt.
3
4
.INCLUDE   "m32def.inc"     ;Deklaration für ATmega32
5
.EQU       takt = 16000000   ;Takt 16 MHz
6
.DEF    akku = r16    ;Arbeitsspeicher
7
.DEF    zaehler = r18    ;Zähler für Tastendruck
8
.CSEG          ;Programm-Flash  
9
10
11
start:          ldi r16,0xFE          
12
    out DDRB,r16   ;PB0 auf Eingang und PB1-PB7 auf Ausgang
13
    
14
    ldi r17,0x01
15
    out PORTB,r17    ;Pull-Up bei PB0 aktivieren
16
    
17
    ldi r16,0x7E   ;Am Anfang 0 anzeigen
18
    out PORTB,r16
19
      
20
    ldi r18, 0x00  ;Zähler am Anfang auf 0
21
    ldi r16, 0x01   ;Zählkonstante 1
22
23
loop:           sbic PINB, 0    ;Überspringt Befehl "rjmp", falls PB0==0
24
    rjmp loop            
25
    
26
    add r18,r16  ;zähler +1      
27
    
28
    cpi r18,1  ;Vergleichen
29
    breq zahl_1  
30
    brne kontrolle_2      
31
32
kontrolle_2:  cpi r18,2  
33
    breq zahl_2
34
    brne kontrolle_3        
35
36
kontrolle_3:  cpi r18,3
37
    breq loeschen
38
39
    rjmp loop            
40
    
41
zahl_1: ldi r19,0x0C         ;zahl 1 ausgeben
42
    out PORTB,r19
43
    rjmp loop
44
45
zahl_2: ldi r20,0xDA         ;zahl 2 ausgeben
46
    out PORTB,r19    
47
    rjmp loop
48
49
loeschen: clr zaehler        ;Zähler löschen 
50
      ldi r21,0xFE          
51
      out PORTB,r19     ; wieder Zahl 0 ausgeben
52
      rjmp loop



Kann mir jemand helfen?

von Karl H. (kbuchegg)


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
1
    cpi r18,1  ;Vergleichen
2
    breq zahl_1                          ; <------------
3
    brne kontrolle_2                     ; <------------
4
5
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
1
loop: sbic PINB, 0    ; Überspringt Befehl "rjmp", falls PB0==0
2
    rjmp loop            
3
    
4
    add r18,r16     ; zähler +1      
5
    
6
    cpi r18,1       ; ist der Zähler 1?
7
    breq zahl_1     ; ja: 1 anzeigen
8
9
    cpi r18,2       ; Ist der Zähler 2?
10
    breq zahl_2     ; ja: 2 anzeigen
11
12
    clr zaehler     ; Weder 1, noch 2: Zähler löschen 
13
    ldi r19,0xFE          
14
    out PORTB,r19
15
16
    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)

von R. F. (rfr)


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

von Peter D. (peda)


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

von R. F. (rfr)


Lesenswert?

man Salami.

Gruss

Robert

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.