Ich hab zwei kleine Fragen zum Compare-Match-Interrupt des
Hi-Speed-Timers 4 (mit dem Overflow-Interrupt sieht es übrigens genauso
aus) und zwar hab ich da heute den ganzen Tag probiert aber es klappt
nicht wie ich mir das vorstelle (und mit Datenblatt/Google bin ich auch
nicht weiter gekommen). Unten seht ihr mein Programm, ich benutze als
Testboard ein Arduino Leonardo. Fuses sind wie beim Leonardo-Board
eingestellt. PWM klappt übrigens hervorragend, daher weiß ich, dass der
Timer zumindest läuft (beachte 2. Frage).
1. Anhand meines Tests weiß ich, dass die ISR nicht angesprungen wird
denn PB5 toggelt nicht so wie ich will (mit 50 kHz), aber was habe ich
hier vergessen zu konfigurieren? Es geht mir hierbei nicht darum einen
OC4x-Pin anzusteuern.
2. Die while-Schleife, in der ich das PLOCK Polle (soll man lt.
Datenblatt) funktioniert auch nicht (egal ob auf 1 oder 0 geprüft).
Nehme ich, wie es unten steht, die Zeile 27 rein bleibt das Programm da
hängen. Kommentiere ich es aus, dann läuft auch das Programm weiter.
Verstehe ich irgendwie auch nicht wirklich. Sieht jemand was da das
Problem ist?
Es sind wahrscheinlich völlig lächerliche Probleme aber ich hab nen
Knoten im Kopf und sehe das Problem nicht. Das Programm unten liefert
mir ein ca. 800 Hz Signal, sollte so aber eigentlich ein 50 kHz Signal
generieren.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
voidsetCompareValue(uint8_tcompareValue){
5
uint8_tsreg=SREG;
6
cli();
7
TC4H=(compareValue>>8);
8
OCR4A=(compareValue&0xff);
9
SREG=sreg;
10
}
11
12
voidmain(void){
13
// Testpin sei PB5
14
DDRB|=(1<<PB5);
15
16
//PLL einstellen
17
// uC laeuft mit 16MHz, PINDIV daher setzen (Kapitel 6.11.5)
18
PLLCSR=(1<<PINDIV);
19
20
// PLL fuer Timer einstellen (Kapitel 15.3.1)
21
// Enable PLL
22
PLLCSR=(1<<PLLE);
23
// wait 100us for stabilize PLL
24
_delay_us(100);
25
// pull PLOCK-Bit until it is set
26
while(!(PLLCSR&(1<<PLOCK)));
27
// Postscaler auf 1, PLL fuer 72 MHz konfigurieren
Hallo,
Timer 4 kann nur bis 64MHz, egal ob die PLL noch höher takten könnte.
Das muss man bei der gesamten Kette von Einstellungen beachten.
Desweiteren verkraftet die PLL Eingangsseitig nur max. 8MHz.
Das heißt du musst die 16MHz CPU Takt am Eingang der PLL erstmal
halbieren.
Im Manual unter 6.9 gibts den Aufbau der PLL zu sehen.
Das Ergebnis was hinten an clkTMR rauskommt bekommt der Timer 4 zu
sehen.
PLOCK brauchte meinem Verständnis nach nicht. Das delay damit eigentlich
auch nicht. Sollte nur für PLOCK Nutzung wichtig sein.
Vorschlag, probier mal
1
/*
2
PDIV3 .... PLL Output Frequency 96MHz
3
PDIV1 .... PLL Output Frequency 96MHz
4
PLLTM1 ... Postscaler Factor 1,5 for High Speed Timer
Veit D. schrieb:> Das heißt du musst die 16MHz CPU Takt am Eingang der PLL erstmal> halbieren.
Das macht das PINDIV-bit (Zeile 18) ;)
Veit D. schrieb:> PLOCK brauchte meinem Verständnis nach nicht. Das delay damit eigentlich> auch nicht. Sollte nur für PLOCK Nutzung wichtig sein.
Ich verstand das so, dass man das PLOCK pollen soll, sodass man sicher
sein kann, dass die PLL auch mit der Wunschfrequenz stabil läuft.
Bräuchte ich in der aktuellen Anwendung nicht, richtig, aber es wäre
halt schön wenn es funktionieren würde.
Das mit den 64 MHz ist richtig, ich hab mal die PLL auf 48 MHz
umgestellt. Das sah zunächst gut aus (SHS00001.BMP). Dann hab ich
versucht den Pin nicht mehr zu toggeln sondern im Compare-Interrupt auf
0 zu setzen und im Overflow-Interrupt auf 1 zu setzen und dann kam das
raus, was hier in SHS00002.BMP zu sehen ist.
aktuelles Programm
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<util/delay.h>
4
5
voidsetCompareValue(uint8_tcompareValue){
6
uint8_tsreg=SREG;
7
cli();
8
TC4H=(compareValue>>8);
9
OCR4A=(unsignedchar)compareValue;
10
SREG=sreg;
11
}
12
13
intmain(void){
14
// Testpin sei PB5
15
DDRB|=(1<<PB5);
16
17
//PLL einstellen
18
// uC laeuft mit 16MHz, PINDIV daher setzen (Kapitel 6.11.5)
19
PLLCSR=(1<<PINDIV);
20
21
// PLL fuer Timer einstellen (Kapitel 15.3.1)
22
// Enable PLL
23
PLLCSR=(1<<PLLE);
24
// wait 100us for stabilize PLL
25
_delay_us(100);
26
// pull PLOCK-Bit until it is set
27
while(!(PLLCSR&(1<<PLOCK)));
28
// Postscaler auf 1, PLL fuer 72 MHz konfigurieren
Veit D. schrieb:> was ist der Unterschied zwischen unseren Konfigurationen von PLLCSR?
Ich hab ehrlich gesagt keine Ahnung wo jetzt der | abgeblieben ist. Im
Quellcode ist er drin in Zeile 23, vgl. Screenshot ;)
Veit D. schrieb:> Ich denke danach sollte es laufen.
Ich denke ja eigentlich auch, dass es laufen sollte aber das tut es eben
nicht. Und das ist ja das, was mich verwirrt. ;)
Hallo,
dann hilft nur noch radikaler Schritt zurück.
Was macht der Code?
Wenn das passt, dann baust du in diesen! Code das PLL ein.
Erstmal ohne weiteren Pin. Nur dem Timer den PLL zuführen.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<util/delay.h>
4
5
voidsetCompareValue(constuint16_tcompareValue)
6
{
7
TC4H=(compareValue>>8);
8
OCR4A=(compareValue&0xFF);
9
}
10
11
intmain(void)
12
{
13
DDRB|=(1<<PB5);// Testpin sei PB5
14
15
// Timer 4 Einstellungen
16
// TOP-Value Timer einstellen
17
TC4H=720>>8;
18
OCR4C=720&0xFF;// 11,1kHz
19
20
setCompareValue(180);// 25% Duty Cycle
21
TIMSK4=(1<<OCIE4A);// Compare Match Interrupt einschalten
Veit D. schrieb:> Was macht der Code?
ein 50% Duty-Cycle.
Ich hab aber auch meinen Fehler entdeckt und war nicht der einzige mit
Tomaten auf den Augen. Schau dir mal Zeile 6 meiner Variante an und
überleg mal was da falsch ist für das Setzen eines 10 bit Registers. Ist
mir grade aufgefallen...oh man, was für ein dämlicher Fehler...
Vielen Dank aber für deine Hilfe.