Forum: Mikrocontroller und Digitale Elektronik Timer Probleme?


von X. Y. (elektro_henkler)


Lesenswert?

DDRD |= (1 << DDD6);
 // PD6 is now an output

 OCR0A = 128;
 // set PWM for 50% duty cycle


 TCCR0A |= (1 << COM0A1);
 // set none-inverting mode

 TCCR0A |= (1 << WGM01) | (1 << WGM00);
 // set fast PWM Mode

 TCCR0B |= (1 << CS20);
 // set prescaler to 8 and starts PWM

Mein Controller läuft mit ext. 16MHZ (ATMega328) - Arduino Uno

Wo habe ich den Fehler gemacht, dass mir nur ca 1KHZ ausgegeben werden? 
es müssten doch eigentlich 8KHZ sein.

Das Gleiche habe ich auch, wenn ich ohne Teiler arbeite, dann müsste ich 
ca 62,5KHZ haben und habe nur ca 8KHZ

FUSES habe ich schon überprüft, sollten alle passen.

von Klaus (Gast)


Lesenswert?

CKDIV8 ?

von Klaus (Gast)


Lesenswert?

Nebenbei bemerkt: Die Einheit schreibt sich "Hz".

von X. Y. (elektro_henkler)


Lesenswert?

Klaus schrieb:
> CKDIV8 ?

gucke nach mom

> Nebenbei bemerkt: Die Einheit schreibt sich "Hz".

Das weiß ich wohl ;)

von Klaus (Gast)


Lesenswert?

X. Y. schrieb:
> Klaus schrieb:
>
>> Nebenbei bemerkt: Die Einheit schreibt sich "Hz".
>
> Das weiß ich wohl ;)

Das mag so sein, wenn Du es sagst. Aber wenn Du es in fünf Fällen 
falsch schreibst und in keinem richtig, dann - sagen wir mal - bleibt 
ein gewisser Restzweifel. :-)

von S. Landolt (Gast)


Lesenswert?

> TCCR0B |= (1 << CS20);
> // set prescaler to 8 and starts PWM

Das kann auch angezweifelt werden.

von X. Y. (elektro_henkler)


Lesenswert?

Klaus schrieb:
> X. Y. schrieb:
>> Klaus schrieb:
>>
>>> Nebenbei bemerkt: Die Einheit schreibt sich "Hz".
>>
>> Das weiß ich wohl ;)
>
> Das mag so sein, wenn Du es sagst. Aber wenn Du es in fünf Fällen
> falsch schreibst und in keinem richtig, dann - sagen wir mal - bleibt
> ein gewisser Restzweifel. :-)

schon spät ;) seit 5 uhr wach

von X. Y. (elektro_henkler)


Lesenswert?

X. Y. schrieb:
> Klaus schrieb:
>> CKDIV8 ?
>
> gucke nach mom
>
>> Nebenbei bemerkt: Die Einheit schreibt sich "Hz".
>
> Das weiß ich wohl ;)

Also FUSES sind zz So:

0xFF  0XDA  0x05

von Klaus (Gast)


Lesenswert?

S. Landolt schrieb:
>> TCCR0B |= (1 << CS20);
>> // set prescaler to 8 and starts PWM
>
> Das kann auch angezweifelt werden.

Mist. Übersehen. Na toll.

von Klaus (Gast)


Lesenswert?

X. Y. schrieb:

> schon spät ;) seit 5 uhr wach

Dann würde ich Dir sehr empfehlen mal zu schlafen.
Morgen guckst Du dann in's Datenblatt. Und falls nötig postest Du Code 
bitte mit Copy&Paste.

von X. Y. (elektro_henkler)


Lesenswert?

ok, ich machs mal anders, eigentlich will / möchte ich eine Funktion 
haben damit ich über

OCR0A = 128;
 // set PWM for 50% duty cycle

meine PWM Steuern möchte, eigentlich ohne Teiler und Co. damit ich auf 
ca 62.5 KHz komme.

von X. Y. (elektro_henkler)


Lesenswert?

Klaus schrieb:
> X. Y. schrieb:
>
>> schon spät ;) seit 5 uhr wach
>
> Dann würde ich Dir sehr empfehlen mal zu schlafen.
> Morgen guckst Du dann in's Datenblatt. Und falls nötig postest Du Code
> bitte mit Copy&Paste.

ich bin noch neu auf diesem Gebiet. Wenn ich 100% ig Bescheid wüsste, 
was da so alles passiert, würde ich nicht fragen

von Klaus (Gast)


Lesenswert?

X. Y. schrieb:
> X. Y. schrieb:
>> Klaus schrieb:
>>> CKDIV8 ?
>>
>> gucke nach mom
>>
>>> Nebenbei bemerkt: Die Einheit schreibt sich "Hz".
>>
>> Das weiß ich wohl ;)
>
> Also FUSES sind zz So:
>
> 0xFF  0XDA  0x05

Und dann guckst Du auch mal nach wofür die Bits stehen. Ich schäme mich 
zwar in Grund und Boden für meine Faulheit aber ich will einfach nicht 
selbst nachschauen.

von Klaus (Gast)


Lesenswert?

X. Y. schrieb:
> Klaus schrieb:
>> X. Y. schrieb:
>>
>>> schon spät ;) seit 5 uhr wach
>>
>> Dann würde ich Dir sehr empfehlen mal zu schlafen.
>> Morgen guckst Du dann in's Datenblatt. Und falls nötig postest Du Code
>> bitte mit Copy&Paste.
>
> ich bin noch neu auf diesem Gebiet. Wenn ich 100% ig Bescheid wüsste,
> was da so alles passiert, würde ich nicht fragen

Na dann halt nicht. Schönes Leben noch.

von X. Y. (elektro_henkler)


Lesenswert?

Klaus schrieb:
> X. Y. schrieb:
>> Klaus schrieb:
>>> X. Y. schrieb:
>>>
>>>> schon spät ;) seit 5 uhr wach
>>>
>>> Dann würde ich Dir sehr empfehlen mal zu schlafen.
>>> Morgen guckst Du dann in's Datenblatt. Und falls nötig postest Du Code
>>> bitte mit Copy&Paste.
>>
>> ich bin noch neu auf diesem Gebiet. Wenn ich 100% ig Bescheid wüsste,
>> was da so alles passiert, würde ich nicht fragen
>
> Na dann halt nicht. Schönes Leben noch.

ich habe ja nicht gesagt, das ich mich nicht damit auseinander setzen 
möchte. ich will ja verstehen was passiert. das Datenblatt lesen ist ja 
kein Problem, die Tabellen und so verstehe ich ja auch, nur das setzten 
der einzelnen bits, da habe ich meine Probleme mit

von X. Y. (elektro_henkler)


Lesenswert?

>
> Und dann guckst Du auch mal nach wofür die Bits stehen. Ich schäme mich
> zwar in Grund und Boden für meine Faulheit aber ich will einfach nicht
> selbst nachschauen.

http://www.engbedded.com/fusecalc/

von S. Landolt (Gast)


Lesenswert?

Im eingangs gezeigten Programm steht der Vorteiler in Wirklichkeit auf 
1, also sollte doch eigentlich eine Frequenz von 16000000/256= 62500 
herauskommen.

von X.Y (Gast)


Lesenswert?

S. Landolt schrieb:
> Im eingangs gezeigten Programm steht der Vorteiler in Wirklichkeit
> auf 1, also sollte doch eigentlich eine Frequenz von 16000000/256= 62500
> herauskommen.

Ist aber nicht der Fall, es fehlt immer Faktor 8

von foo (Gast)


Lesenswert?

X.Y schrieb:
> Ist aber nicht der Fall, es fehlt immer Faktor 8

Und das liegt eben an deinen Fuses. Wie die eingestellt sind hast du 
doch schon geschrieben und die von dir ebenfalls bereits verlinkte 
Webseite dekodiert dir das.

Und da steht dann eindeutig dass CKDIV8 aktiv ist!

von S. Landolt (Gast)


Lesenswert?

Dann läuft entweder ein anderes Programm als das gezeigte, oder die low 
byte fuse steht nicht auf 0xFF.

von foo (Gast)


Lesenswert?

S. Landolt schrieb:
> die low
> byte fuse steht nicht auf 0xFF.

Tut sie nicht. Er hat nicht gesagt was die Reihenfolge ist ;)

Aber da der mega328 nur drei Bits in efuse hat, habe ich einfach mal 
0xff als efuse angenommen, weil 0x05 für efuse nicht sein kann (nicht 
vorhandene Bits müssten gecleart sein)

Er hat lfuse=05 hfuse=da efuse=ff.

von S. Landolt (Gast)


Lesenswert?

Kann ich mir nicht vorstellen, das hieße 'Low Frequency Crystal 
Oscillator'.

von S. Landolt (Gast)


Lesenswert?

Kann man in C nicht noch 'F_CPU' oder so was ähnliches definieren?

von foo (Gast)


Lesenswert?

S. Landolt schrieb:
> Kann ich mir nicht vorstellen, das hieße 'Low Frequency Crystal
> Oscillator'.

Hast recht. Das würde nur dann nicht auffallen, wenn der Takt extern 
erzeugt wird. Die Unos haben aber nur Quarz oder Keramik.
(Auch scheints wohl Programme zu geben die die nicht vorhandenen Bits 
als 0 statt 1 ausgeben. Dann passt 0x05 wieder.)

S. Landolt schrieb:
> Kann man in C nicht noch 'F_CPU' oder so was ähnliches definieren?

Hat nur Auswirkungen auf _delay_ms/_delay_us, damit die libc weiß, wie 
der Takt eingestellt ist. Verstellen kann man den damit nicht, auch wenn 
manche Leute das gerne tun wollen :-)

von S. Landolt (Gast)


Lesenswert?

Dann weiß ich nicht mehr weiter, und mache das, was X.Y. wohl auch schon 
tat, ich gehe ins Bett. Eine gute Nacht wünsche ich.

von foo (Gast)


Lesenswert?

Das letzte, was ich vorm Bett prüfen würde, ist, welche Frequenz 
rauskommt, wenn man das nochmal flasht und CKDIV8 setzt. Und dann, 
welche rauskommt, wenn man danach CKDIV8 wieder rausnimmt.

Falls irgendwas falsch gesetzt war, ist es danach vielleicht richtig. 
Und wenn nicht, geben die dann noch vorhandenen Fehlerfaktoren ggf 
weitere Hinweise, wo der Fehler liegt.

von Karl H. (kbuchegg)


Lesenswert?

foo schrieb:
> Das letzte, was ich vorm Bett prüfen würde, ist, welche Frequenz
> rauskommt, wenn man das nochmal flasht und CKDIV8 setzt. Und dann,
> welche rauskommt, wenn man danach CKDIV8 wieder rausnimmt.

Das erste was ich prfen würde ist, ob ein _delay_ms(1000) auch wirklich 
ca. 1 Sekunde lang dauert, bei einem F_CPU von 16000000.
Das ist der beste Beweis, ob der µC auf 16Mhz läuft oder nicht.

Ehe ich das nicht gecheckt habe, mach ich doch gar nicht erst mit Timern 
weiter und such mir einen Wolf in der Konfiguration.

von Karl H. (kbuchegg)


Lesenswert?

Das hier
1
TCCR0B |= (1 << CS20);
2
// set prescaler to 8 and starts PWM
macht alles mögliche, aber sicher keinen Prescaler von 8

Schon alleine deshalb, weil die Bezeichnung CS20 zum Timer 2 gehört und 
nicht zum Timer 0.

von Martin L. (martin_l795)


Lesenswert?

S. Landolt schrieb:
> Kann man in C nicht noch 'F_CPU' oder so was ähnliches definieren?

Ja, aber das hat m.E. nur Auswirkungen auf "taktzählende" Routinen wie 
ein paar _delay... usw. Funktionen.

von Route_66 H. (route_66)


Lesenswert?

Karl H. schrieb:
> Schon alleine deshalb, weil die Bezeichnung CS20 zum Timer 2 gehört und
> nicht zum Timer 0.

Ist "CS20" nicht einfach eine andere Schreibweise für "0"???

von Thomas E. (thomase)


Lesenswert?

Route 6. schrieb:
> Ist "CS20" nicht einfach eine andere Schreibweise für "0"???

Nein, das ist eine Definition.
1
#define CS20 0

Genau so ist auch das CS00, das dahin gehört definiert:
1
#define CS00 0

Das ist jetzt aber nicht die Pedanterie eines Oberkorinthenkackers, 
sondern ein Hinweis auf mangelnde Sorgfalt und Copy&Paste ohne Sinn und 
Verstand. An dieser Stelle spielt das zufällig keine Rolle. Wer es aber 
bei diesen paar Zeilen Code nicht richtig hinkriegt, dem kann man 
durchaus zutrauen, dass an anderer Stelle ebensolche Böcke eingebaut 
sind, die nicht zufällig funktionieren.

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Thomas E. schrieb:

> sondern ein Hinweis auf mangelnde Sorgfalt und Copy&Paste ohne Sinn und
> Verstand. An dieser Stelle spielt das zufällig keine Rolle.

Es spielt insofern eine Rolle, weil das beim Timer 0 keinen Vorteiler 
von 8 ergibt. Weder so noch so.

Was, wie du richtig anmerkst, auch für mich ein Hinweis darauf ist, dass 
hier wieder mal per Copy&Paste programmiert wird.
Wenn Bezeichnungen nicht zusammenpassen und Kommentare falsch sind, 
werde ich stutzig.

von X. Y. (elektro_henkler)


Lesenswert?

1
/*
2
 * PWM_Test.c
3
 *
4
 * Created: 26.06.2015 21:16:01
5
 *  Author: x.y.
6
 */ 
7
#define F_CPU 16000000UL // 16 MHz
8
#include <util/delay.h>
9
#include <avr/io.h>
10
11
12
int main(void)
13
{
14
  DDRD |= (1 << DDD6);
15
  
16
17
  OCR0A = 1;
18
  
19
  int x = 100;
20
  TCCR0A |= 10000011;
21
  TCCR0B |= 00000001;
22
23
  
24
  while (1)
25
  {
26
    
27
    _delay_ms(1000);
28
    
29
    OCR0A = x;
30
    
31
    
32
  }
33
  return 0;
34
}

hat sich erledigt. keine ahnung was es war aber jetzt wo ich es ohne 
bootloader vom arduino gemacht habe sondern es  im atmel studio gemacht 
habe hat es geklappt

von X. Y. (elektro_henkler)


Lesenswert?


von foo (Gast)


Lesenswert?

X. Y. schrieb:
>   TCCR0A |= 10000011;
>   TCCR0B |= 00000001;

Tut nicht das, was du glaubst, was es tut.

Binärkonstanten werden mit 0b vorne dran angegeben (0b10000011).

(Unabhängig davon, dass es i.A. besser lesbar ist wenn man die 
vorhandenen Defines verwendet.)

von X. Y. (elektro_henkler)


Lesenswert?

foo schrieb:
> X. Y. schrieb:
>>   TCCR0A |= 10000011;
>>   TCCR0B |= 00000001;
>
> Tut nicht das, was du glaubst, was es tut.
>
> Binärkonstanten werden mit 0b vorne dran angegeben (0b10000011).
>
> (Unabhängig davon, dass es i.A. besser lesbar ist wenn man die
> vorhandenen Defines verwendet.)

also er tut zz genau das was ich will.

ja werde ich gleich noch ergänzen. aber so weiß ich schonmal, dass es im 
Grunde funzt. ich habe direkt mein oszi dran, deswegen weiß ich das es 
funzt.

von foo (Gast)


Lesenswert?

X. Y. schrieb:
> also er tut zz genau das was ich will.

Das wird als Dezimalzahl interpretiert. Da in das Register nur 8 Bit 
passen werden nur die untersten 8 Bit davon genommen. Du hättest auch 
TCCR0A |= 131 schreiben können.

Dass diese untersten 8 Bit nun rein zufällig 0b10001011 entsprechen 
und es deshalb das selbe Ergebnis bringt (bei den aktuellen Modellen ist 
das vierte Bit noch unbenutzt) heißt nicht dass der Code so korrekt ist.

Würdest du da z.B. 10100011 schreiben (warum auch immer) dann wären die 
letzten 8 Bits davon 0b0101011 ... wie du siehst, passt es manchmal 
zufällig, manchmal nicht.

Das gleiche gilt natürlich auch für 00000001 (hier passt es aus 
naheliegenderen Gründen), beachte hier, dass Zahlen mit führenden Nullen 
in C oktal interpretiert werden (d.h. 010 = 8!)

von X. Y. (elektro_henkler)


Lesenswert?

foo schrieb:
> X. Y. schrieb:
>> also er tut zz genau das was ich will.
>
> Das wird als Dezimalzahl interpretiert. Da in das Register nur 8 Bit
> passen werden nur die untersten 8 Bit davon genommen. Du hättest auch
> TCCR0A |= 131 schreiben können.
>
> Dass diese untersten 8 Bit nun rein zufällig 0b10001011 entsprechen
> und es deshalb das selbe Ergebnis bringt (bei den aktuellen Modellen ist
> das vierte Bit noch unbenutzt) heißt nicht dass der Code so korrekt ist.
>
> Würdest du da z.B. 10100011 schreiben (warum auch immer) dann wären die
> letzten 8 Bits davon 0b0101011 ... wie du siehst, passt es manchmal
> zufällig, manchmal nicht.
>
> Das gleiche gilt natürlich auch für 00000001 (hier passt es aus
> naheliegenderen Gründen), beachte hier, dass Zahlen mit führenden Nullen
> in C oktal interpretiert werden (d.h. 010 = 8!)

ok, habe es angepasst :)

hm was jetzt noch mein problem ist, wahrscheinlich wieder simpel, ist 
das ich gerne timer 0 und timer 2 mit gleichen config laufen lassen 
will. was ich noch nicht ganz verstehe wie ich die timer ausgänge extern 
zuweise. es gibt ja für jeden timer 2 externe pins.

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

für die Ausgabe an den externen Pins hast du im A-Register des Timers 
für jeden Ausgang zwei Bits COMnA0/1 für Pin OCnA und COMnB0/1 für OCnB. 
Das Datenblatt enthält alle dafür notwendigen Infos.

Sascha

von Rudolph R. (rudolph)


Lesenswert?

X. Y. schrieb:
> keine ahnung was es war aber jetzt wo ich es ohne
> bootloader vom arduino gemacht habe sondern es  im atmel studio gemacht
> habe hat es geklappt

Wenn man Read-Modify-Write Zugriffe macht dann wird der Inhalt nicht 
unbedingt komplett überschrieben.

Damit:
1
  DDRD |= (1 << DDD6);
2
  TCCR0A |= 0b10000011;
3
  TCCR0B |= 0b00000001;

Werden lediglich die angebenen 1-Bits in den Registern auf 1 gesetzt,
die im Register bereits vorhandenen 1-Bits werden aber nicht auf Null 
gesetzt.

Wenn der Bootloader die Register bereits anfasst, die also nicht mehr 
auf Default-Null sind, dann kann es sein, dass dabei was ganz anderes 
raus kommt.

Im Zweifel einfach richtig überschreiben:
1
  DDRD = (1 << DDD6);

von Thomas E. (thomase)


Lesenswert?

Rudolph R. schrieb:
> Wenn der Bootloader die Register bereits anfasst, die also nicht mehr
> auf Default-Null sind, dann kann es sein, dass dabei was ganz anderes
> raus kommt.

Dann ist aber in erster Linie der Bootloader Scheisse.

Das Programm muss von einem Bootloader überhaupt nichts wissen. Wenn der 
fertig ist, hat er den Controller besenrein zu übergeben.

mfg.

von Rudolph R. (rudolph)


Lesenswert?

Thomas E. schrieb:
> Das Programm muss von einem Bootloader überhaupt nichts wissen. Wenn der
> fertig ist, hat er den Controller besenrein zu übergeben.

Dem kann ich nur zustimmen, ich wollte nur eine mögliche Erklärung für 
das Verhalten mit und ohne Bootloader liefern.

Generell ist es aber auch nicht die schlechteste Idee auf sinnlose 
Read-Modify-Write zu verzichten und einfach nur zu schreiben wo es 
angebracht ist.

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.