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 )
Wie wärs denn mit cp r16,r20 statt cp r16,20 ?
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-Tutorial Bitmanipulation Formatierung 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.