Forum: Mikrocontroller und Digitale Elektronik ATMega16M1 Timer1 Problem


von Rudolph (Gast)


Lesenswert?

Ich versuche gerade dem Timer1 eine PWM im Mode 15 zu entlocken, aber so 
langsam glaube ich, dass mein Controller spinnt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
int main(void)
5
{
6
  cli();
7
  
8
  DDRC = (1<<PC1); // OC1B auf Ausgang
9
10
  TCCR1B = 0x00; // stop
11
  TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); // set OC1B on compare match
12
  TCCR1C = 0x00;
13
  OCR1A = 0x420;
14
  OCR1B = 0x10;
15
  TCCR1B = (1<<CS11) | (1<<WGM12) | (1<<WGM13); // mode = 15, fast-pwm, prescaler = 8 -> 2 MHz -> 500 ns / Tick  
16
  
17
  sei();
18
  
19
    while(1)
20
    {
21
        //TODO:: Please write your application code 
22
    }
23
}

Wenn ich das nachrechne sollte ins Register TCCR1A der Wert 0x23 
geschrieben werden und ins Register TCCR1B der Wert 0x1A.
Dem .lss File zu Folge ist das auch so.

Mein Controller läuft mit 16MHz Quarz, die Fuse-Bits sind richtig.
Das ist jetzt auch nur der auf das Problem reduzierte Ausschnitt, der 
CAN lief ohne Probleme auf 500kBit.
Ich habe extra ein frisches Projekt aufgemacht.
Verschiedene Optimierungs-Stufen habe ich auch durch.

Wenn der Timer jetzt im Mode 15 wäre, dann müsste am Pin OC1B eine PWM 
raus kommen mit:

0x420 = 1056 -> 1057 * 500ns = 528,5µs
0x10 = 16 -> 17 * 500ns = 8,5µs
Also etwa 1890 Hz und 1,5% Duty-Cycle.

Was ich allerdings messen kann sind 16,5µs Periode und 8,5µs Puls.

Mit OCR1A = 0x2ff erhalte ich 384,5µs Perioden-Dauer.
0x2ff = 767 -> 768 * 500ns = 384µs -> passt

Der Timer akzeptiert aus irgendeinem Grund nur Werte bis 0x3ff und hat 
dann einen Überlauf.
Nur macht das überhaupt keinen Sinn, es gibt keinen Modus mit TOP = 
OCR1A und TOP = 0x3ff.

Hier noch der relevante Ausschnitt aus der .lss Datei bei -Os:
1
int main(void)
2
{
3
  cli();
4
  94:  f8 94         cli
5
  
6
  DDRC = (1<<PC1); // OC1B auf Ausgang
7
  96:  82 e0         ldi  r24, 0x02  ; 2
8
  98:  87 b9         out  0x07, r24  ; 7
9
10
  TCCR1B = 0x00; // stop
11
  9a:  10 92 81 00   sts  0x0081, r1
12
  TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); // set OC1B on compare match
13
  9e:  83 e2         ldi  r24, 0x23  ; 35
14
  a0:  80 93 80 00   sts  0x0080, r24
15
  TCCR1C = 0x00;
16
  a4:  10 92 82 00   sts  0x0082, r1
17
  OCR1A = 0x0420;
18
  a8:  80 e2         ldi  r24, 0x20  ; 32
19
  aa:  94 e0         ldi  r25, 0x04  ; 4
20
  ac:  90 93 89 00   sts  0x0089, r25
21
  b0:  80 93 88 00   sts  0x0088, r24
22
  OCR1B = 0x10;
23
  b4:  80 e1         ldi  r24, 0x10  ; 16
24
  b6:  90 e0         ldi  r25, 0x00  ; 0
25
  b8:  90 93 8b 00   sts  0x008B, r25
26
  bc:  80 93 8a 00   sts  0x008A, r24
27
  TCCR1B = (1<<CS11) | (1<<WGM12) | (1<<WGM13); // mode = 15, fast-pwm, prescaler = 8 -> 2 MHz -> 500 ns / Tick  
28
  c0:  8a e1         ldi  r24, 0x1A  ; 26
29
  c2:  80 93 81 00   sts  0x0081, r24
30
  
31
  sei();
32
  c6:  78 94         sei
33
  c8:  ff cf         rjmp  .-2        ; 0xc8 <main+0x34>

Sag mir doch mal bitte jemand, dass ich was falsch mache und was ich 
falsch mache, ich würde den Controller gerne einsetzen.
Ach ja, eine zweite Platine aus einem anderen Projekt zeigt mit der 
Test-Software das gleiche Verhalten.
Die Controller sind mit Date-Code 1330, das ist auf jeden Fall lange 
nach der letzten Revision E des Datenblattes von 11/2012.
Errata sind keine für diesen Controller gelistet.

von Stefan E. (sternst)


Lesenswert?

In dem Augenblick, wo du die OC-Register beschreibst, befindet sich der 
Timer nicht im Mode 15, sondern im Mode 3. Und das ist ein 10-Bit-Modus.

von Rudolph (Gast)


Lesenswert?

Stefan E. schrieb:
> In dem Augenblick, wo du die OC-Register beschreibst, befindet sich der
> Timer nicht im Mode 15, sondern im Mode 3. Und das ist ein 10-Bit-Modus.

Ah, okay, OCR1A wird dann automatisch auf 0x3ff begrenzt, warum auch 
immer.
Und das ist mir bisher auch noch nie aufgefallen.

So funktioniert das jetzt:
1
  TCCR1B = 0x00; // stop
2
  TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10); // set OC1B on compare match
3
  TCCR1B = (1<<WGM12) | (1<<WGM13); // mode = 15, fast-pwm
4
  TCCR1C = 0x00;
5
  OCR1A = 0x0x420;
6
  OCR1B = 0x10;
7
  TCCR1B |= (1<<CS11); // prescaler = 8 -> 2 MHz -> 500 ns / Tick

Danke!

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
Noch kein Account? Hier anmelden.