Forum: Mikrocontroller und Digitale Elektronik Frage zur Multiplex Ansteuerung


von Michael T (Gast)


Lesenswert?

Hallo,
habe ein Problem mit einer Multiplex Ansteuerung.
Möchte folgendes machen:
Eine Siebensegment Anzeige, die durch einen Latch (74HC573), die Zahlen 
0 bis 9 hochzählen soll.
Die Zahlen sind ind einer Tabelle in Hex-Form gespeichert.
Jetzt will ich diese Auslesen und zur Anzeigen bringen.
Vor dem Schreiben soll das Latch auf High gesetzt werden danach wieder 
auf Low.
Bekomme aber nur die Null zur Anzeige.
Was mache ich nur falsch?
Habe mir schon die Zähne an der Tastatur ausgebissen.

Anbei noch das Programm:

.device AT90s8515
.include "C:\Programme\Atmel\AVR Studio\Appnotes\8515def.inc"

;Definition der Steuerleitungen
.equ     sek_ein   = PA7        ; Sekunden Einer
.equ     sek_zen   = PA6        ; Sekunden Zehner
.equ     min_ein   = PA5        ; Minuten Einer
.equ     min_zen   = PA4        ; Minuten Zehner
.equ     stu_ein   = PA3        ; Stunden Einer
.equ     stu_zen   = PA2        ; Stunden Zehner

; Variablendefinition
.def     zeichen   = r0         ; Zeichen aus Tabelle
.def     counter   = r17        ; Zaehler für die Anzeige
.def     temp      = r18
.def     buffer    = r19
.def     delay     = r20
.def     delay1    = r21

.CSEG
.ORG 0x00                        ; Programm beginnt bei 0


             rjmp   main         ; Starte Hauptprogramm

 init:       cli
             ldi temp,0b1111111
             out DDRA,temp
             ret
 write_data:
             ldi temp,0b11111111
             out DDRB,temp
             cbi porta,sek_ein
             out PORTB,buffer
             sbi porta,sek_ein
             ret

 main:       ldi temp,RAMEND
             out SPL,temp
             rcall init
             ldi ZL,LOW(tabelle*2)
             ldi ZH,HIGH(tabelle*2)
             ldi counter,10


 loop_msg1:  lpm
             mov buffer,zeichen
             rcall write_data
             inc ZL
             brcc no_carry1
             inc ZH

 no_carry1:  dec counter
             brne loop_msg1


 loop:       rjmp loop

  ; Ziffern    0    1    2    3    4    5    6    7    8    9
Tabelle: .db 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90

Danke im voraus
    Michael T

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Du darfst nix "rcall"en bevor der Stackpointer gesetzt ist!
Und außerdem: inc ändert nix am Carry. Nimm einfach adiw zum erhöhen des 
Z-Pointers.

von Uwe (Gast)


Lesenswert?

Hi!
cbi setzt Ausgang auf 0 = Low
Ausgabe
sbi setzt Ausgang auf 1 = High

Wolltest du es nicht andersrum??
Eine Verzögerung der Ausgabe vermisse ich ebenfalls, du wirst 
bestenfalls eine 9 sehen. Beachte auch die Flag's im Datasheet. Bei inc 
steht da Z,N,V. ADIW ist also völlig richtig.
viel Erfolg
Uwe

von Michael T (Gast)


Lesenswert?

Danke,
aber eine 9 ist da nicht das ganze bleibt bei 0 stehen.
Gibt es da vieleicht noch eine andere Lösung?
Viele Grüße
  Michael T

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Hast du die vorgeschlagenen Änderungen schon umgesetzt?

von Schmittchen (Gast)


Lesenswert?

Oder ums noch deutlicher zu machen:
> Du darfst nix "rcall"en bevor der Stackpointer gesetzt ist!
heißt auch, daß der Stackpointer nicht richtig initialisiert wird. Der 
besteht beim 8515 nämlich aus SPH und SPL. Aber das ist wohl nicht der 
Grund für das Versagen des Programms. Das wird eher mit dem mehrfach 
erwähnten inc/adiw zusammenhängen.

Schmittchen.

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Öhm, was ich über den SP geschrieben habe vergeßt mal bitte wieder. Ich 
habe mir eingeildet das "rcall init" käme vor der Initialisierung des 
Stackpointers.

Aber dass der Stack nicht richtig initialisiert ist stimmt natürlich, 
siehe Tutorial #3.

von Michael T (Gast)


Lesenswert?

Habe ich alles probiert.
Mit dem "rcall"en, habe mich schon gewundert.
Das Programm geht in der Simulation wunderbar.
Doch bleibt es im Avr irgendwo hängen.
Habe ich vieleicht was übersehen.
Viele Grüße
     Michael T

von Michael T (Gast)


Lesenswert?

Jetzt geht es!

.include "C:\Programme\Atmel\AVR Studio\Appnotes\8515def.inc"

.def zeichen = r0
.def buffer = r16
.def counter = r17
.def delay =r18
.def delay1 =r19
.def temp = r20
.equ sek_ein = pa7
.CSEG

.ORG 0x0000
 rjmp main

 init:   ldi   temp,0b11111111    ;
         out   ddra,temp          ;PORTA ist Ausgang
         out   ddrb,temp          ;PORTB ist Ausgang
         ret

 output: sbi   porta,sek_ein      ;spreche Anzeige an
         out   portb,buffer       ;sende Daten
         cbi   porta,sek_ein      ;disable Anzeige
         rcall dly                ;springe zur Pause
         ret
 dly:    dec   delay
         brne  dly
         dec   delay1
         brne  dly
         ret
 main:   ldi   temp,LOW(ramend)    ; Oberes Byte
         out   SPL,temp            ; an Stapelzeiger
         ldi   temp,HIGH(ramend)   ; Unteres Byte
         out   SPH,temp            ; an Stapelzeiger
         rcall init

 Loop0:  ldi   counter,10          ;Zaehler für Zeichen
         ldi   ZL,LOW(Tabelle*2)   ;Low-Zeiger auf Tabellenanfang
         ldi   ZH,HIGH(Tabelle*2)  ;High-Zeiger auf Tabellenanfang

 loop1:  lpm                       ;hole Zeichen aus Tabelle
         mov   buffer,zeichen      ;Zeichen uebergeben
         rcall output              ;schreibe Zeichen in Anzeige
         adiw  ZL,1                ;16-Bit Pointer um 1 erhoehn

nocarry: dec   counter             ;alle Zeichen gesendet?
         brne  loop1               ;Nein! Sende naechstes Zeichen

 loop:   rjmp  main                ;Programm wird neu gestartet



  ; Ziffern    0    1    2    3    4    5    6    7    8    9
 Tabelle: .db 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90


Habe jetzt adiw genommen, aber mit "inc ZL" und "inc ZH" geht es auch.
Nur was ist jetzt der unterschied vom Stackpointer bei:
         ldi   temp, LOW(ramend)   ; Oberes Byte
         out   SPL,temp            ; an Stapelzeiger
         ldi   temp,HIGH(ramend)   ; Unteres Byte
         out   SPH,temp            ; an Stapelzeiger

zu:     ldi    temp,RAMEND
        out    SPL,temp
Weiss einer dazu die Antwort?
 Gruß
      Michael T

von Schmittchen (Gast)


Lesenswert?

Wie meinen? Na einmal belegst du nur SPL mit einem Wert, das andere Mal 
SPL und SPH!
SPH steht nach dem Einschalten auf 0x00, und das ist schon was anderes 
als 0x02, damit steht im ersten (richtigen) Fall der Stackpointer auf 
0x025F, in deinem zweiten (nicht funktionierenden) Fall auf 0x005F. 
Irgendwann läuft dir da dann was rein.

RAMEND = 0x025F
HIGH(RAMEND) = 0x02
LOW(RAMEND) = 0x5F

Schmittchen.

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.