-         

Ergebnis 1 bis 5 von 5

Thema: [ERLEDIGT] Assembler-Anfänger Problem mit Timern

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Schrobenhausen, München
    Alter
    24
    Beiträge
    583

    [ERLEDIGT] Assembler-Anfänger Problem mit Timern

    Anzeige

    Hallo zusammen,

    in der Schule lernen wir in Info zur Zeit Assembler und da hab ich mir gedacht ich lern jetz mal AVR-Assembler

    Ich mach grad das mikrocontroller.net-tutorial durch und bin bei den timern

    Code:
    #define servoreg1 DDRA
    #define servoreg2 DDRA
    #define servoport1 PORTA
    #define servoport2 PORTA
    #define servopin1 PA0
    #define servopin2 PA1
    .def servo1 = R19
    .def servo2 = R20
    
    .include "m32def.inc"
    
    
    .def tmp = R16			; Allzweckregister
    .def counter = R17		; Counter für Timer-1-Zyklen
    .def counter2 = R18		; Counter für Timer-0-Zyklen
    .equ Timer1AOVF = 200	; 200 = 0,1ms bei prescaler 8
    						; 20 = 0,01ms bei prescaler 8
    						; 2 = 0,001ms bei prescaler 8
    						; 10 = 0,005ms bei prescaler 8
    						; 16 = 0,001ms bei prescaler 1
    						; 80 = 0,005ms bei prescaler 1
    
    .org 0x000
           rjmp Main
    .org OC1Aaddr                 ; Output Compare1A Interrupt Vector Address
    		rjmp OC1A_interrupt
    .org OVF0addr                 ; Overflow0 Interrupt Vector Address
    		rjmp OVF0_interrupt
    
    .org INT_VECTORS_SIZE
    
    OC1A_interrupt:
    	inc counter
    
    	;update servos:
    	cp counter, servo1
    	brne s2
    	cbi servoport1, servopin1
    s2:
    	cp counter, servo2
    	brne counterreset
    	cbi servoport2, servopin2
    counterreset:
    	cpi counter, 200
    	brne end
    	clr counter
    	sbi servoport1, servopin1
    	sbi servoport2, servopin2
    end:	reti
    
    OVF0_interrupt:
    	inc counter2
    	cpi counter2, 255
    	brne end2
    	inc servo1
    	inc servo2
    	clr counter2
    	cpi servo1, 21
    	brne end
    	ldi servo1, 10
    	ldi servo2, 10
    end2:	reti
    
    
    Main:                       ; hier beginnt das Hauptprogramm
    		ldi tmp, HIGH(RAMEND)            ; HIGH-Byte der obersten RAM-Adresse
    		out SPH, tmp
    		ldi tmp, LOW(RAMEND)             ; LOW-Byte der obersten RAM-Adresse
    		out SPL, tmp
    		clr tmp
    ;/*Timer 0:
    		ldi tmp, ( 1 << CS02 ) | ( 1 << CS00 )	; Prescaler auf 1024
            out TCCR0, tmp
    							;=> 61.4 Overflows in der Sekunde (bei 16 MHz)
    							;=> alle 16,4 ms
    		ldi tmp, TIMSK
    		ori tmp, ( 1 << TOIE0 )      ; TOIE0: Interrupt bei Timer Overflow
            out TIMSK, tmp
    ;*/ ;Timer 0
    
    ;/*Timer 1:
    		ldi tmp, high( Timer1AOVF - 1 )
            out OCR1AH, tmp
            ldi tmp, low( Timer1AOVF - 1 )
            out OCR1AL, tmp
                                        ; Prescaler auf 1 (001), 8 (010), 64 (011), 256 (100), 1024 (101)
            ldi tmp, ( 1 << WGM12 ) | ( 1 << CS11 )
            out TCCR1B, tmp
     
     		ldi tmp, TIMSK
    		ori tmp, ( 1 << OCIE1A )      ; OCIE1A: Interrupt bei Timer Compare A
            out TIMSK, tmp
    ;*/ ;Timer 1
    
    
    	ldi tmp, 0xFF
    	out DDRA, tmp
    	
    	
    	ldi counter, 0x00
    	ldi counter2, 0x00
    
    	rcall init_servos
    
    	sei
    loop:
    	
    	rjmp loop
    
    init_servos:
    	sbi servoreg1, servopin1
    	ldi servo1, 10
    	sbi servoreg2, servopin2
    	ldi servo2, 10
    	ret
    Ziel war es:
    2 Servos "parallel" von anschlag1 zu anschlag 2 zu fahren und wenn man dort ankommt wieder auf anschlag 1

    mit timer0 sollte ich dank 16MHz und 1024 prescaler mit dem counter2 und den 256 fürn overflow von mir auf etwa 4 sekunden takte kommen bei denen im interrupt die servopositionen servo1 und servo2 inkrementiert werden, bei 10 positionen sollte das also 40s dauern, bis der wieder die richtung wechselt und zum anschlag 1 fährt.

    timer1 soll dagegen die pwm übernehmen
    16MHz, prescale 8, compare bei 200 --> alle 0.1 ms

    ergebnis des codes sind zwei zwischen anschlag 1 und ca. 15° hin- und herbewegende Servos

    als board nehm ich grad weil ich nix besseres zur hand hatte das pollin funk evaluationsboard ver 1.1 mit ATMega32
    die stromversorgung des Servos läuft zwar auch über den spannungsregler der platine, aber nicht über den controller, der spannungsregler wird dabei weder warm noch sonstwas außergewöhnliches...

    Ich hoffe ihr könnt mir helfen.

    LG Roland

    PS: im AVR-Studio-Debugger läuft alles ohne Probleme, die Taktzyklen sind genau so wie ich sie ausgerechnet hatte, alle 20ms ein neues signal für den servo, die länge des signals passt, auch die zeit zum "hochschalten" der position der Servos stimmt...
    keine ahnung was da wieder nicht geht...
    danke schonmal an alle

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Stimmt den die Taktfrequenz bei dem Board ? Nicht das es da mit 14 MHz läuft.

    Hier passiert nicht, aber mir ist aufgefallen, dass in den ISRs die Register nicht gerettet werden. Wenn da das Hauptprogramm noch was sinnvolles tun soll, gibt das Probleme.

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Schrobenhausen, München
    Alter
    24
    Beiträge
    583
    Hi,

    ich hatte das auch zuvor mit push tmp und anschließendem pop tmp geschrieben, ist im verlauf des debuggings mal rausgeflogen, nicht dass die isr's zu lang sind und sich überschneiden oder was auch immer, keine ahnung

    die frequenz sollte stimmen, hab davor schonmal n kleinen test mit timer1 gemacht, der led's im 0,5s-rhytmus blinken ließ, überprüfung mit uhr, hat genau gestimmt...
    das quarz das verbaut und nach schaltplan und platinen-bahnen mit dem atmega32 verbunden is war mitgeliefert und hat die aufschrift K16.000

    bin echt am verzweifeln hier -.-

    LG Roland

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Schrobenhausen, München
    Alter
    24
    Beiträge
    583
    UPDATE:
    So, ihr seht es ist schon spät und ich bin auch schon einen verfusten Controller weiter... *grml*
    Naja, muss ich schnell nen taktgenerator aufbaun...

    Egal, zurück zum Thema

    getestet:
    -externe stromversorgung für Servos => gleiches ergebnis (verbundene massen etc...)
    -anderer chip => gleiches ergebnis
    -programm umschreiben, jetzt nurnoch led's blinken lassen im 4,...s rhytmus von timer0 wie oben
    funktioniert irgendwie auch nicht -.- (code dafür siehe unten)

    -Fuses umkehren, man weiß ja nie wenn man n anderes Programm hernimmt... => atmega32 verfust...
    fuses für die clock stehen momentan so:
    *ckopt = 1
    *sut1 = 0
    *sut0 = 1
    *cksel3 = 1
    *cksel2 = 1
    *cksel1 = 1
    *cksel0 = 0

    wäre laut datenblatt dann "Ceramic resonator, slowly
    rising power"
    sollte doch passen oder nicht?
    naja, was ich nich versteh is, warum es zu schnell blinkt/fährt

    selbst wenn der statt den 16 MHz dann den internen takt von 1/4/8 MHz nehmen würde, das würde das ganze doch nur verlangsamen
    also die LED's würden dann alle 8sec blinken...
    komisch echt

    Code:
    .include "m32def.inc"
    
    
    .def tmp = R16			; Allzweckregister
    .def counter2 = R18		; Counter für Timer-0-Zyklen
    
    .org 0x000
           rjmp Main
    .org OVF0addr                 ; Overflow0 Interrupt Vector Address
    		rjmp OVF0_interrupt
    
    .org INT_VECTORS_SIZE
    
    OVF0_interrupt:
    	inc counter2
    	cpi counter2, 255
    	brne end
    	in tmp, PORTD
    	com tmp
    	out PORTD, tmp
    end:	reti
    
    
    Main:                       ; hier beginnt das Hauptprogramm
    		ldi tmp, HIGH(RAMEND)            ; HIGH-Byte der obersten RAM-Adresse
    		out SPH, tmp
    		ldi tmp, LOW(RAMEND)             ; LOW-Byte der obersten RAM-Adresse
    		out SPL, tmp
    ;/*Timer 0:
    		ldi tmp, ( 1 << CS02 ) | ( 1 << CS00 )	; Prescaler auf 1024
            out TCCR0, tmp
    							;=> 61.4 Overflows in der Sekunde (bei 16 MHz)
    							;=> alle 16,4 ms
    		ldi tmp, TIMSK
    		ori tmp, ( 1 << TOIE0 )      ; TOIE0: Interrupt bei Timer Overflow
            out TIMSK, tmp
    ;*/ ;Timer 0
    
    
    	ldi tmp, 0xFF
    	out DDRD, tmp
    	ldi tmp, 0x55
    	out PORTD, tmp
    	ldi counter2, 0x00
    
    
    	sei
    loop:
    	
    	rjmp loop
    LG Roland

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Schrobenhausen, München
    Alter
    24
    Beiträge
    583
    Hallo, also letzter Beitrag hier... endlich funktionierts
    Da sieht man mal wieder, ausschlafen lohnt sich...

    statt
    Code:
          ldi tmp, TIMSK 
          ori tmp, ( 1 << TOIE0 )      ; TOIE0: Interrupt bei Timer Overflow 
          out TIMSK, tmp 
    [...]
          ldi tmp, TIMSK 
          ori tmp, ( 1 << OCIE1A )      ; OCIE1A: Interrupt bei Timer Compare A 
          out TIMSK, tmp
    wäre wohl

    Code:
          in tmp, TIMSK 
          ori tmp, ( 1 << TOIE0 )      ; TOIE0: Interrupt bei Timer Overflow 
          out TIMSK, tmp 
    [...]
          in tmp, TIMSK 
          ori tmp, ( 1 << OCIE1A )      ; OCIE1A: Interrupt bei Timer Compare A 
          out TIMSK, tmp
    besser gewsen... (ldi -> in) jetzt funktioniert alles wie erwünscht


    LG Roland

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •