Input Capture Atmega16 Problem

Gast #3697088
Lesenswert?
• ▲
▼
Hallo Leute,
Will zur Übung mit uCs und aus Spaß an der Freude eine DCF77-Uhr bauen.
Zuerst wollte ich mir dazu auf irgendeine Weise das Signal ausgeben 
lassen. Meine erster Ansatz: ich lasse mir die Pulsdauer (als einfacher 
Timerwert) auf ein 2x16 Display schreiben.

Conrad DCF Modul an PortD 
http://www.conrad.de/ce/de/product/641138/Conrad-DCF-Empfaengerplatine
P.Fleurys LCD-Bib, LCD an PORTA 
http://homepage.hispeed.ch/peterfleury/avr-software.html#libs
easyAVR6-Board (Pullups/downs am Board werden nicht genutzt)
Atmega16, 8Mhz int.RC, Timer1, Prescaler 1024.

Erwarten würde ich, dass ich, da Input Capture ja sowohl auf fallende 
als auch steigende Flanken reagieren sollte, für die 0,1-Sek.-Pulse 
ICR1-Werte um 780(für 0,2-Sek.-Pulse um 1550, für 0,9-Sek.-Pausen um 
7000, für 0,8-Sek.-Pausen 6250) bekommen würde.
Dem ist aber leider überhaupt nicht so. Die ausgegebenen Werte liegen 
alle etwa in den Bereichen 8800+-100, 8050+-100, 7200+-100.

Die einzige Erklärung die ich dafür finden konnte ist, dass nicht alle 
Flanken erkannt werden. Ist diese Erklärung evtl falsch? Wenn ja, wo ist 
mein Denkfehler? Wenn nein, woran könnte es liegen, bzw. was kann ich 
dagegen tun?

1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#include <string.h>
5

6
#include "lcd.h"
7
#define LCD_BL 2
8

9
volatile long int pulsewidth1=0;
10
volatile long int pulsewidth2=0;
11
volatile uint8_t a=0;
12
char LCD_string[10];
13

14

15
int main(void){  
16
  lcd_init(LCD_DISP_ON);
17
  DDRA|=(1<<LCD_BL);  // Pin unbelegt -> Ausgang
18
  PORTA|=(1<<LCD_BL);
19
  
20
  DDRD&=~(1<<DDD6);  // PD6 Eingang
21
  PORTD=(1<<PD6);    // Pullup, da DCF-Modul OpenCollector
22
  
23
  TCCR1B|=(1<<CS12)|(1<<CS10)|(1<<ICNC1);  // Normal-Mode, Prescaler 1024
24
  TIMSK|=(1<<TOIE1)|(1<<TICIE1);           // Timer 1 Ovf-Interrupt und Capt-Event-Interrupt
25
  sei();
26
  while(1){
27
    if(a){
28
      sprintf(LCD_string,"%#8ld", pulsewidth1);
29
      lcd_gotoxy(6,0);
30
      lcd_puts(LCD_string);
31
    }
32
    else{
33
      sprintf(LCD_string,"%#8ld", pulsewidth1);
34
      lcd_gotoxy(6,1);
35
      lcd_puts(LCD_string);
36
    }
37
  }
38
  cli();
39
}
40

41
ISR(TIMER1_CAPT_vect){
42
  pulsewidth1=ICR1;    // bei 8Mhz,Psc=1024: 781,25=0,1s | 1562,5=0,2s | 7812,5=1s
43
                       // 7031,25=0,9s | 6250=0,8s | 14843,75=1,9s | 14062,5=1,8s
44
  if(a==0){a=1;}
45
  else{a=0;}
46
  TCNT1=0;
47
}
48

49
ISR(TIMER1_OVF_vect){ // eigentlich irrelevant
50
  PORTC++;
51
}

Vielen Dank schonmal im voraus!
Gast #3697105
Lesenswert?
• ▲
▼
Nachtrag: Der einzige sinnvolle Wert kommt jede Minute beim 
ausgelassenen 59. Bit, welches einer Pause von 1,8 Sek bzw 1,9 Sek (also 
Timerwert um ca 15000) entspricht.
Gast #3697471
Lesenswert?
• ▲
▼
K. S. schrieb:

> Erwarten würde ich, dass ich, da Input Capture ja sowohl auf fallende
> als auch steigende Flanken reagieren sollte, für die 0,1-Sek.-Pulse
> ICR1-Werte um 780(für 0,2-Sek.-Pulse um 1550, für 0,9-Sek.-Pausen um
> 7000, für 0,8-Sek.-Pausen 6250) bekommen würde.

Soweit erstmal nachvollziehbare Überlegungen. Und da es lobens- und 
fördernswert ist, wenn noch jemand selber denkt, tatsächlich noch ein 
kleiner Hinweis:

> Dem ist aber leider überhaupt nicht so. Die ausgegebenen Werte liegen
> alle etwa in den Bereichen 8800+-100, 8050+-100, 7200+-100.

Und was passiert, wenn du vor jeder Ausgabe erstmal das Display komplett 
löschst (oder zumindest den Bereich, in dem die Ausgaben erfolgen, also 
wenigstens 4 Zeichen)...

Problem erkennt?
Gast #3697616
Lesenswert?
• ▲
▼
K. S. schrieb:
> Erwarten würde ich, dass ich, da Input Capture ja sowohl auf fallende
> als auch steigende Flanken reagieren sollte...

Richtig!

Entweder wird auf die fallende oder auf die steigende Flanke reagiert. 
Welche davon, das wird durch Bit ICES1 in TCCR1B festgelegt.
Gast #3698049
Lesenswert?
• ▲
▼
c-hater schrieb:
> Und was passiert, wenn du vor jeder Ausgabe erstmal das Display komplett
> löschst (oder zumindest den Bereich, in dem die Ausgaben erfolgen, also
> wenigstens 4 Zeichen

Das stimmt natürlich, danke.

test schrieb:
> Entweder wird auf die fallende oder auf die steigende Flanke reagiert.
> Welche davon, das wird durch Bit ICES1 in TCCR1B festgelegt.

Dieses Bit ist mir überhaupt nicht aufgefallen, danke. Das heißt also, 
ich müsste das Bit jedes Mal im Interrupt Checken und entsprechend 
setzen bzw. löschen.
1
ISR(TIMER1_CAPT_vect){
2
  pulsewidth_new=ICR1;
3
  TCNT1=0;
4
  if(TCCR1B&&(1<<ICES1)){   // Wenn steigende Flanke aktiv
5
    TCCR1B&=~(1<<ICES1);    // fallende aktivieren
6
  }
7
  else{                      // Wenn fallende Flanke aktiv
8
    TCCR1B|=(1<<ICES1);     // steigende aktivieren
9
  }
10
}

Sehe ich das richtig?

Antwort schreiben

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.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.