Hallo liebe Freunde,
ich versuche die letzen Tage den xmega256A zu programieren, der µC
soll ein digitales Signal messen. Daher muss die Zeit zwischen zwei
fallenden Flanken gemessen werden, und dann diese Messungen auswerten.
Alles muss mithilfe von Interrupt gemacht werden.
Mein Problem: Die Interrupt Serviceroutine wird nie ausgelöst, ich habe
bestimmt fehler bei der Initialisierung. Kann jemand bitte mir den Code
gucken vielleicht findet man den Fehler, ich sitze seit ein paar Tage
und habe das Problem leider nicht gelöst.
Das Eingangssignal liegt an PIN3 PORTC.
1
#include<avr/io.h>
2
#include"avr/interrupt.h"
3
#include<stdint.h>
4
#include<util/delay.h>
5
#include"avr_compiler.h"
6
#include"function.h"
7
#include"UartHandler.h"
8
#include"usart_driver.h"
9
10
11
/***********************************/
12
13
voidfunct_port_init(void)
14
{
15
16
/* Port C - digital I/O */
17
DIGI_PORT.DIRSET=DIGI_PIN1;// Port C Pin 1 digital I/O 1 as output PIN7
18
DIGI_PORT.DIRCLR=DIGI_PIN2;// Port C Pin 3 digital I/O 2 as input PIN9
19
DIGI_PORT.DIRSET=OPTO_PIN;// Port C Pin 0 opto-coupler as digital output
>> Daher muss die Zeit zwischen zwei
fallenden Flanken gemessen werden, und dann diese Messungen auswerten.
Alles muss mithilfe von Interrupt gemacht werden.
1.) das mit Interupts zu machen ist idiotisch! (Hast du eine Ahnung
warum?)
2.) Das macht man beim Xmega:
mit Timer + Frequency-Capture <= Eventkanal <= Portpin
PS:
Du hast vergessen, global Interrupts zu enablen!
=> sei() !
PPS: Wenn 'was nicht funktioniert, schau im Debugger unter I/O nach.
Da muss das Flag gesetzt sein.
Bei "Prozessor" siehst du dann sicher, dass "I" noch nicht enabled ist.
der Interrupt für xmega256A3 wird nicht ausgelöst schrieb im Beitrag
Alexxx schrieb:> PS:> Du hast vergessen, global Interrupts zu enablen!> => sei() !
Lesen kannst Du schon?
#4272641:
> int main (void)> {>> sei();> funct_clock_init_PLL_60M();
Danke Alex für die Antwort,
mein Signal ist eine Impulsfolge, die zeit zwischen zwei fallenden
Flanken liegt in µs Bereich. Außerdem muss jede Periode gemessen und
gleichzeitig mit einem anderen Wert verglichen. Daher ist nutze ich
Interrupt. Es könnte sein, dass die Zeit zum Messen länger dauert als
die nächste fallende Flanke kommt, und somit wird eine Periode verpasst.
wo muss ich die globale interrupts enablen ??
Danke im Voraus.
Ahmed M. schrieb:> Danke Alex für die Antwort,>> mein Signal ist eine Impulsfolge, die zeit zwischen zwei fallenden> Flanken liegt in µs Bereich. Außerdem muss jede Periode gemessen und> gleichzeitig mit einem anderen Wert verglichen. Daher ist nutze ich> Interrupt.
Interrupt ist schon ok.
Aber nicht mit selber die Flanke erkennen.
Dazu benutzt man einen Timer, dem man den Input Capture aktiviert.
Denn genau dafür ist er gedacht: um die Zeit zwischen 2 Flanken zu
messen.
> Es könnte sein, dass die Zeit zum Messen länger dauert als> die nächste fallende Flanke kommt
was jetzt?
sind die Flanken im µs Bereich oder sind sie so lang, dass der der Timer
'überläuft'?
(denn in Wirklichkeit setzt man auch den Timer nicht dauernd zurück. Man
lässt ihn laufen. Zeit = Endstand - Anfangsstand)
Hallo Karl Heinz,
Timer habe ich schon in meinem Code, aber ich weiß es nicht ob es so
richtig konfiguiert ist oder doch nicht.
Im Prinzip ist die Zeit zwischen zwei fallenden Flanken in meinem Fall
in µs Bereich. Der Counter muss bei jeder Fallenden Flanke zurückgesetzt
werden (der Counter-Wert muss in array gespeichert werden, bevor er
zurückgesetzt wird).
Irgendwie wird die fallende Flanke nicht gefunden, obwohl das digitale
Eingangssignal im Oscilloskop zu sehen ist.
Gruß
Ahmed M. schrieb:> Im Prinzip ist die Zeit zwischen zwei fallenden Flanken in meinem Fall> in µs Bereich. Der Counter muss bei jeder Fallenden Flanke zurückgesetzt> werden
nein, muss er nicht.
> (der Counter-Wert muss in array gespeichert werden, bevor er> zurückgesetzt wird).
Der Zeitwert ergibt sich aus Endstand minus Anfangsstand.
Wenn ein Skifahrer um 12:35:12 oben wegfährt und um 12:35:19 im Ziel
ankommt, dann war er 7 Sekunden unterwegs. Das kannst du mit deiner ganz
normalen Armbanduhr stoppen, du brauchst keine Stoppuhr dazu, die du
daernd starten und stoppen musst.
Und genau das willst du mit deinem Timer auch machen. Du willst ihn
ständig laufen haben. Der Input Capture Mode sichert eigenständig bei
der Flanke den aktuellen Timerwert in einem speziellen Register und löst
dann einen Interrupt aus. In diesem Interrupt holst du dir gemütlich den
Wert aus dem Register und ziehst von ihm den Wert vom letzten Interrupt
ab. Und schon hast du die Anzahl an Timertakten die seit der letzten
Flanke vergangen sind. Und zwar hast du die auf den Timertakt genau ohne
dass du irgendwo etwas hättest starten oder stoppen müssen oder
irgendwelche Flanken auswerten müssen. etc.
Der Timer Input Capture ist dein Freund. Genau dafür, um die Zeit
zwischen 2 Flanken zu messen, ist er perfekt geeignet. Genau dafür wurde
er gemacht.
Hallo Karl Heinz,
klar verstehe ich Zeit = Endstand - Anfangsstand, das Problem
jetzt in meiner timer Funktion:
void funct_timer2_init(void)
{
TCD1.CTRLA = TC_CLKSEL_DIV1_gc;
TCD1.CTRLB = TC_WGMODE_NORMAL_gc;
TCD1.INTCTRLA = TC_OVFINTLVL_HI_gc;
TCD1.PER= 0xFFF;
}
wie muss ich noch diese Funktion erweitern damit ich den Timer Input
Capture hinkriege.
Ich bin leider neu beim Assembler Programmieren.
Gruß
Ahmed M. schrieb:> Hallo Karl Heinz,>>> klar verstehe ich Zeit = Endstand - Anfangsstand, das Problem> jetzt in meiner timer Funktion:>>> void funct_timer2_init(void)> {> TCD1.CTRLA = TC_CLKSEL_DIV1_gc;> TCD1.CTRLB = TC_WGMODE_NORMAL_gc;> TCD1.INTCTRLA = TC_OVFINTLVL_HI_gc;> TCD1.PER= 0xFFF;> }>> wie muss ich noch diese Funktion erweitern damit ich den Timer Input> Capture hinkriege.
AUch wenn ich keine XMega benutze, bin ich sicher, die Antwort findet
sich im Datenblatt zu deinem XMega.
> Ich bin leider neu beim Assembler Programmieren.
brauchst du auch nicht.
Du brauchst nur im Datenblatt beim Timer nachsehen, welche Bits in
welchem Register zu setzen sind. Was anderes machst du ja jetzt auch
nicht. Nur eben andere Bits.
Assembler braucht dazu kein Mensch können. Auch weil die Atmel
Datenblätter sehr gut gemacht sind.
OK, sei() ist schon da!
Aber was soll/macht die "funct_clock_init_PLL_60M(); "??
Wie hoch ist die Fsys?
Man kann zwar die PLL mit 60MHz laufen lassen, muss aber dann Teiler für
den Sytemclock einstellen. Xmega (CPU & Timer!) können nur max. 32MHz.
(Das HIRES-Zeug ist nur ein "Schummelmodus")
Es hat anscheinend jemand geschafft ihn mit 40 (48??)MHz zu übertakten.
Bei Fsys= 60MHz macht er aber nur noch komische Sachen.
Alexxx schrieb:> OK, sei() ist schon da!>> Aber was soll/macht die "funct_clock_init_PLL_60M(); "??> Wie hoch ist die Fsys?>> Man kann zwar die PLL mit 60MHz laufen lassen, muss aber dann Teiler für> den Sytemclock einstellen. Xmega (CPU & Timer!) können nur max. 32MHz.> (Das HIRES-Zeug ist nur ein "Schummelmodus")> Es hat anscheinend jemand geschafft ihn mit 40 (48??)MHz zu übertakten.> Bei Fsys= 60MHz macht er aber nur noch komische Sachen.
hallo Alex,
bei 32 Mhz funktionierte der Interrupt auch nicht.
irgendwie die fallende flanke wird nicht gefunden.
Gruß
> AUch wenn ich keine XMega benutze, bin ich sicher, die Antwort findet> sich im Datenblatt zu deinem XMega.>
Im Datenblatt habe ich nicht viel über Timer Input capture gefunden,
hier was auf dem Datenblatt steht:
"Selecting the input capture event action makes the enabled capture
channel perform an input capture on an event. The
interrupt flags will be set and indicate that there is a valid capture
result in the corresponding CC register. At the same
time, the buffer valid flags indicate valid data in the buffer
registers.
The counter will continuously count from BOTTOM to TOP, and then restart
at BOTTOM, as shown in Figure 14-11."
> brauchst du auch nicht.> Du brauchst nur im Datenblatt beim Timer nachsehen, welche Bits in> welchem Register zu setzen sind. Was anderes machst du ja jetzt auch> nicht. Nur eben andere Bits.> Assembler braucht dazu kein Mensch können. Auch weil die Atmel> Datenblätter sehr gut gemacht sind.
Ja aber Beispiele finde ich leider nicht :(
Ahmed M. schrieb:> Im Datenblatt habe ich nicht viel über Timer Input capture gefunden,
Das steht auch im xmega A Manual und nicht im datasheet.
Das Manual gilt für alle xmega A1 bis A4.
Veit D. schrieb:> Hallo,>> serielle Ausgaben haben auch in Interrupts nichts zu suchen. Ein ISR muß> nur das notwendigste machen. Der Rest wieder in der main().
Hallo,
ich habe die serielle Ausgabe nur geschrieben, um bei der Termite zu
gucken, ob überhaupt die interrupt ausgelöst wird oder nicht.
Peter M. schrieb:> Ahmed M. schrieb:>> Im Datenblatt habe ich nicht viel über Timer Input capture gefunden,>> Das steht auch im xmega A Manual und nicht im datasheet.> Das Manual gilt für alle xmega A1 bis A4.
ja das meinte ich auch das Manuel von Atmel, findet man nicht viel
Ahmed M. schrieb:> findet man nicht viel
14.7 Capture Channel, Input Capture, Frequency Capture, Pulse Width
Capture
Mir ist das ausführlich genug beschrieben.
Wenn Dir das nicht reichen sollte, gibt es bestimmt auch noch eine
Application Note bei Atmel.