www.mikrocontroller.net

Forum: Compiler & IDEs mal wieder ICP! Werte immer identisch.


Autor: Axel Lemke (lemmi4711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich werde noch irre...

Ich will Impulse von 10-80ms (in 10ms Schritten) im 100ms Abstand 
messen.
Für die Signalerzeugung wird auch ein Mega8 verwendet. Laut Oszi haben 
die Zeiten eine Toleranz von ~0,2ms.

Ich dachte, zum Erfassen der Zeiten ist der ICP-Pin ideal, da man die 
Flankenerkennung umschalten kann. Aber ich kann machen was ich will, die 
Timerwerte sind immer identisch und das Ergebnis ist dann logischerweise 
immer 0;
Es soll erstmal die Zeitdifferenz zwischen steigender und fallender 
Flanke ausgegeben werden.

Text "Impulsdauer:" wird angezeigt...
Pulsdauer wird auch angezeigt, aber immer 0...
Flanke1 und Flanke2 aus der ISR werden auf dem LCD mit verschiedenen 
Werten (beide Variablen immer gleich!) angezeigt ...

Die LCD-Routine ist nur testweise drin (einfacher...) und funktioniert 
einwandfrei! In der ISR sind die LCD-Aufrufe nur drin, damit ich sehe, 
welche Werte ausgegeben werden. Ob die nun da drin sind oder nicht ist 
egal, der Effekt ist der selbe.
Später soll dann eine 7-Segment Anzeige verwendet werden, aber bevor ich 
mich da weiter mache, sollte erstmal die Berechnung funktionieren...


Ich hoffe Ihr könnt mir weiterhelfen, hier ist der Code:


#define F_CPU 8000000UL

#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <util/SPI_LCD.h>
#include <avr/interrupt.h>

volatile uint16_t Flanke1;
volatile uint16_t Flanke2;
uint16_t Pulsdauer;
int a;



ISR (TIMER1_CAPT_vect)
{
  if (TCCR1B & (1<<ICES1))           // Test auf steigende Flanke
  {
    Flanke1 = ICR1;                  // ICP Register = Flanke 1
    TCCR1B &=~(1<<ICES1);            // ICP1 auf fallende Flanke
    lcd_xy(0,2);
    lcd_Var(Flanke1);

  }

  if (!(TCCR1B & (1<<ICES1)))        // Test auf fallende Flanke
  {
    Flanke2 = ICR1;                  // ICP Register = Flanke 2
    TCCR1B |= (1<<ICES1);            // ICP1 auf steigende Flanke
    lcd_xy(9,2);
    lcd_Var(Flanke2);

  }
}


int main (void)
{
  PORTB = 0b00111110;
  DDRB  = 0b00111110;                // Port B0 als Eingang (ICP)

  TIMSK  |= (1<<TICIE1);             // ICP enable
  TCCR1B |= (1<<CS10)|(1<<CS12)|(1<<ICES1);
  // Timer1 => 1/1024 CPU-Clock, ICP steigende Flanke

  sei();                             // Interruptfreigabe

  while (1)
  {
    Pulsdauer = (Flanke2 - Flanke1); // Pulsdauer ausrechnen
    cli();
    // für LCD Ausgabe die Interrupts sperren, führt sonst zu Störungen
    // in den LCD-delays...
    lcd_xy(0,0);
    lcd_String("Impulsdauer:");
    lcd_xy(0,1);
    lcd_Var(Pulsdauer);
    _delay_ms(100);
    sei();                           // Interrupts wieder freigeben
  }
  return (0);
}

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überleg mal, warum dein Programm immer beide if-Blöcke in der ISR 
durchläuft. Ein "else" an Stelle des zweiten if's dürfte das Problem 
lösen.

Oliver

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem:

1. cli und sei sind falsch positioniert. Du klammerst damit genau den 
falschen Bereich.

2. Welcher Controller?
Z.B. Zitat Datenblatt ATmega8:
After a change of the edge, the Input Capture Flag (ICF1) must be
cleared by software (writing a logical one to the I/O bit location).

3. Die LCD-Ausgaben im Interrupt sind auch eher suboptimal.

4. Solltest du mit dem Berechnen von Pulsdauer nicht so lange warten, 
bis in Flanke1/2 auch was sinnvolles drin steht?

Autor: Axel Lemke (lemmi4711)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, Leute...

Mit Eurer Hilfe habe ich es nun geschafft.

Es sollte ein Zuordnungsgerät für 8 Leitungen werden, bestehend aus 
Sender und Empfänger...

@ Oliver: Hauptproblem war die 2. if Abfrage in der ISR. Ich musste dann 
nur noch eine Variablenzuweisung hinzufügen, welche ich in 'main' 
abfrage. Dann hat alles funktioniert.

@ Stefan E.: Nun gut, es musste natürlich gewartet werden, bis beide 
Messungen abgeschlosen sind. Aber dennoch ist Dein Zitat aus dem ATMEGA8 
Datenblatt falsch!!!

Sobald der Interrupt in der ISR aufgerufen wird, wird ICF1 automatisch 
gelöscht...

Das richtige Zitat lautet:

ICF1 is automatically cleared when the Input Capture Interrupt Vector is 
executed. Alternatively, ICF1 can be cleared by writing a logic one to 
its bit location.

cli() & sei() habe ich korrigiert...

Über die anderen Kommentare werde ich nicht eingehen, da Du 
offensichtlich meine Info dazu nicht gelesen hast.

Da ich das Projekt interressant finde, werde ich das Projekt in der 
Codesammlung veröffentlichen...


Danke und Gruß an Euch....

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Axel Lemke schrieb:

> @ Stefan E.: Nun gut, es musste natürlich gewartet werden, bis beide
> Messungen abgeschlosen sind. Aber dennoch ist Dein Zitat aus dem ATMEGA8
> Datenblatt falsch!!!

Das Zitat steht genau so wie von mir gepostet im Datenblatt (per 
Copy&Paste rausgeholt). Glaubst du ernsthaft, ich hätte mir den Text 
einfach ausgedacht?


> Sobald der Interrupt in der ISR aufgerufen wird, wird ICF1 automatisch
> gelöscht...
>
> Das richtige Zitat lautet:
>
> ICF1 is automatically cleared when the Input Capture Interrupt Vector is
> executed. Alternatively, ICF1 can be cleared by writing a logic one to
> its bit location.

Lies mein Zitat nochmal genau. Es bezieht sich ja gar nicht auf das 
Flaglöschen nach einem Interrupt, sondern darauf, dass man nach dem 
Ändern der Flankenerkennung (also Bit ICES1) das Flag löschen muss. Das 
bedeutet implizit nichts anderes, als dass das Ändern des Bit ICES1 als 
Nebeneffekt ICF1 setzt (oder zumindest unter bestimmten Umständen setzen 
kann).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.