Forum: Mikrocontroller und Digitale Elektronik atmega328 timer konfiguration


von Andreas H. (Gast)


Lesenswert?

Hallo,

ich bin mal wieder am Verzwifeln mit den Timern vom avr.
Der Controller ist ein atmega328 und ich will mit Timer 1(16bit) ein ppm 
signal mit 50Hz Wiederholfrequenz ausgeben.

Soweit mein code. Ich hoff er ist ausreichend kommentiert
1
#include <avr/io.h>          
2
3
#ifndef F_CPU
4
#define F_CPU 16000000UL
5
#endif
6
7
uint16_t ppm1, ppm2;
8
9
int main (void) {            
10
11
  DDRB = 0xFF;
12
  
13
    PRR &= ~(1<<PRTIM1); //enable timer/cunter 1
14
  
15
     // PB1 and PB2 is now an output
16
17
    ICR1 = 0x9C40;
18
    // set TOP to 40 000 equals 50Hz with prescaler of 8
19
20
    OCR1A = 0x9C4; //1250ppm (*2)
21
    // set PPM1
22
23
    OCR1B = 0xDAC; //1750ppm (*2)
24
    // set PPM2
25
26
    TCCR1A |= (1 << COM1A1)|(1 << COM1B1);
27
    // set none-inverting mode
28
29
    TCCR1A |= (1 << WGM11);
30
    TCCR1B |= (1 << WGM12)|(1 << WGM13);
31
    // set Fast PWM mode using ICR1 as TOP
32
    
33
    TCCR1B |= (1<<CS11);
34
    // START the timer with 8 prescaler -> increments twice a us
35
36
     while(1) {                
37
    asm volatile ("nop");
38
     }                         
39
     return 0;                 
40
}

Das Problem ist, dass PB1 und 2 (OC1A/B) einfach nicht schalten wollen. 
Wo/Was ist mein Fehler?

Ich hoffe ihr könnt mir helfen.

Danke,
Andreas

von MWS (Gast)


Lesenswert?

Würd' mal die Finger vom PRR lassen. Beim Erstbeschreiben eines 
Registers immer die direkte Zuweisung verwenden.

von Oliver (Gast)


Lesenswert?

So auf Anhieb sieht das alles gut aus. Das löschen des Bits im 
PRR-Register kannst du dir zwar sparen, da das nach eime Reset sowieso 
gelöscht ist, aber funktionieren sollte es trotzdem.

Also: Falschen Prozessor zum Compilieren eingestellt? Funktionieren die 
Portpins, wenn du die direkt ansteuerst? Taktfrequenz sollte egal sein, 
selbst bei 1MHz müssten die Pins irgendwann schalten, aber lang genug 
gemessen hast du schon, oder?

Oliver

von Stefan E. (sternst)


Lesenswert?

1
The ICR1 Register can only be written when using a Waveform Generation
2
mode that utilizes the ICR1 Register for defining the counter’s TOP value.
3
In these cases the Waveform Generation mode (WGM13:0) bits must be set
4
before the TOP value can be written to the ICR1 Register.

von Andreas H. (Gast)


Lesenswert?

Zunächst an alle ein großes Dankeschön für die schnelle Hilfe :)
@MWS: Ok werd ich machen
@Oliver: Ne compiler passt schon
@Stefan Ernst: Danke! Das hab ich wohl überlesen. Ich habs jetzt mal im 
Programm geändert. Nacher werd ichs dann mal flashen und Testen ;)
Meld mich dann nochmal wenns trotzdem nicht Funktionert.

Ansonsten: Nochmals Danke für die Hilfe. Das war mein erster Beitrag in 
diesem Forum und ich bin begeistert über die Hilfsbereitschaft hier :)

Viele Grüße,
Andreas

von Karl H. (kbuchegg)


Lesenswert?

Stefan Ernst schrieb:
>
1
The ICR1 Register can only be written when using a Waveform 
2
> Generation
3
> mode that utilizes the ICR1 Register for defining the counter’s TOP 
4
> value.
5
> In these cases the Waveform Generation mode (WGM13:0) bits must be set
6
> before the TOP value can be written to the ICR1 Register.

Oh, das ist aber eine böse Falle. Und so schön versteckt im Datenblatt.

von Karl H. (kbuchegg)


Lesenswert?

Andreas H. schrieb:

Etwas konstruktive Kritik


>     ICR1 = 0x9C40;
>     // set TOP to 40 000 equals 50Hz with prescaler of 8

wenn du 40000 meinst, dann schreib auch 40000 und nicht 0x9c40.

Und im übrigen müssen es 39999 sein, da ja der Zählvorgang von 39999 auf 
0 auch 1 Zählvorgang ist

     ICR1 = 39999;

>     OCR1A = 0x9C4; //1250ppm (*2)
>     // set PPM1

Detto: Wenn du 1250 meinst, dann schreib auch 1250. Und wenn du das 
Doppelte davon willst, dann spricht nichts dagegen das so zu schreiben

     OCR1A = 1250 * 2;

Jeder Kommentar, den du einsparen kannst, weil du genau dasselbe direkt 
im Code ausdrücken kannst, ist es Wert dass man ihn durch entsprechenden 
Code ersetzt.

von Ingo (Gast)


Lesenswert?

In der Tat sehr böse!!! Hatte noch nie diese Problem, da ich das 
Register immer zum Schluss beschreibe...

von Karl H. (kbuchegg)


Lesenswert?

Ingo schrieb:
> In der Tat sehr böse!!! Hatte noch nie diese Problem, da ich das
> Register immer zum Schluss beschreibe...

Geht mir genauso.
Allerdings hätte ich diesen Absatz nie und nimmer bei der Beschreibung 
der Input Capture Edge Select Bits gesucht, sondern beim ICR1H/L 
Register. Nur dort steht nichts davon.

Na ja. Wieder was, was man sich merken muss.

von Andreas H. (Gast)


Lesenswert?

@Kalr Heinz: Hab den Code jetzt übersichtlicher umgeschrieben.

Und wenn ich ICR am Ende schreib funktionerts perfekt.

von Ingo (Gast)


Lesenswert?

Gibt's eigentlich ne Rubrik "Fallen"? Da gehört das rein!

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.