Drehzahlmesser mit LCD

Gast #1468064
Also ich bin noch ziemlich unerfahren mit Programmierung.
Als Controller verwende ich ein Atmega8.

Ich hab am PC5 ein Funktionsgenerator dran wo ich erstmal 50Hz 
einspeise.
An dem LCD zeigt es aber kein konstanten Wert an nur mal 0.. mal -100, 
mal 567.
...........
Ist der Eingang vielleicht der falsche?
1
#include <avr/io.h>
2
#include <inttypes.h>
3
#include "lcd-routines.c"
4
#include <avr/interrupt.h>
5

6

7
extern int sprintf(char *__s, const char *__fmt, ...); //Umwandeln einer Zahl in einen String
8

9
//globale Variablen
10
unsigned long int xa=0;
11
unsigned long int xb=0;
12
char zeitstring[5];
13

14

15
// Interrupt Service Routine fuer Timer1
16
ISR(TIMER1_OVF_vect) {        
17
      TCNT1 = 34286;          //Zaehlregister mit Vorladewert V vorladen / Berechnung: siehe unten
18
      PORTD ^= (1<<PD7);      //LED toggeln
19
      xa=0;      //Zählwert auf
20
      xb=1;      //Zahl im main ausgeben
21
}
22

23

24
void AUSGABE(void){
25
      sprintf(zeitstring, "%d", xa);                  // Wandelt y nach String   
26
  set_cursor(12, 1);lcd_string("     ");    // Zahl im LCD löschen
27
  set_cursor(12, 1);lcd_string(zeitstring);  // Zahl in LCD schreiben
28
  xb=0;            
29
}
30

31
int main(void){
32
  
33
        DDRB |=  (1<<PB0);   // PB0 ist Status-LED Ausgang
34
  DDRD |=  (1<<PD7);   // PD7 ist Status-LED Ausgang
35
  DDRC &= ~(1<<PC5);  // PC5 ist Status-Eingang
36
  PORTC|=  (1<<PC5);   //internen Pull-Up-Widerstand einschalten
37
  
38
  lcd_init();
39
  lcd_clear();
40
  
41
  set_cursor(1, 1); lcd_string("Drehzahl:");
42
  
43
sei(); //Interrupts ermoeglichen
44
       
45
   
46
    // fuer Timer:     
47
    TIMSK |= (1<<TOIE1);
48
    TCCR1B |= (1<<CS11) |  (1<<CS10);     //Prescaler = 64
49
    TCNT1 = 0xFFFF;//Zaehlregister vorladen mit FFFF zum Sofortstart
50

51
while (1)  {  
52
    
53
    if (!(PINC &(1<<PINC5)) ) xa++; //Zähle immer eins hoch an PINC5
54
    if (xb==1)   AUSGABE();    
55
    
56
    }
57

58
    return(0);
59
}
Also wenn ich das richtig sehe, dann fragst du alle paar µs den Port ab 
(while(1)) und schaust wie der Zustand ist. Wenn er LOW ist wird xa 
inkrementiert. Wenn du eine Rechteckspannung misst, dann liegt ja der 
Pegel länger auf LOW. Es kann also sein, dass du einige 100 mal Pro LOW 
xa inkrementierst. Dann hast du noch das Problem, dass vor der "AUSGABE" 
xa bereits wieder durch den Timer interrupt auf 0 gesetzt wurde. Also 
irgendwie ist das alles sehr komisch.
Du darfst ja nur hochzählen wenn sich der Zustand geändert hat. Also
1
while(1){
2
  aktuellerpegel = PINC &(1<<PINC5);
3
  if(alterpegel != aktuellerpegel){ 
4
    xa++;
5
    alterpegel = aktuellerpegel;
6
  }
7
}
Und für die Ausgabe musst du dir natürlich auch noch was einfallen 
lassen, dass der Wert noch konsistent ist. Und immer schön volatile 
Variablen verwenden, wenn du in interrupt-routinen mit Globalen 
Variablen spielst.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.