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.