- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 4 von 4

Thema: AtMega16 Timer1 Overflow Zeitberechnung

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    13.09.2007
    Beiträge
    39

    AtMega16 Timer1 Overflow Zeitberechnung

    Anzeige

    Praxistest und DIY Projekte
    Hallo!
    So, für die Uni muss ich auf 4 verschiedene Arten ein PWM Signal (50us high, 25us low) generieren.
    Timer1 mit Prescaler von 8 wird verwendet (F_CPU = 16M).
    Bei der Timeroverflow Methode weicht leider mein berechneter Wert für High- und Lowtime vom gemessenen ab. Bei dieser Methode sollen wir nur die berechneten Preload Werte einsetzten ohne Fehlerkorrektur also soll der Wert nicht genau stimmen (25us, 50us).

    Der Assemblercode der ISR ist im Anhang (mit Debuginfos von C Datei).
    Hier die Ergebnisse von 4 Messungen:
    Code:
    +---------+-----------+----------+---------+
    | Messung | High Time | Low Time | Periode |
    +---------+-----------+----------+---------+
    |       1 |   52.04us |  26.46us | 78.50us |
    +---------+-----------+----------+---------+ 
    |       2 |   52.00us |  26.49us | 78.50us |
    +---------+-----------+----------+---------+ 
    |       3 |   52.05us |  26.45us | 78.50us |
    +---------+-----------+----------+---------+ 
    |       4 |   52.09us |  26.40us | 78.50us |
    +---------+-----------+----------+---------+
    Da ich in der Main ständig in den Idle Sleep Modus gehe, dauert es mMn
    4+4+3 Taktzyklen bis ich den ISR Code erreicht habe (4 cycles PC push, 3 cycles JMP @ Vector Adresse, 4 cycles weil Sleep).
    Wakeup-Time hab ich beim Idle Sleep nicht gefunden im Datasheet, sondern nur bei Powerdown und noch einem anderen "tiefen" Modus.

    Bis der Pin auf HIGH gesetzt wird, vergehen also:
    4+4+3
    2+1+1 (lds, and, brne=false)
    2 (sbi)
    --------
    17 cycles

    Bis der neue Preload eingetragen ist:
    17
    1+1+2 (ldi, ldi, rjmp)
    1+1 (out, out)
    -------
    23 cycles

    Innerhalb dieser 23 cycles hat der Timer floor(23/ = 2 increments ausgeführt.


    Jetzt läuft der Timer wieder normal weiter, bis der Pin auf LOW geht vergehen folgende cycles:
    4+4+3
    2+1+2 (lds, and, brne=true)
    2 (cbi)
    --------
    18 cycles

    Bis der neue Preload eingetragen ist:
    18
    1+1 (ldi, ldi)
    1+1 (out, out)
    --------
    22 cycles

    Hier ebenfalls 2 increments beim Timer.

    Da der Wechsel von HIGH auf LOW und umgekehrt ca gleich schnell erfolgt (nach 17 bzw 18 cycles) und der Preloadwert noch vor dem 24ten cycle eingetragen wird, sollte mMn eine Verzögerung von 2 Timeriterationen (16 cycles) bei HIGH und LOW sein.
    Ist es aber nicht, wie man den gemessenen Werten entnehmen kann.

    Ich bräuchte nun Hilfe, ich bin mit meinem Latein am Ende. Bei der busywait Variante war alles noch so schön leicht
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.685
    Hallo cbg,

    kannst Du mal den Code posten? Aber bitte in "in üblicher Weise" , also genauso wie Du Deine Messergebnisse gepostet hast? Bei Deiner txt-Datei müsste man ja erst ne halbe Stunde die Buchstaben ordnen . Und ich meine den originalen Code.

    Vielleicht reicht es aber auch, wenn Du Dir in der Atmeldoc zum M16 den Abschnitt Clear Timer on Compare Match (CTC) Mode durchliest und (z.B.) den OC1A direkt vom Controller schalten läßt. Schau doch mal im Doc das Timingdiagramm auf Abb. 45 an. (Doc in der Version 2466P–AvR–08/07).

    Zitat Zitat von cbg
    ... So, für die Uni muss ich ...
    Was ist denn das für eine Uni? Gibts dort keine Assistenten die Du fragen kannst? Es gibt nämlich Unis, da haben die Assistenten entweder "open door" oder wenigstens Sprechstunden. Und bist Du der einzige Student? Es soll ja Unis geben, wo man den/die Kommilitonen fragen kann. Nicht dass Dir hier nicht geholfen werden soll, ich wundere mich nur.
    Ciao sagt der JoeamBerg

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    13.09.2007
    Beiträge
    39
    Ja werd den Code nochmal posten. Ich glaub du meinst mit "halbe Stunde die Buchstaben ordnen", dass es kein CR gibt sondern nur LF (vom Linux). Werd nur den Assemberteil rauskopieren.
    CTC Mode darf ich für dieses Teilbeispiel eben NICHT verwenden. Das PWM Signal soll auf 4 Arten erzeugt werden.
    1) Busywait (funktionniert so wies soll)
    2) Overflow (geht eben ned so gut)
    3) CTC (funktionniert so wies soll)
    4) FastPWM (funktionniert so wies soll)

    Das ist eine Laborübung aber ich hab mir das Laborkit ausgeborgt um auch zuhause arbeiten zu können. Ich kann durch andere Kurse bedingt nicht imma hinschaun. Dort sind ausserdem auch nur Tutoren, da weiß der eine mal ein bisschen mehr, der andere weniger. Ich glaube aber auch, dass die Frage gar nicht so genau beantwortet gehört ("How long is the signal really high and low in each of these methods and why? How do you
    compute the actual high- and low-times? Verify your calculations with the oscilloscope.") aber ich möchte es persönlich wissen.

    Code (mit C-Code Kommentaren):
    Code:
    ISR_SIG_OVERFLOW1:
    	;__attribute__((naked)) SIGNAL(SIG_OVERFLOW1) {
    	; static uint8_t delay_select = 0;
    	; if(delay_select == 0) {
    	lds	r18, 0x0060	; # +2 cycles
    	and	r18, r18	; # +1 cycle
    	brne	.+8      	; zu cbi # +2/1 cycles
    	;  P_PORT |= (1<<P_NR);
    	sbi	0x12, 5		; 18 # +2 cycles
    	;  TCNT1 = PRELOAD_50US;
    	ldi	r24, 0x9C	; 156 # +1 cycle
    	ldi	r25, 0xFF	; 255 # +1 cycle
    	rjmp	.+6      	; zum ersten out # +2 cycles
    	; } else {
    	;  P_PORT &= ~(1<<P_NR);
    	cbi	0x12, 5	; 18	; # +2 cycles
    	;  TCNT1 = PRELOAD_25US;
    	ldi	r24, 0xCE	; 206 # +1
    	ldi	r25, 0xFF	; 255 # +1
    	out	0x2d, r25	; 45 # +1
    	out	0x2c, r24	; 44 # +1
    	; }
    	; /* toggle delay_select */
    	; delay_select = 1 - delay_select;
    	ldi	r24, 0x01
    	sub	r24, r18
    	sts	0x0060, r24
    	; asm volatile("reti \n\t" ::);
    	reti
    	;}
    	
    MAIN:
    	;void main() {
    	; /* Pin P_NR as output, initially 0 */
    	; P_DDR |= (1<<P_NR);
    	; /* enable Idle sleep mode */
    	; MCUCR |= (1<<SE);
    	; /* turn off AC to reduce power consumption */
    	; ACSR |= (1<<ACD);
    	; /* Timer1 in Normal Mode
    	;  *  default, so nothing to do */
    	; /* Enable Timer1 overflow interrupt */
    	; TIMSK |= (1<<TOIE1);
    	; /* Preload Timer1 to get Interrupt after 25us */
    	; TCNT1 = PRELOAD_25US;
    	; /* Start TIMER1 clock F_CPU/8 */
    	; TCCR1B |= (1<<CS11);
    	; /* enable interrupts */
    	; sei();
    	ldi	r28, 0x5F	; 95
    	ldi	r29, 0x04	; 4
    	out	0x3e, r29	; 62
    	out	0x3d, r28	; 61
    	sbi	0x11, 5	; 17
    	in	r24, 0x35	; 53
    	ori	r24, 0x40	; 64
    	out	0x35, r24	; 53
    	sbi	0x08, 7	; 8
    	in	r24, 0x39	; 57
    	ori	r24, 0x04	; 4
    	out	0x39, r24	; 57
    	ldi	r24, 0xCE	; 206
    	ldi	r25, 0xFF	; 255
    	out	0x2d, r25	; 45
    	out	0x2c, r24	; 44
    	in	r24, 0x2e	; 46
    	ori	r24, 0x02	; 2
    	out	0x2e, r24	; 46
    	sei
    
    	; while(1)
    	;  asm volatile("sleep \n\t");
    	sleep
    	rjmp	.-4		; zu sleep
    	;}
    Code (ohne C-Code Kommentare):
    Code:
    ISR_SIG_OVERFLOW1:
    	; if togglevariable == 0
    	lds	r18, 0x0060	; # +2 cycles
    	and	r18, r18	; # +1 cycle
    	brne	.+8      	; zu cbi # +2/1 cycles
    
    	;  LED setzen
    	sbi	0x12, 5		; # +2 cycles
    	;  preload 50us;
    	ldi	r24, 0x9C	        ; 156 # +1 cycle
    	ldi	r25, 0xFF        ; 255 # +1 cycle
    	rjmp	.+6      	; zum ersten out # +2 cycles
    
            ; LED löschen
    	cbi	0x12, 5        ; # +2 cycles
    	;  preload 25us
    	ldi	r24, 0xCE	       ; 206 # +1
    	ldi	r25, 0xFF        ; 255 # +1
    
           ; preloadwert schreiben
    	out	0x2d, r25        ; 45 # +1
    	out	0x2c, r24        ; 44 # +1
    
           ; toggle variable neu setzen
    	ldi	r24, 0x01
    	sub	r24, r18
    	sts	0x0060, r24
    	reti
    	
    MAIN:
    	ldi	r28, 0x5F	; 95
    	ldi	r29, 0x04	; 4
    	out	0x3e, r29	; 62
    	out	0x3d, r28	; 61
    	sbi	0x11, 5	; 17
    	in	r24, 0x35	; 53
    	ori	r24, 0x40	; 64
    	out	0x35, r24	; 53
    	sbi	0x08, 7	; 8
    	in	r24, 0x39	; 57
    	ori	r24, 0x04	; 4
    	out	0x39, r24	; 57
    	ldi	r24, 0xCE	; 206
    	ldi	r25, 0xFF	; 255
    	out	0x2d, r25	; 45
    	out	0x2c, r24	; 44
    	in	r24, 0x2e	; 46
    	ori	r24, 0x02	; 2
    	out	0x2e, r24	; 46
    	sei
    
    	sleep
    	rjmp	.-4		; zu sleep

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Der Simulator von AVRStudio ist zwar nicht perfekt, aber hier sollte er ausreichen. Einfach mal im Simulator schritt für schritt laufen lassen da sollte man sehen wo etwas falsch läuft.

Berechtigungen

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

12V Akku bauen