Hi Ernst,
dann will ich mal ein wenig was tippen ...
Hier habe ich mal ein Bild von meinen „Machwerk“
geschossen, aber bitte nicht auslachen. Es ist nur ein Provisorium. Wenn die
Anzeige wie gewünscht klappt dann stelle ich eine komplette Platine dafür her
wo ich dann nur noch den fertig programmierten Prozessor einstecke.
http://img96.imageshack.us/img96/2464/p1060519.jpg
Das würde ich nicht unbedingt als Provisorium ansehen, sieht doch gut aus
Bei mir ist das immer Lochrastergebastel weil ich keine Lust mehr zum panschen
mit Ätzlösung habe und auch keine Lust mir ein Einzelexemplar von ner Platine
zu bestellen.
Hier ist das Programm dazu. Weiter bin ich auch aus Zeitgründen noch nicht
gekommen.
Dann wolln wir doch mal sehen ...
ich zerleg es mal in Abschnitte ...
CodeBox asm
;----------------------------------------------------------------------
; Title : myAVR Beispiel "Multiplex" für den ATmega8
;----------------------------------------------------------------------
; Funktion : 4 Stellige Anzeige
; Schaltung
;----------------------------------------------------------------------
; Prozessor : ATmega8
; Takt : 3,6864 MHz
; Sprache : Assembler
; Datum : 12.09.09
; Version : 1.0
; Autor : Ernst
; Programmer :
; Port :
;----------------------------------------------------------------------
.equ F_CPU, 3686400
.include "avr.h"
;-----------------------------------------------------------------------
;Reset and Interruptvectoren ;VNr. Beschreibung
begin:
rjmp main ; 1 POWER ON RESET
reti ; 2 Int0-Interrupt
reti ; 3 Int1-Interrupt
reti ; 4 TC2 Compare Match
reti ; 5 TC2 Overflow
reti ; 6 TC1 Capture
reti ; 7 TC1 Compare Match A
reti ; 8 TC1 Compare Match B
reti ; 9 TC1 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
reti ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comperator
reti ;18 TWI (IC) Serial Interface
reti ;19 Strore Program Memory Ready
;------------------------------------------------------------------------
Schön mit Kopf und Version(Datum) und Bemerkungen
Sieht recht nett aus ... Den Programmierstil kanst du beibehalten
Als Tip ... Schreib bei den Interrupt-Vektoren vor jedes
reti ein
.org
ungefähr so ...
CodeBox asm
;########## BEISPIEL VON MIR ############
; ----- INTERRUPT-VECTOREN -----
;
.cseg ; Beginn eines Code-Segmentes
.org 0x000 rjmp RESET ; Reset Handler
;.org 0x002 rjmp EXT_INT0 ; IRQ0 Handler
;.org 0x004 rjmp EXT_INT1 ; IRQ1 Handler
.org 0x006 rjmp PC_INT0 ; PCINT0 Handler (PCINT7..0)
.org 0x008 rjmp PC_INT1 ; PCINT1 Handler (PCINT14..8)
.org 0x00A rjmp PC_INT2 ; PCINT2 Handler (PCINT23..16)
;.org 0x00C rjmp WDT ; Watchdog Timer Handler
;.org 0x00E rjmp TIM2_COMPA ; Timer2 Compare A Handler
;.org 0x010 rjmp TIM2_COMPB ; Timer2 Compare B Handler
;.org 0x012 rjmp TIM2_OVF ; Timer2 Overflow Handler
.org 0x014 rjmp TIM1_CAPT ; Timer1 Capture Handler
;.org 0x016 rjmp TIM1_COMPA ; Timer1 Compare A Handler
;.org 0x018 rjmp TIM1_COMPB ; Timer1 Compare B Handler
.org 0x01A rjmp TIM1_OVF ; Timer1 Overflow Handler
;.org 0x01C rjmp TIM0_COMPA ; Timer0 Compare A Handler
;.org 0x01E rjmp TIM0_COMPB ; Timer0 Compare B Handler
;.org 0x020 rjmp TIM0_OVF ; Timer0 Overflow Handler
;.org 0x022 rjmp SPI_STC ; SPI Transfer Complete Handler
;.org 0x024 rjmp USART_RXC ; USART, RX Complete Handler
;.org 0x026 rjmp USART_UDRE ; USART, UDR Empty Handler
;.org 0x028 rjmp USART_TXC ; USART, TX Complete Handler
;.org 0x02A rjmp ADC ; ADC Conversion Complete Handler
;.org 0x02C rjmp EE_RDY ; EEPROM Ready Handler
;.org 0x02E rjmp ANEOMP ; Analog Comparator Handler
;.org 0x030 rjmp TWI ; 2-wire Serial Interface Handler
;.org 0x032 rjmp SPM_RDY ; Store Program Memory Ready Handler
.org 0x034 ; Start Hauptprogramm (erste brauchbare Adresse)
;
; ----- MAIN-PROGRAM -----
;
RESET:
ldi r16,low(ramend)
ldi r17,high(ramend)
out spl,r16 ; Stackpointer auf
out sph,r17 ; RAM-Ende setzen
;########## BEISPIEL VON MIR ############
Das hat einen wichtigen Grund ... manche AVRs haben bei den Vektoren
Platz für einen Befehl und manche für 2 Befehle. Wenn du also nur die
reti-Befehle hintereinanderschreibst, dann hast du zB bei AVRs mit mehr
Platz bei den Vektoren 2x reti bei einem Vektor drin aber nur die hälfte der
Vektoren definiert. Das könnte später mal Probleme geben.
Aber sonst ist das so ok.
CodeBox asm
;Start, Power ON, Reset
main:
ldi r16,lo8(RAMEND)
out SPL,r16 ;Init Stackpointer LO
ldi r16,hi8(RAMEND)
out SPH,r16 ;Init Stackpointer HI
rcall Stelle4
rcall Z1 ;Ziffer 1
rcall waitMs
rcall Stelle3
rcall Z2 ;Ziffer 2
rcall waitMs
rcall Stelle2
rcall Z3 ;Ziffer 3
rcall waitMs
rcall Stelle1
rcall Z4 ;Ziffer 4
rcall waitMs
rjmp main
;------------------------------------------------------------------------
mainloop: wdr
;------------------------------------------------------------------------
rjmp mainloop
;------------------------------------------------------------------------
Z0: ;Ziffer 0
ldi r17,0b11111100
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z1: ;Ziffer 1
ldi r17,0b01100000
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z2: ;Ziffer 2
ldi r17,0b11011010
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z3: ;Ziffer 3
ldi r17,0b11110010
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z4: ;Ziffer 4
ldi r17,0b01100110
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z5: ;Ziffer 5
ldi r17,0b10110110
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z6: ;Ziffer 6
ldi r17,0b10111110
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z7: ;Ziffer 7
ldi r17,0b11100000
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z8: ;Ziffer 8
ldi r17,0b11111110
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;------------------------------------------------------------------------
Z9: ;Ziffer 9
ldi r17,0b11110110
out DDRD,17 ; << muß das nicht r17 heißen ?
ret
;-----------------------------------------------------------------------
Stelle4:
ldi r20,0b00001000
out DDRC,20 ; << muß das nicht r20 heißen ?
ret
;------------------------------------------------------------------------
Stelle3:
ldi r20,0b00000100
out DDRC,20 ; << muß das nicht r20 heißen ?
ret
;------------------------------------------------------------------------
Stelle2:
ldi r20,0b00000010
out DDRC,20 ; << muß das nicht r20 heißen ?
ret
;------------------------------------------------------------------------
Stelle1:
ldi r20,0b00000001
out DDRC,20 ; << muß das nicht r20 heißen ?
ret
;------------------------------------------------------------------------
Irgendwie stellst du da ne Menge an den Dadenrichtungs-Registern für
die Ports C und D dran rum. Warum so kompliziert ? Man stellt normalerweise
alle 8 Bits eines Ports auf einmal ein. Außerdem gibt es nach meiner Meinung
keinen Befehl, mit dem man einen Wert direkt in ein Ausgangsregister schreiben
kann. Darum geht das auch immer indirekt über ein weiteres Register als
Zwischenspeicher. es müßte also zum Beispiel so heißen ...
CodeBox asm
;########## BEISPIEL VON MIR ############
ldi r18,0b00110000 ; PortB: PB4 und PB5 auf Ausgang
out ddrb,r18 ; setzen
ldi r18,0b00001001 ; PullUps bei PB0 und PB3 einschalten
out portb,r18 ; setzen
und weiter im Text ...
CodeBox asm
; UP WaitMs, Warteroutine im Millisekundenbereich
waitMs: push r16 ;r16 retten
push r17 ;r17 retten
push r18 ;r18 retten
ldi r16,10
loop1: ldi r17,10 ;Laufvariable loop1 0xFF
loop2: ldi r18,10 ;Laufvariable loop3 13 255
loop3: dec r18 ;Zähler 3 -1, hier Kalibrierung auf MCU Takt
brne loop3 ;Solange nicht NULL
dec r17 ;Zähler 2 -1
brne loop2 ;Solange nicht NULL
dec r16 ;Zähler1 -1
brne loop1 ;Solange nicht NULL
pop r18 ;r18 wiederherstellen
pop r17 ;r17 wiederherstellen
pop r16 ;r16 wiederherstellen
ret ;Rücksprung
;------------------------------------------------------------
Die Warteschleife sieht soweit gut aus ...
Aber das mit deiner Ziffernanzeige wird mit den Befehlen nix. Da ist nach
meiner Meinung noch ein kleines Verständnisproblem
Ich glaube, du
versuchst die Segmente und Stellen mit den DDR-Registern an- und
abzuschalten. Das geht leider so nicht. Lies dir mal folgendes durch ...
Mini-FAQ : Die Port-Register DDRx, PORTx, PINx
Das erklärt dir einige Sachen mit den Ports ...
Wie ziehe ich ein Projekt durch ... (7-Segment-Multiplexanzeige)
Das sollte dir eine andere einfachere Lösungsmöglichkeit zeigen. So bei
Beitrag #19 (Seite 2) wirds Programmtechnisch interessant. Ich mache das
über Daten-Tabellen. Auf die Art arbeiten auch Character-LCDs in ihrem
Inneren
Das ist sehr flexibel und einfach zu programmieren.
Ich hab die Quellcodes aber nie selber getestet. Alles im Kopf zusammengebaut
und hoffentlich fehlerfrei
Gruß
Dino