Forum: Compiler & IDEs Unterschied zw. ICP und INT0


von Holger (Gast)


Lesenswert?

was ist eigentlich der entscheidende Unterschied zwischen dem ICP und 
z.b. dem INT0 eines ATmega16/32.
Ich kann ja beide so einstellen, dass sie auf eine negative bzw. eine 
positive Flanke reagieren und beide sollten mir einen Interrupt 
auslösen.

ist meine Init richtig?
Int0:
1
...
2
  GIMSK = (1 << INT0);                 // Interrupt von INT0 aktivieren
3
  MCUCR = (1 << ISC01) | (1 << ISC00); // Interrupt0 bei steigender Flanke
4
  sei();
5
....
6
ISR(INT0_vect)
7
{
8
i++;
9
}

bzw für ICP:
1
...
2
   TIMSK |= (1<<TICIE1);  // Input Capture Interrupt aktivieren
3
   TCCR1B |= (1<<ICES1);  // steigende Flanke für ICP Interrupt
4
   sei();
5
...
6
ISR(TIMER1_CAPT_vect)   //Interrupt bei Overflow Timer1
7
{
8
   i++;
9
}

von isr (Gast)


Lesenswert?

Ganz einfach der INT0 löst einfach nur einen IRQ aus, während die ICP 
auch noch einen Timestamp erzeugt.
Näheres im Datenblatt :-P

von Holger (Gast)


Lesenswert?

ok, danke schon mal, aber ist die Init zum ICP denn richtig (Int0 
funktioniert wunderbar, i wird hochgezählt)
beim ICP passiert eher nicht das erwartete
es ist eher wie ein berührungssensor, wenn ich die leitung von PD6 
anfasse zählt er lustig munter hoch, lege ich aber Referenzspannung 
(also 1 Signal) an, passiert meist gar nichts, wobei er gerade da 
hochzählen sollte (so wie der Int0 es ja auch macht)

mal der ganze code:
1
uint16_t i=0;
2
3
void wait (uint16_t zeit) //zeit: wartezeit in ms (0 bis 65536)
4
{
5
   uint16_t i;
6
   for(i=0;i<zeit;i++) _delay_ms(1);
7
} 
8
9
int main (void)
10
{
11
   char s[10];
12
13
   DDRD &= ~( 1 << PD6 );  // PD6 als Eingang
14
   TIMSK |= (1<<TICIE1);  // Input Capture Interrupt aktivieren
15
   TCCR1B |= (1<<ICES1);  // steigende Flanke für ICP Interrupt
16
17
   lcd_init(LCD_DISP_ON);
18
   lcd_clrscr();
19
   lcd_puts("ICP\n");
20
   sei();      //Interrupts aktivieren 
21
22
23
while(1)
24
{ wait(500);
25
  lcd_clrscr();
26
  lcd_puts(itoa(i,s,10));  
27
}   
28
           
29
}
30
31
32
ISR(TIMER1_CAPT_vect)
33
{
34
   i++;
35
}

von Rahul D. (rahul)


Lesenswert?

>lege ich aber Referenzspannung (also 1 Signal) an, passiert meist gar
>nichts, wobei er gerade da hochzählen sollte (so wie der Int0 es ja auch
>macht)

ICP reagiert auf Flanken (die kann man einstellen, und so wie ich dein 
Programm verstehe sollte es auch funktionieren).
Du scheinst aber ein Verständinsproblem zu haben:
Du willst scheinbar die Dauer eines konstanten Signals messen. Das geht 
nicht mit dem ICP, wenn man die Flankenrichtung nicht während des 
Ereignisses ändert.
Mit ICP kann man hervorragend Periodendauern messen: Die 
Detektions-Flanke auf fallend oder steigend stellen und die Differenz 
zwischen zwei Zeitmarken, die man aus dem ICP-Register auslesen kann 
(die "ältere" muß man in einer 16-Bit-Variablen zwischenspeichern...). 
Dann hat man die Periodendauer eines Signals.
Um nur den Puls einer Periode zu messen (z.B. PWM-Auswertung durch den 
Controller), muß man die Flankenrichtung nach der ersten Detektion 
umschalten , den Zeitstempel sicher und bei der nächsten Flanke beides 
wieder machen, und die Differenz bilden. Ein gutes Beispiel dafür ist 
die Auswertung von Modellbauservo-Signalen, die einen Puls zwischen ca. 
1ms und 2ms haben. Diese Pulsdauer ist proportional zur Servoposition.

Ein sinnvoller Einsatz für einen externen Interrupt fällt mir gerade 
nicht ein, ausser dass darüber mehrere Controller darüber eine 
Kommunikation aufbauen könnten...


Kann aber auch sein, dass ich daneben liege.

von Michael U. (Gast)


Lesenswert?

Hallo,

ich weiß zwar jetzt nicht, was bei Dir Referenzspannung ist, aber auch 
INT0 hat da kein Zählen zu bewirken, wenn er auf steigende Flanke 
programmiert ist. H-Pegl ist nur einmal eine stegende Flanke, dann, wenn 
man ihn anlegt.

Anfassen ist auch mit SIcherheit keine sinnvolle Fuinktionsprobe dafür, 
die Eingänge des AVR sind hochohmig genug, um jede Störung und z.B. 50Hz 
Netzbrummen vom Finger einzufangen...

Selbst ein Taster ist ungeeignet, wenn die Software nicht entprellt, 
weil der auch bei einem Tastendruck etlich Impulse produziert, bis er 
geschlossen oder geöffnet bleibt.

Gruß aus Berlin
Michael

von Holger (Gast)


Lesenswert?

Ich will nicht die Dauer von "Gleichspannung" messen, ich hab nur zum 
testen ( da ich später Frequenzen messen will) probiert ob i hochgezählt 
wird, wenn ich Vcc anlege und wieder entferne und wieder anlege und...
Halt genau was du gesagt hast --> eine Flanke erzeugen
Bei INT0 klappt das wunderbar, nur halt bei ICP nicht so.
Ich werd mal probieren ein richtiges Signal anzulegen, evtl. klappts ja 
dann.
Komisch ist halt nur, dass es bei INT0 klappt, also dort die "Flanke" 
erkannt wird.

von Holger (Gast)


Lesenswert?

das mit dem "anfassen" war nur eine Nebenerscheinung welche ich 
festgestellt habe, war nicht zum testen

von Johannes M. (johnny-m)


Lesenswert?

Abgesehen davon, dass die Verwendung des Capture Interrupt nicht gerade 
seinem Sinn entspricht, wundert es mich, dass es mit dem INT0 angeblich 
funktioniert, mit dem Capture aber nicht. Ich hätte erwartet, dass 
keiner von beiden wirklich sinnvolle Werte liefert, da die Zählvariable 
i nicht volatile deklariert ist. Ansonsten sollte auch der 
zweckentfremdete Capture-Interrupt seinen Dienst tun...

von Holger (Gast)


Lesenswert?

Ok, mal andere Sache, wenn ich dann die Frequenzmessung machen will und 
mir das erste ICR1 (A) zwischenspeichere und dann beim nächsten 
interrupt auch das zweite (B), wie rechne ich dann die zeit zwischen den 
beiden interrupts aus
rechne ich einfach B-A und hab dann schon die Zeit?
oder lass ich nen timer nebenbei mitlaufen und stoppe qusi die zeit mit?

von Johannes M. (johnny-m)


Lesenswert?

Holger wrote:
> Ok, mal andere Sache, wenn ich dann die Frequenzmessung machen will und
> mir das erste ICR1 (A) zwischenspeichere und dann beim nächsten
> interrupt auch das zweite (B), wie rechne ich dann die zeit zwischen den
> beiden interrupts aus
> rechne ich einfach B-A und hab dann schon die Zeit?
Im Prinzip ja, Du musst nur eventuell in der Zwischenzeit aufgetretene 
Timer-Überläufe mitzählen und dazurechnen.

> oder lass ich nen timer nebenbei mitlaufen und stoppe qusi die zeit mit?
Siehe oben. Wichtig ist nur, dass der Timer auch laufen muss, sonst 
gibts bei jedem Capture das selbe Ergebnis.

von Karl H. (kbuchegg)


Lesenswert?

Holger wrote:
> rechne ich einfach B-A und hab dann schon die Zeit?

Direkt nicht.
Du hast erst mal die Anzahl der Timer Ticks, die der Timer
vom Auftreten einer Flanke bis zum Auftreten der nächsten
Flanke geschafft hat.
Aber: Du weist ja wie schnell der Timer zählt (*)
Wenn er zb. in 1 Sekunde 1000 Ticks macht, dann braucht er
logischerweise für 1 Tick 1 Millisekunde. Und wenn du jetzt
eine Differnz von 534 hast, dann hat er dafür 534 Millisekunden
oder 0.534 Sekunden gebraucht.

(*) Das weist du, weil du ja den Systemtakt kennst und auch
welchen Vorteiler du eingestellt hast.


von Holger (Gast)


Lesenswert?

Ok, das heisst ja dann , wenn ich zb den 16bit Timer nehm mit extern 
16Mhz und nem Prescaler von z.B 256, dann hat mein Timer ne max 
Auflösung von 16µs, also kann ich auch nur max 62,5kHz messen
heist, wenn ich den Prescaler verkleinere, kann ich bei Prescaler 1 max 
16Mhz messen da der Timer mit 62,5ns läuft
Wie sieht das nun aber bei der minimalen Frequenz aus, da zählt der sich 
ja bei einer sehr niedrigen Frequenz dumm und dusselig mit den 
Überläufen.
seh ich das dann richtig, dass ich minimal 65536*62,5µs=4,095ms-->244Hz 
messen kann (die 65536 kommt jetzt wegen z.b einer 16 bit integer 
variablen)

von Johannes M. (johnny-m)


Lesenswert?

Mit nem Prescaler von 1024 kriegste bei 16 MHz einen Überlauf alle 4,19 
s mit einer Zählauflösung von 64 µs... Und wenn Du dann noch ne 
16-Bit-Variable für das Zählen der Überläufe spendierst, kannste drei 
Tage lang auf die nächste Flanke warten!

von Karl H. (kbuchegg)


Lesenswert?

Holger wrote:
> Wie sieht das nun aber bei der minimalen Frequenz aus, da zählt der sich
> ja bei einer sehr niedrigen Frequenz dumm und dusselig mit den
> Überläufen.

Und?
Wenn ein µC etwas gut kann, dann ist das sich dumm und dusselig
zu zählen.
Ausserdem: Dem µC ist doch ansonsten sowieso fad.
Bei einem Überlauf alle ~4 ms kann man noch nicht von
dumm und dusselig reden. Siehs mal so: 65500 Takte
gibts nichts zu tun und dann muss in 3 oder 4 Takten mal
was gearbeitet werden. Das wäre sogar einem Beamten zu fad :-)

> seh ich das dann richtig, dass ich minimal 65536*62,5µs=4,095ms-->244Hz
> messen kann (die 65536 kommt jetzt wegen z.b einer 16 bit integer
> variablen)

* Du hast ja auch noch den Vorteiler
* Wie macht das dann eine Uhr: Die misst auch nur Sekunden und
  trotzdem kannst du mit einer Stoppuhr stundenlang, tagelang,
  wochenlang stoppen.

von Εrnst B. (ernst)


Lesenswert?

Wenn du wirklich hohe Frequenzen messen willst, (Oben stand was von 
16MHz...), dann leg die Frequenz nicht an den ICP oder INT pin, sondern 
als Externes Taktsignal an den Zählereingang.

Im Einfachsten Fall: Zähler einschalten, exakt eine Sekunde warten, 
Zähler wieder ausschalten, Zählerstand == Frequenz.

/Ernst

von Alfred Q. (higedigdag)


Lesenswert?

Hallo ich hätte dazu noch ein Frage.

Wie sieht es aus wenn ich mit dem µC zwei Frequenzen gleichzeitig messen 
will? Ich glaube es gibt keinen AVR mit zwei ICP's, oder?

Oder kann man in so einem Fall auch einen INT-Eingang verwenden?

von STK500-Besitzer (Gast)


Lesenswert?

>Oder kann man in so einem Fall auch einen INT-Eingang verwenden?
Das ist verboten...

Aus dem Thread sollte hervorgegangen sein, wie man kleine und große 
Frequenzen misst.
Die Messmethode hängt halt von der Frequenz ab...
Wie groß sind deine Frequenzen?

von Alfred Q. (higedigdag)


Lesenswert?

Die eine ist max 5kHz die andere geht bis 300Hz.

Ich denk mal für die 5kHz sollte man den ICP verwenden, oder?

von STK500-Besitzer (Gast)


Lesenswert?

Du solltest einen Timer so programmieren, dass er in regelmäßigen 
Abständen einen Überlauf produziert und guckst dann in der Timer-ISR 
nach, ob sich der Zustand des jeweiligen Eingangspin verändert hast.
In der ISR muss dann noch jeder Timer-Interrupt mitgezählt werden, um 
auf die vergangene Zeit zurück schliessen zu können.

von Alfred Q. (higedigdag)


Lesenswert?

ok danke ich werd das mal versuchen... mir gings nur erstmal um die 
gestaltung der hardware

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.