RevolT3c
27.12.2010, 16:50
Hi @ all,
ich hab mir eine kleine Schaltung gebastelt die mir über eine Gabellichtschranke und einer 4-stelligen 7-Segmentanzeige die Drehzahl meiner Bohrmaschine anzeigen soll.
Leider bin ich noch Anfänger in C und was das programmieren mit µC angeht also habt Gnade [-o<
Das Ganze soll über Multiplexing funktionieren.
Hier ein Bild zum Schaltplan:
http://www.abload.de/img/planclhl.png
Und hier der Code:
///////////////////////////////////////////////////////////////////
// Drehzahlmessung:
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
// dauer des Signals von einer steigenden Flanke bis zur naechsten
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
// errechnen. Zwischen den Messwerten ist jeweils ein Takt der nicht gemessen wird.
//
//
//
//
/////////////////////////////////////////////////////////////////////
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
// beim Aufruf des C Compilers gab.
#ifndef F_CPU
#define F_CPU 8000000
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
// Ports der entsprechenenden Ausgänge
#define seg_port1 PORTC //a - f
#define seg_port2 PORTD //g
#define seg_masse_port PORTB //massepins
// 7seg LED Pins
#define sega PC0
#define segb PC1
#define segc PC2
#define segd PC3
#define sege PC4
#define segf PC5
#define segg PD0
//Masse Pins
#define seg1 PB4 // 1er
#define seg2 PB3 // 10er
#define seg3 PB2 // 100er
#define seg4 PB1 // 1000er
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die waehrend der Messung passiert sind
volatile unsigned int StartTime = 0; // ICR-Wert bei 1.High-Flanke speichern
volatile unsigned int EndTime = 0; // ICR-Wert bei 2.High-Flanke speichern
volatile unsigned char Ausgabe = FALSE; // Job Flag
volatile unsigned char Messungfertig; // Job Flag
volatile unsigned char ErsteFlanke = TRUE;
volatile uint32_t Erg = 0;
volatile int drehzahl;
volatile int ziffer = 0;
volatile int zahl = 0;
volatile int stelle= 0;
volatile int Mittelwert = 0;
volatile int schleife =0;
void ausgabe(int ziffer, int stelle);
int main(void);
ISR ( TIMER1_CAPT_vect )
{
if (Ausgabe == TRUE) // Das Display wurde mit den Ergebnissen der vorhergehenden
{
return;
} // Messung noch nicht upgedated. Die naechste Messung
// verz?gern, bis die Start und EndTime Variablen wieder
// gefahrlos beschrieben werden koennen
if( ErsteFlanke == TRUE )
{
StartTime = ICR1; // Startzeit= ICR 1
NrOverflows = 0;
ErsteFlanke = FALSE; // Die naechste Flanke ist das Ende der Messung
}
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
else
{
EndTime = ICR1; // Stopzeit für die Messung= ICR1
Ausgabe = TRUE; // Eine vollst?ndige Messung. Sie kann ausgewertet werden
ErsteFlanke = TRUE; // Bei der naechsten Flanke beginnt der naechste Messzyklus
}
}
ISR( TIMER1_OVF_vect )
{
NrOverflows++;
return;
}
void init_interrupt(void) // Interrups klar machen
{
TCCR1B = (1<<ICES1) | (1<<CS10); // Input Capture steigende Flanke an ICT-Pin(PB0), kein PreScale
TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow
sei(); //Interrups freigeben
}
int Messwerte_auslesen() //Unterprogramm zur Messwertausgabe
{
schleife++;
// liegt eine vollst?ndige Messung vor?
Erg = (NrOverflows * 65536) + (EndTime - StartTime);
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Erg = F_CPU / Erg; // f = 1 / t
//aus der Frequenz berechnet sich die Drehzahl
zahl = Erg * 60; // Drehzahl berechnen aus der Frequenz f*60sec= U/min
Mittelwert+=zahl; //Mittelwert aus 28 Messungen bilden
if (schleife<29)
{
return;
}
else
{
drehzahl=Mittelwert/28;
Mittelwert=0;
schleife=0;
}
}
void Messwerte_ausgeben(void)
{
static int zahl3;
zahl3 = drehzahl; //Drezahlwert wird übergeben
ziffer = zahl3/1000; // 1000er Stelle für Segmentanzeige
zahl3 = zahl3 - ziffer*1000;
ausgabe (ziffer,4);
_delay_ms(1);
ziffer = zahl3/100; // 100er Stelle für Segmentanzeige
zahl3= zahl3 - ziffer*100;
ausgabe (ziffer,3);
_delay_ms(1);
ziffer = zahl3/10; // 10er Stelle für Segmentanzeige
zahl3 = zahl3 - ziffer*10;
ausgabe (ziffer,2);
_delay_ms(1);
ziffer = zahl3; // 1er Stelle für Segmentanzeige
ausgabe (ziffer,1);
_delay_ms(1);
}
void ausgabe(int iziffer, int istelle)
{
seg_port1=0;
seg_port2=0;
seg_masse_port=0;
//Steuerleitungen ausgeben
switch(iziffer)
{
case 0: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
break;
case 1: seg_port1 |= ((1<<segb)|(1<<segc));
break;
case 2: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segd)|(1<<sege));
seg_port2 |= (1<<segg);
break;
case 3: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd));
seg_port2 |= (1<<segg);
break;
case 4: seg_port1 |= ((1<<segb)|(1<<segc)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 5: seg_port1 |= ((1<<sega)|(1<<segc)|(1<<segd)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 6: seg_port1 |= ((1<<sega)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 7: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc));
break;
case 8: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 9: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segf));
seg_port2 |= (1<<segg);
break;
default: seg_port1 = 0;
seg_port2 = 0;
break;
}
//Masse schalten
switch(istelle)
{
case 1: seg_masse_port |= (1<<seg1);
break;
case 2: seg_masse_port |= (1<<seg2);
break;
case 3: seg_masse_port |= (1<<seg3);
break;
case 4: seg_masse_port |= (1<<seg4);
break;
default : break;
}
return;
}
int main(void)
{
DDRD |= 0xFF;
DDRC |= 0xFF;
DDRB &= ~(1 << DDB0);
DDRB |= (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4);
PORTD = 0;
PORTC = 0;
PORTB &= ~(1<<PB0);
//Interrups klar machen
init_interrupt();
while(1) //diese Schleife soll das Programm immer wiederholen.
{
Messwerte_ausgeben();
if (Ausgabe==TRUE)
{
Messwerte_auslesen();
Ausgabe=FALSE;
}
}
}
Eigentlich soll nach 2 steigenden Flanken der Wert ausgelesen werden und die Drehzahl ermittelt werden. Gemessen wird 28x und dann ein Mittelwert gebildet. Der Mittelwert soll dann auf die 7-Segmentanzeige ausgegeben werden.
Leider klappt das so nicht :P Die Anzeige zeigt immer 0000 an und flackert höchstens mal. Weiss jemand Rat?
Gruss RevolT3c
ich hab mir eine kleine Schaltung gebastelt die mir über eine Gabellichtschranke und einer 4-stelligen 7-Segmentanzeige die Drehzahl meiner Bohrmaschine anzeigen soll.
Leider bin ich noch Anfänger in C und was das programmieren mit µC angeht also habt Gnade [-o<
Das Ganze soll über Multiplexing funktionieren.
Hier ein Bild zum Schaltplan:
http://www.abload.de/img/planclhl.png
Und hier der Code:
///////////////////////////////////////////////////////////////////
// Drehzahlmessung:
// Das zu messende Signal wird an den Input Capture Pin des Prozessors
// angelegt. Zur Freqenzbestimmung wird mittels Timer1 die Perioden-
// dauer des Signals von einer steigenden Flanke bis zur naechsten
// steigenden Flanke ermittelt. Daraus laesst sich dann die Frequenz
// errechnen. Zwischen den Messwerten ist jeweils ein Takt der nicht gemessen wird.
//
//
//
//
/////////////////////////////////////////////////////////////////////
// Prozessor Taktfrequenz einstellen sofern es nicht eine Vorgabe
// beim Aufruf des C Compilers gab.
#ifndef F_CPU
#define F_CPU 8000000
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
// Ports der entsprechenenden Ausgänge
#define seg_port1 PORTC //a - f
#define seg_port2 PORTD //g
#define seg_masse_port PORTB //massepins
// 7seg LED Pins
#define sega PC0
#define segb PC1
#define segc PC2
#define segd PC3
#define sege PC4
#define segf PC5
#define segg PD0
//Masse Pins
#define seg1 PB4 // 1er
#define seg2 PB3 // 10er
#define seg3 PB2 // 100er
#define seg4 PB1 // 1000er
volatile unsigned char NrOverflows = 0; // Anzahl der Timer Overflows die waehrend der Messung passiert sind
volatile unsigned int StartTime = 0; // ICR-Wert bei 1.High-Flanke speichern
volatile unsigned int EndTime = 0; // ICR-Wert bei 2.High-Flanke speichern
volatile unsigned char Ausgabe = FALSE; // Job Flag
volatile unsigned char Messungfertig; // Job Flag
volatile unsigned char ErsteFlanke = TRUE;
volatile uint32_t Erg = 0;
volatile int drehzahl;
volatile int ziffer = 0;
volatile int zahl = 0;
volatile int stelle= 0;
volatile int Mittelwert = 0;
volatile int schleife =0;
void ausgabe(int ziffer, int stelle);
int main(void);
ISR ( TIMER1_CAPT_vect )
{
if (Ausgabe == TRUE) // Das Display wurde mit den Ergebnissen der vorhergehenden
{
return;
} // Messung noch nicht upgedated. Die naechste Messung
// verz?gern, bis die Start und EndTime Variablen wieder
// gefahrlos beschrieben werden koennen
if( ErsteFlanke == TRUE )
{
StartTime = ICR1; // Startzeit= ICR 1
NrOverflows = 0;
ErsteFlanke = FALSE; // Die naechste Flanke ist das Ende der Messung
}
// das ist die zweite Flanke im Messzyklus. Die Messung wird gestoppt
else
{
EndTime = ICR1; // Stopzeit für die Messung= ICR1
Ausgabe = TRUE; // Eine vollst?ndige Messung. Sie kann ausgewertet werden
ErsteFlanke = TRUE; // Bei der naechsten Flanke beginnt der naechste Messzyklus
}
}
ISR( TIMER1_OVF_vect )
{
NrOverflows++;
return;
}
void init_interrupt(void) // Interrups klar machen
{
TCCR1B = (1<<ICES1) | (1<<CS10); // Input Capture steigende Flanke an ICT-Pin(PB0), kein PreScale
TIMSK = (1<<TICIE1) | (1<<TOIE1); // Interrupts akivieren, Capture + Overflow
sei(); //Interrups freigeben
}
int Messwerte_auslesen() //Unterprogramm zur Messwertausgabe
{
schleife++;
// liegt eine vollst?ndige Messung vor?
Erg = (NrOverflows * 65536) + (EndTime - StartTime);
// ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
Erg = F_CPU / Erg; // f = 1 / t
//aus der Frequenz berechnet sich die Drehzahl
zahl = Erg * 60; // Drehzahl berechnen aus der Frequenz f*60sec= U/min
Mittelwert+=zahl; //Mittelwert aus 28 Messungen bilden
if (schleife<29)
{
return;
}
else
{
drehzahl=Mittelwert/28;
Mittelwert=0;
schleife=0;
}
}
void Messwerte_ausgeben(void)
{
static int zahl3;
zahl3 = drehzahl; //Drezahlwert wird übergeben
ziffer = zahl3/1000; // 1000er Stelle für Segmentanzeige
zahl3 = zahl3 - ziffer*1000;
ausgabe (ziffer,4);
_delay_ms(1);
ziffer = zahl3/100; // 100er Stelle für Segmentanzeige
zahl3= zahl3 - ziffer*100;
ausgabe (ziffer,3);
_delay_ms(1);
ziffer = zahl3/10; // 10er Stelle für Segmentanzeige
zahl3 = zahl3 - ziffer*10;
ausgabe (ziffer,2);
_delay_ms(1);
ziffer = zahl3; // 1er Stelle für Segmentanzeige
ausgabe (ziffer,1);
_delay_ms(1);
}
void ausgabe(int iziffer, int istelle)
{
seg_port1=0;
seg_port2=0;
seg_masse_port=0;
//Steuerleitungen ausgeben
switch(iziffer)
{
case 0: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
break;
case 1: seg_port1 |= ((1<<segb)|(1<<segc));
break;
case 2: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segd)|(1<<sege));
seg_port2 |= (1<<segg);
break;
case 3: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd));
seg_port2 |= (1<<segg);
break;
case 4: seg_port1 |= ((1<<segb)|(1<<segc)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 5: seg_port1 |= ((1<<sega)|(1<<segc)|(1<<segd)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 6: seg_port1 |= ((1<<sega)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 7: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc));
break;
case 8: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<sege)|(1<<segf));
seg_port2 |= (1<<segg);
break;
case 9: seg_port1 |= ((1<<sega)|(1<<segb)|(1<<segc)|(1<<segd)|(1<<segf));
seg_port2 |= (1<<segg);
break;
default: seg_port1 = 0;
seg_port2 = 0;
break;
}
//Masse schalten
switch(istelle)
{
case 1: seg_masse_port |= (1<<seg1);
break;
case 2: seg_masse_port |= (1<<seg2);
break;
case 3: seg_masse_port |= (1<<seg3);
break;
case 4: seg_masse_port |= (1<<seg4);
break;
default : break;
}
return;
}
int main(void)
{
DDRD |= 0xFF;
DDRC |= 0xFF;
DDRB &= ~(1 << DDB0);
DDRB |= (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4);
PORTD = 0;
PORTC = 0;
PORTB &= ~(1<<PB0);
//Interrups klar machen
init_interrupt();
while(1) //diese Schleife soll das Programm immer wiederholen.
{
Messwerte_ausgeben();
if (Ausgabe==TRUE)
{
Messwerte_auslesen();
Ausgabe=FALSE;
}
}
}
Eigentlich soll nach 2 steigenden Flanken der Wert ausgelesen werden und die Drehzahl ermittelt werden. Gemessen wird 28x und dann ein Mittelwert gebildet. Der Mittelwert soll dann auf die 7-Segmentanzeige ausgegeben werden.
Leider klappt das so nicht :P Die Anzeige zeigt immer 0000 an und flackert höchstens mal. Weiss jemand Rat?
Gruss RevolT3c