Forum: Compiler & IDEs Drehzahlmesser mit LCD


von crasher (Gast)


Lesenswert?

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
}

von Timmo H. (masterfx)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

Alles das was Timmo gesagt hat.
Plus: Bitte immer darauf achten bei printf und Konsorten die richtigen 
Codes zu verwenden. %d ist definitiv falsch für unsigned long. Und das 
ist kein Kavaliersdelikt!

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.