Hallo,
für das generieren von mehreren festen Testfrequenzen (25 Hz, 50 Hz, 100
Hz...) über einen ATtiny13A muss ich den Prescaler bemühen, damit ich
möglichst nah an der Zielfrequenz dran bin.
Leider funktioniert das neu setzen des Prescalers in TCCR0B innerhalb
von einer Schleife in main() nicht, wie erhofft; der erste Counter läuft
wie erwartet, ab der nächsten Änderung (im Code unten setzen des
Prescalers auf 64) sind die Ergebnisse nicht mehr determinierbar.
Ich vermute, das ich irgendeine Initialisierungsreihenfolge übersehen
habe, habt Ihr dazu einen Tip? Prescaler Artefacts sind für eine
Frequenzerzeugung wie unten kein echtes Problem, da sie nur den ersten
Durchlauf von OCR0A betreffen, korrekt?
Danke,
Adrian
1
//
2
// *** ATTiny13A with 1.2 MHz as shipped ***
3
//
4
#define F_CPU 1200000UL
5
6
#include<util/delay.h>
7
#include<avr/power.h>
8
#include<avr/interrupt.h>
9
#define SEQ_DELAY 5000
10
11
intmain(void)
12
{
13
14
// set PB0 as output port
15
DDRB|=(1<<PB0);
16
17
//set CTC Mode
18
TCCR0A|=(1<<WGM01);
19
20
// set Timer/Counter0 Output Compare Match A Interrupt Enable
>für das generieren von mehreren festen Testfrequenzen (25 Hz, 50 Hz, 100>Hz...) über einen ATtiny13A muss ich den Prescaler bemühen, damit ich>möglichst nah an der Zielfrequenz dran bin.
Versteh ich nicht. 1000 Hz kannst Du genau [*] generieren (Timer Mode =
CTC, Prescaler = 8, OC-Wert = 150 bzw. 75) und aus 1000 Hz kannst Du 500
Hz, 250 Hz, 200 Hz, 125 Hz, 100 Hz, 50 Hz, 40 Hz, 25 Hz, 20 Hz, 10 Hz
und noch viele andere Frequenzen problemlos per Softwareteilung
ableiten.
[*] Wobei "genau" bei Verwendung des internen RC-Oszillators als
Taktquelle relativ ist.
Jürgen, vielen Dank! Peinlicher Fehler, alle drei Bits gesetzt ist nicht
dokumentiert, kein Wunder daß das nicht funktioniert.
Gastofatz, ich hab bisher der Einfachheit halber auf eine
Softwareteilung verzichtet. Bis zu 2-3% Fehlerrate reicht bei meiner
Anwendung, und das bekomme ich mit zwei Teilern (64 und 256) problemlos
hin. Mit dem internen RC Oszillator schwankt die Ausgabe bei
Zimmertemperatur um 0.3-0.5%, da kann ich auch gut mit leben.
Vielen Dank für die Unterstützung,
Adrian
Dann habe ich den falschen Ansatz im Kopf, erklär mal bitte kurz den
Ansatz. Ich fand den CTC Timer schon recht einfach, aber wenn es noch
einfacher geht... ;)
Danke!
Der delay da drinnen ist jetzt aber nicht dein Ernst. Oder?
Was glaubst du, wie das die 'Genauigkeit' deines
_delay_ms(SEQ_DELAY);
in der Hauptschleife beeinflussen wird :-)
Grrrr:
1
// Enable Interrupts again
2
SREG|=(1<<7);
3
}
Lass das Interrupt Flag im SREG in Ruhe!
Interrupts sind in einer ISR automatisch ausgeschaltet und werden nach
Beeindigung der ISR automatisch wieder eingeschaltet. Mit deiner Aktion
da oben bettelst du praktisch um Schwierigkeiten.
A. L. schrieb:
> Dann habe ich den falschen Ansatz im Kopf, erklär mal bitte kurz den> Ansatz. Ich fand den CTC Timer schon recht einfach, aber wenn es noch> einfacher geht... ;)>
Dazu müsste man erst mal genau wissen, was eigentlich das Ziel ist.
Willst du hintereinander an einem Pin 2 verschiedene Frequenzen jeweils
eine bestimmte Zeitdauer ausgeben? (zumindest sieht es so aus)
Nebenschauplatz, ist auch nicht mein Ernst, wie Du schon erraten hat :)
Danke für den SREG Tip, ich war der Annahme, daß ich am Ende der ISR die
Interrupts wieder aktivieren muss.
SEQ_DELAY soll die jeweils aktuelle Frequenz ein paar Sekunden für die
Ansicht am Scope ausgeben. Das Programm oben ist nur ein schnell
reingehackter Test der Idee, in ein Tachoadapter Projekt noch eine
Kalibrierfunktion für den Tacho mit einzubauen.
Folgender Codeschnipsel möge das Prinzip der Softwareteilung
verdeutlichen:
1
t=t+1;
2
3
IF(t==n)
4
{
5
t=0;
6
a=~a;
7
<PortpingemaessaaufLoderHsetzen>
8
}
Diese Routine rufst Du in Deinem Fall 2000 mal pro Sekunde auf. Um die
Toggle-Frequenz f des Portpins zu ändern, musst Du nur den Wert von n
passend setzen:
n = 1 --> f = 1000 Hz
n = 2 --> f = 500 Hz
n = 4 --> f = 250 Hz
n = 5 --> f = 200 Hz
n = 10 --> f = 100 Hz
n = 20 --> f = 50 Hz
n = 40 --> f = 25 Hz
n = 50 --> f = 20 Hz
n = 100 --> f = 10 Hz
n = 200 --> f = 5 Hz
Danke für die Erklärung, ich rechne am Wochenende mal durch, mit welchen
Hardware/Softwareteilern ich am besten auf meine Zielfrequenzen komme.
Und bringe den Code mal in eine saubere Form, damit Karl Heinz keine
Zustände bekommt :)