Hallo,
habe hier ein Atmel ATmega8 auf dem AVR Board.
Programmie mit my AVRWorkpad.
Zu meinem problemchen.
Lese den Poti ein und wandle ihn digital um lege dies auf r16.
dann schieb ich mir (rol) r 16, das mir nur noch 2 bits bleiben (0+1)
D.h. theoretisch 2 ausgänge mit 4 zuständen!
Dies funktioniert auch alles ohne probleme.
Nun möchte ich bei keinem ausgang ein unterprogramm ansteuern...
bei Ausgang 1 ein unterprogramm und bei Ausgang 2 ein unterprogramm
ansteuern.
Dazu wollte ich einfach 2 register verlgleichen
ldi r20,0b00000000 ; Wert zum vergleichen bei keinem ausgang
cp r16,20
brlt TEST
TEST: sbi PORTD,0
ldi r20,0b00000001 ; Wert zum vergleichen bei keinem ausgang
cp r16,20
brlt TEST1
TEST1: sbi PORTD,1
ldi r20,0b00000011 ; Wert zum vergleichen bei keinem ausgang
cp r16,20
brlt TEST2
TEST2: sbi PORTD,2
aber irgendwie funktioniert das ganze so nicht ...
wo ist mein fehler ???
vielen dank
brlt ist der falsche Branch
Ich hab zwar das was du machen willst, wahrscheinlich nicht richtig
verstanden (auch deswegen, weil 'Ausgang' ein anderwertig mit Bedeutung
beladener Begriff ist), aber ich denke du willst eigentlich auf
Gleichheit testen: breq. Oder auf Ungleichheit: brne
ldi r20,0b00000000 ; Wert zum vergleichen bei keinem ausgang
cp r16,r20
breq Kein_Ausgang
Noch ein Hinweis: Ein Branch wird genommen, wenn eine Bedingung erfüllt
ist. breq macht also einen Sprung, wenn das (in deinem Fall)
vorhergehende Vergleichsergebnis 'gleich' lautet.
Völlig sinnlos ist aber das hier:
1
ldi r20,0b00000000 ; Wert zum vergleichen bei keinem ausgang
2
cp r16,20
3
brlt TEST
4
5
TEST: sbi PORTD,0
6
7
ldi r20,0b00000001 ; Wert zum vergleichen bei keinem ausgang
8
cp r16,20
9
brlt TEST1
10
11
TEST1: sbi PORTD,1
Gehs von oben durch: Wenn lt, wird nach TEST gesprungen. Aber was
passiert, wenn brlt nicht springt? Genau. Es geht ebenfalls bei TEST
weiter. Quintessenz: Egal wie der Test ausgeht, es geht immer bei TEST
weiter.
(Und tu dir selbst einen Gefallen, und rücke die Anweisungen ein. Dann
sieht man näcmlich viel besser wo Labels, also potentielle Sprungziele,
sind. Und wenn du auf eine Sequenz...
1
....
2
brXX Label
3
Label: ....
... stößt, dann ist irgendwas faul, weil der branch (oder auch ein rjmp)
sinnlos ist und sich nichts verändern würde, wenn man ihn einfach
rausnimmt
)
So dann versuche ich das Ganze nocheinmal zu erklären.
ich habe einen Poti.
mit diesem möchte ich einen motordrezhal steuern.
Dies soll aber nur stufig geschehen (3 Stufen + Aus).
Der Motor braucht ein pulsierendes signal zum drehen (schrittmotor)
leider bekomme ich nicht hin die zu realisieren? wo liegt mein fehler ?
Hier mein bisheriges programm:
VIELEN DANK FÜR JEGLICHE HILFE:
;-----------------------------------------------------------------------
-
;Reset and Interrupt vector ;VNr. Beschreibung
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 ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
rjmp onADC ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comparator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Store Program Memory Ready
;-----------------------------------------------------------------------
-
;Start, Power ON, Reset
main:
ldi r16,lo8(RAMEND)
out SPL,r16
ldi r16,hi8(RAMEND)
out SPH,r16
ldi r16,0b11111111 ;Festlegung als Ausgang von PORTB
out DDRB,r16
sei
sbi DDRD,2
sbi DDRD,3
sbi DDRD,4
sbi DDRD,5
;-----------------------------------------------------------------------
-
;AD Wandlereinstellungen aktivierung
ldi r16,0b00100000
out ADMUX,r16
ldi r25,0b11011101
out ADCSRA,r25
;-----------------------------------------------------------------------
-
;Analogwert auswerten
in r17,ADCL ; Analogwert wird abgelegt
in r16,ADCH ; Analogwert wird abgelegt
lsr r16 ; schieben um 1 nach rechts ( geteilt durch 2)
lsr r16
lsr r16
lsr r16
lsr r16
lsr r16
out PORTB,r16 ; Register 16 wird auf port B ausgegebn
ldi r20,0b00000000 ; Auswertung für Tempo1
cp r16,r20
breq TEMPO1
ldi r20,0b00000001 ; Auswertung für Tempo2
cp r16,r20
breq TEMPO2
ldi r20,0b00000010 ; Auswertung für Tempo3
cp r16,r20
breq TEMPO3
ldi r20,0b00000011 ; Auswertung für AUS
cp r16,r20
breq
;-----------------------------------------------------------------------
TEMPO1: ;Unterprogramm "Drehzahl1"
;sbi PORTD,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop1: ldi r25,0x06 ;0xFF ins Arbeitregister r25 laden
loop2: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop3: subi r24,0x06 ;Registerinhalt in r24 um 1 vermindern
brcc loop3 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop2 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop1 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTD,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
;Unterprogramm "Drehzahl1"
TEMPO2: sbi PORTD,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop21: ldi r25,0x06 ;0xFF ins Arbeitregister r25 laden
loop22: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop23: subi r24,0x10 ;Registerinhalt in r24 um 1 vermindern
brcc loop23 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop22 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop21 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTD,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
TEMPO3: ;Unterprogramm "Drehzahl1"
sbi PORTD,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop31: ldi r25,0x06 ;0xFF ins Arbeitregister r25 laden
loop32: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop33: subi r24,0x16 ;Registerinhalt in r24 um 1 vermindern
brcc loop33 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop32 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop31 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTD,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
onADC:
cli
sbi ADCSRA,6 ;Bit 6 startet Konvertierung beim drehen am Poti
sei
reti
Hänge Dein Programm bitte als .asm an.
Das lässt sich doch nicht ohne Fehler compilieren oder?
Ich sehe da mehrere Punkte, an denen das scheitert.
Otto
Hi
Als erstes solltest du dir angewöhnen in den Kommentaren zu beschreiben
warum du etwas machst. Einen push oder pop-Befehl zu kommentieren ist
recht sinnfrei. Auch sollten die Kommentare den Befehlen entsprechen.
Als Nächstes erleichtert eine Formatierung, wie sie Karl-Heinz
vorgeschlagen hat, die Lesbarkeit ungemein.
ldi r20,0b00000000 ; Auswertung für Tempo1
cp r16,r20
lässt sich durch 'tst r16' ersetzen
ldi r20,0b00000001 ; Auswertung für Tempo2
cp r16,r20
lässt sich durch 'cpi r16,1' ersetzen
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop21 ;wiederhole solange bis Flag C in r26 =1
da benutzt man besser:
dec r26
brne loop21
Warum springst du mit 'rjmp main' wieder an den Programmanfang mit der
Initialisierung?
>;Analogwert auswerten> in r17,ADCL ; Analogwert wird abgelegt> in r16,ADCH ; Analogwert wird abgelegt
Woher weisst du, wann der ADC fertig ist?
ADEN ADSC ADFR ADIF ADIE
> ldi r25,0b11011101> out ADCSRA,r25
Sollte besser mit Bitnamen erfolgen:
ldi r25,1<<ADN|...|1<<ADPS2|1<<ADPS0
out ADCSRA,r25
...................
MfG Spess
cli und sei im Interrupt Handler sind Unsinn. Das macht die
Controller-Hardware automatisch. Ansonsten solltest Du auch im
Interrupt Handler die ADC-Datenregister auslesen! Dazu ist der Interrupt
schließlich da. Und den ADC im Interrupt Handler von Hand starten ist
auch überflüssig. Nimm den Free-Running-Mode, dann geht auch das
automatisch.
Bevor ich es vergesse:
Empfehlenswerte Literatur:
AVR-TutorialBitmanipulationFormatierung im Forum
Hi
>cli und sei im Interrupt Handler sind Unsinn. Das macht die
Da ist noch mehr Unsinn:
> ldi r16,0b00100000> out ADMUX,r16
1. Damit (0b00XXXXXX) schaltest du die internen Referenzspannungen ab.
Fall jetzt nichts an AREF hängt ist deine Referenzspannung 0V.
2. Mit 0bXX1XXXXXX stzt du ADLAR (Left Adjust). Damit befinden sich die
höherwertigsten 8 Bit in ADCH. In der 'Auswertung' schiebst du ADCH 6x
nach rechts um die obersten 2 Bits zu erhalten. Mit ADLAR=0 bräuchtest
du lediglich ADCH auswerten.
MfG Spess
hab noch etwas weiter gemacht doch leider finde ich den fehler nicht
bekomme es hier leider nicht besser eingerückt:
wie geschrieben steuere über einen ausgang eine schrittmotorplatine an.
diese braucht ein pulsierendes signal, damit der motor sich dreht.
;+----------------------------------------------------------------------
.include "AVR.H"
;-----------------------------------------------------------------------
-
;Reset and Interrupt vector ;VNr. Beschreibung
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 ;10 TC0 Overflow
reti ;11 SPI, STC Serial Transfer Complete
reti ;12 UART Rx Complete
reti ;13 UART Data Register Empty
reti ;14 UART Tx Complete
rjmp onADC ;15 ADC Conversion Complete
reti ;16 EEPROM Ready
reti ;17 Analog Comparator
reti ;18 TWI (I²C) Serial Interface
reti ;19 Store Program Memory Ready
;-----------------------------------------------------------------------
-
;Start, Power ON, Reset
main:
ldi r16,lo8(RAMEND)
out SPL,r16
ldi r16,hi8(RAMEND)
out SPH,r16
;Ausang festlegen
sbi DDRC,4 ;Ausgang für Motor- braucht pulsierendes signal
;AD Wandlereinstellungen aktivierung
ldi r18,0b00100000
out ADMUX,r18
ldi r19,0b11011101
out ADCSRA,r19
;Statusregister konfigurieren
ldi r20,0b11111111 ;Bit 7 Global Interrupt Enable
out SREG,r20 ;Bit 6 Bit Copy Storage
;Bit 5 Half Carry Flag
;Bit 4 Sign Bit
;Bit 3 Two’s Complement Overflow Flag
;Bit 2 Negative Flag
;Bit 1 Zero Flag
;Bit 0 Carry Flag
;-----------------------------------------------------------------------
-
;Analogwert auswerten
;Hier soll der Analogwert voom Poti (Eingang C0) digitalisiert und
minimiert werden
onADC:
cli
sbi ADCSRA,6 ;Bit 6 startet Konvertierung beim drehen am Poti
sei
in r21,ADCL ; Analogwert wird abgelegt
in r22,ADCH ; Analogwert wird abgelegt
lsr r22 ; schieben um 1 nach rechts ( geteilt durch 2)
lsr r22
lsr r22
lsr r22
lsr r22
lsr r22
out ADMUX,r18
sbi ADCSRA,6
;---------------------------
;Hier soll die Auswahl erfolgen, welche fest Drezahl ausgwählt wird.
;Hierzu soll das digitalisierte und minimierte Signal vom Poti (Eingang
C0)
;mit festen Werten im r23 verglichen werden.
ldi r23,0b00000000 ; Auswertung für Tempo1
cp r22,r23
breq lapp1
rjmp TEMPO1
lapp1:
ldi r23,0b00000001 ; Auswertung für Tempo2
cp r22,r23
breq lapp2
rjmp TEMPO2
lapp2:
ldi r23,0b00000010 ; Auswertung für Tempo3
cp r22,r23
breq main
rjmp TEMPO3
;-----------------------------------------------------------------------
;Hier wird der Motor für einen Zeitraum X ein dann wieder ausgeschaltet
;Unterprogramm "Drehzahl1"
TEMPO1: sbi PORTC,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop1: ldi r25,0x05 ;0xFF ins Arbeitregister r25 laden
loop2: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop3: subi r24,0x06 ;Registerinhalt in r24 um 1 vermindern
brcc loop3 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop2 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop1 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTC,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
;Hier wird der Motor für einen Zeitraum X ein dann wieder ausgeschaltet
;Unterprogramm "Drehzahl1"
TEMPO2: sbi PORTC,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop21: ldi r25,0x15 ;0xFF ins Arbeitregister r25 laden
loop22: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop23: subi r24,0x10 ;Registerinhalt in r24 um 1 vermindern
brcc loop23 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop22 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop21 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTC,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
;Hier wird der Motor für einen Zeitraum X ein dann wieder ausgeschaltet
;Unterprogramm "Drehzahl1"
TEMPO3: sbi PORTC,4 ;Motor an
push r24 ;Inhalt von Register r24 kellern
push r25 ;Inhalt von Register r25 kellern
push r26 ;Inhalt von Register r246 kellern
ldi r26,0x01 ;0x10 ins Arbeitregister r26 laden
loop31: ldi r25,0x50 ;0xFF ins Arbeitregister r25 laden
loop32: ldi r24,0xFF ;0xFF ins Arbeitregister r24 laden
loop33: subi r24,0x16 ;Registerinhalt in r24 um 1 vermindern
brcc loop33 ;wiederhole solange bis Flag C in r24 =1
subi r25,0x01 ;Registerinhalt in r25 um 1 vermindern
brcc loop32 ;wiederhole solange bis Flag C in r25 =1
subi r26,0x01 ;Registerinhalt in r26 um 1 vermindern
brcc loop31 ;wiederhole solange bis Flag C in r26 =1
pop r26 ;Inhalt von Register r26 entkellern
pop r25 ;Inhalt von Register r25 entkellern
pop r24 ;Inhalt von Register r24 entkellern
cbi PORTC,4 ;Motor aus
rjmp main
;-----------------------------------------------------------------------
Hi
>hab noch etwas weiter gemacht doch leider finde ich den fehler nicht
Wenn es nur 'den' Fehler gäbe. Aber, entschuldige bitte, dein 'Programm'
strotzt vor Fehlern.
>;Statusregister konfigurieren> ldi r20,0b11111111 ;Bit 7 Global Interrupt Enable> out SREG,r20 ;Bit 6 Bit Copy Storage> ;Bit 5 Half Carry Flag.....
Wo hast du den den Unsinn her? Es gibt normalerweise keinen Grund SREG
zu initialisieren oder zu manipulieren. Als Anfänger schon garnicht.
Du hast eine Interruptroutine 'OnADC' aber nirgen ein 'RETI', statt
dessen springst du wieder nach 'main'. Stacküberlauf garantiert.
Dein 'Main' ist keine Schleife. Dein Programm läuft lustig von Main über
OnADC und dem Rest hin und her.
..........
Versuch mal das 'Programm' in überschaubare Funktionen zu bringen, die
du dann in Unterprogramme verpackst und bei Bedarf aufrufst.
MfG Spess