Quellcode |
/******************************************************************************
* SYSTEM INCLUDE FILES
******************************************************************************/
#include <stm32f4xx.h>
/******************************************************************************
* DEFINES
******************************************************************************/
//Messung mit N Flanken durchführen
anstelle von einer Flanke durchführen
#define WARTE_ERSTE_FLANKE 0
#define WARTE_N_FLANKEN 1
#define MESSUNG_FERTIG 2
#define ANZAHL_VON_FLANKEN 1
//Hier kann die Anzahl der Flanken bestimmt
//werden.
/******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************/
//Diese Funktion
initialisiert den GPIO Pin (GPIO=General Purpose Input Output)
void init_GPIO(void)
{
//Dieser TypeDef structure ist ein
Datentyp der aus mehreren Datentypen besteht.
//Er beinhaltet alle Eigenschaften die man dem Pin zuweist,
wie z.B. ob es sich
//um einen
Input oder Output bin handeln soll.
GPIO_InitTypeDef GPIO_InitStruct;
//Hier wird die Peripherie Zeit des
GPIO-Moduls aktiviert
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//Initialisierung GPIO Modul A
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
//Hier wird Pin0 im Modul A
//konfiguriert.
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
//Pin0 als Input deklarieren.
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
//Zeittakt von GPIO
//einstellen (20ns).
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
//Einstellen ob open drain
//oder push/pull
//setzt den Pin auf
//push/pull Betrieb.
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
//Hier auf pulldown setzten,
//da wir den high Zustand
//detektieren wollen.
GPIO_Init(GPIOA, &GPIO_InitStruct); //Die Konfiguration oben
//wird dem Modul A
//zugewiesen.
}//init_GPIO
//Diese Funktion initialisiert den
Timer1
void init_TIM(void)
{
RCC_APB2PeriphClockCmd (RCC_APB2Periph_TIM1,
ENABLE);
//Aktivieren den Takt des
//Timers.
TIM_TimeBaseInitTypeDef
TIM_InitStruct;
//Der Datentyp Struct
//enthält alle Eigenschaften
//die nachfolgend
//eingestellt werden.
TIM_InitStruct.TIM_Prescaler = 1009;
//Prescale von 1009.
//Ungefähr 63us pro Takt.
TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up;
//Timer zählt aufwärts.
TIM_InitStruct.TIM_Period = 0xFFFF;
//Der Timer kann bis FFFF
//zählen.
TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
//Die Frequenz des Timers
//kann dividiert werden hier
//1.
TIM_TimeBaseInit(TIM1,
&TIM_InitStruct); //Die KOnfiguration oben
//wird dem Timer 1
//zugewiesen.
TIM_Cmd(TIM1,
ENABLE); //Aktiviert den Timer1.
}//init_TIM
/******************************************************************************
* FUNCTION BODYS
******************************************************************************/
int main(void)
{
init_GPIO();
//Aufruf der Initilisierung von GPIO
init_TIM();
//Aufruf der Initialierung
//des Timers.
uint8_t state;
//state gibt den Zustand des
//Programms wieder
uint8_t
prevPegel, pegelNow;
//prevPegel gibt den
//vorherigen Pegel wieder,
//pegelNow gibt den jetzigen
//Pegel wieder.
uint8_t nrFlanken;
//nrFlanken gibt die Anzahl
//der Flanken an.
uint16_t
startTime;
//Gibt die Startzeit an
uint16_t
endTime;
//Gibt die Endzeit an
double
Drehzahl;
//Gibt die Drehzahl an
state = WARTE_ERSTE_FLANKE;
//das Programm wartet auf
//die erste Flanke.
prevPegel =
GPIOA->IDR & 0x0001;
//prevPegel wird das erste
//Bit von GPIOA zugewiesen
//(d.h. welchen Zustand das
//erste Bit hat, high oder
//low)
nrFlanken = 0;
//Startwert der Anzahl der
//Flanken.
TIM_SetCounter(TIM1,
0);
//Zähler wird auf 0 gesetzt
uint16_t timeStart_ZU, timeNow;
timeStart_ZU = TIM_GetCounter(TIM1);
//timeStart_ZU wird die
//Bitanzahl von TIM1
//zugewiesen.
timeNow =
timeStart_ZU;
//Schleife endet wenn
timeNow-timeStart_ZU>1200. Das dient dazu wenn Rotor im
//Stillstand wird keine Drehzahl erfasst. Schleife endet
auch wenn
//MESSUNG_FERTIG wenn
Anzahl der eingestellten Flanken erreicht ist
while( timeNow - timeStart_ZU < 0x2EE0 &&
//12000 Takt( von Timer 1
//überschreitet.
state !=
MESSUNG_FERTIG )
{
timeNow = TIM_GetCounter(TIM1);
//hier wird timeNow die
//Zeit des Timers zugewiesen.
pegelNow = GPIOA->IDR & 0x0001;
//pegelNow wird der Pegel
//des Pins zugewiesen high
//oder low
switch( state )
{
case WARTE_ERSTE_FLANKE:
//prevPegel muss unterschiedlich von pegelNow sein und
gleichzeitig
//muss pegelNow high
sein. So werden nur die positiven Flanken erkannt.
if( prevPegel != pegelNow && pegelNow == 0x0001 )
{
startTime = timeNow;
timeStart_ZU = timeNow;
state = WARTE_N_FLANKEN;
}
break;
case WARTE_N_FLANKEN:
//
// Start
der Messung
// Nach N erkannten
steigenden Flanke wird abgebrochen
// In diesem Beispiel ist N=3
//
//
+---+ +---+ +----+
+----+ +----+
// | |
| | |
| | |
| |
// --+ +----+ +----+
+----+ +----+ +----
// ^
^ 1
2 3
//
| |
|
//
| |
Ende der Messung
//
| Beginn der Messung
//
|
//
Einstieg in die Funktion
//
// Die 3.te steigende Flanke kennzeichnet den Beginn des
// 4.ten Pulses. Der Propeller hat in diesem Fall 3
Umdrehungen gemacht.
//hier werden die ANZAHL_VON_FLANKEN mit
nrFlanken verglichen. nrFlanken
//wird solage inkrementiert, bis nrFlanken == ANZAHL_VON_FLANKEN
if( prevPegel != pegelNow && pegelNow == 0x0001 )
{
nrFlanken++;
timeStart_ZU = timeNow;
if( nrFlanken == ANZAHL_VON_FLANKEN )
{
endTime = timeNow;
state = MESSUNG_FERTIG;
}
}
break;
}//switch
prevPegel = pegelNow;
}//while
//hier wird die Drehzhal berechnet
if( state == MESSUNG_FERTIG )
{
Drehzahl =
ANZAHL_VON_FLANKEN*60*1000/((endTime-startTime)*0.06318);
//Aus endTime und startTime
//die Drehzahl errechnen.
}
else
Drehzahl
= 0;
//Wegen Zeitüberschreitung.