Libs for using Nucleo STM32F411 periphery

Introduction

Descruption: This lib uses the hardware peripherie from STM32F411 under serveral conditions. So you can use an quadraturencoder with different timers.

Requirement: Only tested with the nucleo F411. Include the mbed lib! Interfacing details are explained in the documentary of each class.

Overview

  1. timer modules
    1. Quadratur Encoder (Version 1.2 - C. Hoyer 12.8.2015)
  2. SPI modules
    1. AD5664 (Version 1.1 - C. Hoyer 23.7.2015)
  3. software modules
    1. Ringbuffer (Version 0.9 - C. Hoyer 18.8.2015)
    2. PID-Regler (Version 1.0 - C. Hoyer 17.9.2015)

Files at this revision

API Documentation at this revision

Comitter:
ChrisselH
Date:
Mon Nov 28 17:27:43 2016 +0000
Commit message:
port from priv lib

Changed in this revision

SPI/AD5664.cpp Show annotated file Show diff for this revision Revisions of this file
SPI/AD5664.h Show annotated file Show diff for this revision Revisions of this file
SWModule/PIDControl.cpp Show annotated file Show diff for this revision Revisions of this file
SWModule/PIDControl.h Show annotated file Show diff for this revision Revisions of this file
SWModule/RingBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
SWModule/RingBuffer.h Show annotated file Show diff for this revision Revisions of this file
TIM/QUADRATURE.cpp Show annotated file Show diff for this revision Revisions of this file
TIM/QUADRATURE.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 1acdcc576936 SPI/AD5664.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SPI/AD5664.cpp	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,137 @@
+#include "mbed.h"
+#include "AD5664.h"
+
+//====================================================================================================================================
+//                              Grundlagen, DAC Schreiben und Initialisieren
+//====================================================================================================================================
+
+AD5664::AD5664(SPI _spi, PinName _daccs): spi(_spi), daccs(_daccs)
+{                                 
+        sendDAC(0x2F, 0x00, 0x00);                                         //Software Reset, alle Ausgänge auf 0                                                              
+    } 
+  
+  
+void AD5664::sendDAC(int instruction = 0x00, int data1 = 0x00, int data2 = 0x00)
+{        
+        daccs = 0;                                                          // Select Device      
+                                                       
+                spi.write(instruction);                                     // Schreibt entsprechend die Anweisung und die Adresse                                     
+                spi.write(data1);                                           // Schreibt den ersten Byte an Daten 
+                spi.write(data2);                                           // Schreibt den zweiten Byte an Daten              
+                 
+        daccs = 1;                                                          // Deselect                                                                         
+    }     
+
+//====================================================================================================================================
+//                              Setter-Funktionen
+//====================================================================================================================================
+
+void AD5664::SelectCS()
+{         daccs = 0;                                                        // Select Device                              
+    }
+
+void AD5664::DeselectCS()
+{          daccs = 1;                                                       // Deselect  
+    }  
+    
+void AD5664::writeDAC(char channel, int value)
+{
+        int choch = 0x00;                                                    //Temporäre Variable um die Instructions zu übernehmen
+            
+            switch(channel){
+                    case 'A':                                                // DAC A
+                        choch = 0x18;
+                    break;
+                    
+                    case 'B':                                                // DAC B
+                        choch = 0x19;
+                    break;
+                    
+                    case 'C':                                                // DAC C
+                        choch = 0x1A;
+                    break;   
+
+                    case 'D':                                                // DAC D
+                        choch = 0x1B;
+                    break;                
+
+                    case 'F':                                                // Alle Dacs
+                        choch = 0x1F;
+                    break;
+                    
+                    default:
+                        choch = 0x1F;                                       // Alle Dacs
+                    }      
+                                                                     
+    sendDAC(choch, *((uint8_t*)&(value)+1), *((uint8_t*)&(value)+0));      //Schreibe via SPI: Anweisung mit Adresse, oberes Byte, unteres Byte)                                                                      
+           
+    }
+      
+
+
+void AD5664::loadDAC(char channel, int value)
+{
+        int choch = 0x00;                                                    //Temporäre Variable um die Instructions zu übernehmen
+            
+            switch(channel){
+                    case 'A':                                                // DAC A
+                        choch = 0x00;
+                    break;
+                    
+                    case 'B':                                                // DAC B
+                        choch = 0x01;
+                    break;
+                    
+                    case 'C':                                                // DAC C
+                        choch = 0x02;
+                    break;   
+
+                    case 'D':                                                // DAC D
+                        choch = 0x03;
+                    break;                
+
+                    case 'F':                                                // Alle Dacs
+                        choch = 0x07;
+                    break;
+                    
+                    default:
+                        choch = 0x07;                                       // Alle Dacs
+                    }      
+                                                                     
+    sendDAC(choch, *((uint8_t*)&(value)+1), *((uint8_t*)&(value)+0));      //Schreibe via SPI: Anweisung mit Adresse, oberes Byte, unteres Byte)                                                                      
+           
+    }
+    
+    
+void AD5664::updateDAC(char channel)
+{
+        int choch = 0x00;                                                    //Temporäre Variable um die Instructions zu übernehmen
+            
+            switch(channel){
+                    case 'A':                                                // DAC A
+                        choch = 0x08;
+                    break;
+                    
+                    case 'B':                                                // DAC B
+                        choch = 0x09;
+                    break;
+                    
+                    case 'C':                                                // DAC C
+                        choch = 0x0A;
+                    break;   
+
+                    case 'D':                                                // DAC D
+                        choch = 0x0B;
+                    break;                
+
+                    case 'F':                                                // Alle Dacs
+                        choch = 0x0F;
+                    break;
+                    
+                    default:
+                        choch = 0x0F;                                       // Alle Dacs
+                    }      
+                                                                     
+    sendDAC(choch, 0x00 , 0x00);      //Schreibe via SPI: Anweisung mit Adresse, oberes Byte, unteres Byte)                                                                      
+           
+    }
diff -r 000000000000 -r 1acdcc576936 SPI/AD5664.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SPI/AD5664.h	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,145 @@
+#include "mbed.h"
+
+#ifndef AD5664_h
+#define AD5664_h
+
+/*! Diese Klasse dient zur Ansteuerung des Digital-Analog-Wandlers AD5664 der Firma Analog Devices. Der DAC ist ein 16-Bit Wandler mit 4 Kanälen, Versorgungsspannung von 2,7V bis 5,5V. 
+Die Maximale Settling Time beträgt 7µs (AD5664), und die Genauigkeit liegt bei +-12 LSBs maximum. Angesteuert wird er mittels SCLK, CS und MOSI mit maximal 50 MHz. Zuvor muss die SPI-Schnittstelle definiert werden. Die 
+Chip Select Schnittstelle kann durch die Initialisierung mit Übergeben werden. Es ist darauf zu achten das der Chip bzw die Library nur den SPI-Modus "1" (CLK Standart auf 0 und übernahme mit fallender Flanke) mit einer Datenbreite von 8-Bit unterstützt.
+ 
+ * @code
+ * #include "mbed.h"
+ * #include "AD5664.h"
+ *
+ * SPI interface(PB_5, PB_4, PB_3);         // SPI Interface und Pins (MISO PB.5 , MOSI PB.4, SCLK PB.3) festlegen
+ *
+ * int main() {
+ *    
+ *     interface.format(8,1);               // Interface Format festlegen: 8-Bit, SPI-Modus 1
+ *     interface.frequency(1000000);        // Übertragungsgeschwindigkeit 1MHz 
+ *      
+ *     AD5664 device(interface, PB_2);     // Eine Instanz des DACs erzeugen, Chipselect ist PB.2
+ *            
+ *     device.loadDAC('D', 0x11FF);         // Den Wert 0x11FF in den Kanal D laden
+ *  
+ *     device.updateDAC('D');               // Den geladenen Wert am Kanal D ausgeben
+ *
+ *     device.writeDAC('A', 0x89BD);        // Den Wert 0x89BD an dem Kanal A direkt ausgeben
+ *   
+ *      }
+ *
+ * @endcode
+ */
+ 
+class AD5664     
+{   
+    public:
+    
+     /*! Konstruktor zum Erstellen einer Instanz für einen vorher spezifizierten SPI-Port und Chip Select-Pin. Nach dem Erstellen dieser Instanz werden alle Ausgänge des DACs auf 0 gesetzt. */
+     /*!
+        \param spi Entsprechner SPI-Port (Datenbreite 8 Bit, SPI Modus 1)
+        \param daccs Pin für Chipselect
+     */                   
+    AD5664(SPI _spi, PinName _daccs);
+     
+     
+        
+     /*! Funktion zum Beschreiben des Chips mit je 8-Bit. Für genauere Details bitte das Datenblatt lesen*/
+     /*!
+        \param instruction <b>Direkte Anweisungen für den AD5664</b><br>
+                            Die 8 Instruction-Bits sind wie folgt aufgebaut:<br> <br>
+                            <CENTER> X X C C C A A A </CENTER><br>
+                            - Die ersten zwei Bits sind don't cares<br> 
+                            - Die <EM>Befehle C</EM> sind wie fogt aufgebaut<br>
+                            <ul>  
+                            <li> 000   Schreibe Input register N</li> 
+                            <li> 001   Update DAC Register N</li>
+                            <li> 010   Schreibe Inputregister N und Update alle DAC Register</li>
+                            <li> 011   Schreibe Inputregister N und Update DAC Register N</li>
+                            <li> 100   Power Down DAC (siehe Datenblatt)</li>
+                            <li> 101   Reset (siehe Datenblatt)</li>
+                            <li> 110   Funktionsregister LDAC (siehe Datenblatt)</li>
+                            </ul>
+                            - Die <EM>Adresse A</EM> zum Register N sind wie fogt aufgebaut<br>
+                            <ul>  
+                            <li> 000   DAC A</li> 
+                            <li> 001   DAC B</li>
+                            <li> 010   DAC C</li>
+                            <li> 011   DAC B</li>
+                            <li> 111   All DACs</li>
+                            </ul>
+                            
+        \param data1 <b>Datenbits</b><br>
+                            ersten 8 Datenbits, bzw. oberen zwei Nibble
+        \param data2 <b>Datenbits</b><br>
+                            zweiten 8 Datenbits, bzw. unteren zwei Nibble        
+     */         
+    void sendDAC(int instruction, int data1, int data2); 
+    
+    /*! Destruktor der Klasse */        
+    virtual ~AD5664(){};
+    
+    /*! Setzt den Chipselect-Pin des Wandlers auf "select" bzw. wählt diesen aus. */
+    void SelectCS();
+    
+    /*! Setzt den Chipselect-Pin des Wandlers auf "deselect" bzw. wählt diesen ab. */
+    void DeselectCS();
+    
+    
+    
+    /*! Schreibt ein 16-Bit Wert in den eingestellten Kanal. Der Wert wird direkt in das DAC Register geschrieben und der Wert wird direkt ausgegen. */
+    /*!
+        \param channel <b>Einstellung des Ausgewählten Kanals</b><br>
+                            <ul>  
+                            <li> A   Beschreibt Kanal A</li> 
+                            <li> B   Beschreibt Kanal B</li>
+                            <li> C   Beschreibt Kanal C</li>
+                            <li> D   Beschreibt Kanal D</li>
+                            <li> F   Beschreibt alle DACs </li>
+                            </ul>
+                            Standartwert, falls ein falscher Kanal angegeben wird ist "F" 
+        \param value <b>16-Bit Wert</b><br>  Wird Automatisch in zwei 8 Bit Werte angepasst.  
+     */        
+    void writeDAC(char channel, int value);    
+ 
+ 
+ 
+     /*! Lädt ein 16-Bit Wert in den eingestellten Kanal. Der Wert wird direkt in das Inputregister geschrieben und kann mit der updateDAC-Funktion in das DAC-Register geschrieben werden */
+    /*!
+        \param channel <b>Einstellung des Ausgewählten Kanals</b><br>
+                            <ul>  
+                            <li> A   Lädt Kanal A</li> 
+                            <li> B   Lädt Kanal B</li>
+                            <li> C   Lädt Kanal C</li>
+                            <li> D   Lädt Kanal D</li>
+                            <li> F   Lädt alle DACs </li>
+                            </ul>
+                            Standartwert, falls ein falscher Kanal angegeben wird ist "F" 
+        \param value <b>16-Bit Wert</b><br>  Wird Automatisch in zwei 8 Bit Werte angepasst.  
+     */        
+    void loadDAC(char channel, int value); 
+    
+    
+    /*! Schreibt zuvor eingestellten Wert in das DAC Register (Laden mittels loadDAC-Funktion). Dieser Wert ist dann am Ausgang des entsprechenden DAC-Kanals zu messen. */
+    /*!
+        \param channel <b>Einstellung des Ausgewählten Kanals</b><br>
+                            <ul>  
+                            <li> A   Beschreibt Kanal A</li> 
+                            <li> B   Beschreibt Kanal B</li>
+                            <li> C   Beschreibt Kanal C</li>
+                            <li> D   Beschreibt Kanal D</li>
+                            <li> F   Beschreibt alle DACs </li>
+                            </ul>
+                            Standartwert, falls ein falscher Kanal angegeben wird ist "F"   
+     */        
+    void updateDAC(char channel);     
+               
+    protected:      
+        //! SPI Schnittstelle
+        SPI spi;    
+        //! Chipselect Pin     
+        DigitalOut daccs;                                  
+   
+    };
+
+#endif
diff -r 000000000000 -r 1acdcc576936 SWModule/PIDControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWModule/PIDControl.cpp	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,260 @@
+#include "mbed.h"
+#include "PIDControl.h"
+
+//====================================================================================================================================
+//                                                  Konstruktor und Regelprozess
+//====================================================================================================================================
+
+PIDControl::PIDControl(bool P_usr, float KP_usr, bool I_usr, float KI_usr, bool D_usr, float KD_usr){
+    
+      awu_gain = 0;                                                 // Anti-Windup deaktivieren
+      u_max = 32760;                                                // Maximale Stellgröße limitiert auf max. Integer Wert
+      u_min = -32760;                                               // Minimale Stellgröße limitiert auf min. Integer Wert
+      lockctrl = false;                                             // Regler frei parametrierbar
+      
+      e_last = 0;                                                   // Letzter Regelfehler ist 0
+      e_sum = 0;                                                    // Integralteil ist 0
+      u = 0;                                                        // Führungsgröße ist 0
+      awu_value = 0;                                                // Atin-Windup größe ist 0
+      status = 0;                                                   // Statusregister bisher nicht gefüllt
+      extfct = false;                                               // Keine Externe Funktion festgelegt
+      
+      P = P_usr;                                                    // P-Anteil on/off
+      KP = KP_usr;                                                  // P-Anteil Verstärkung
+      I = I_usr;                                                    // I-Anteil on/off
+      KI = KI_usr;                                                  // I-Anteil Verstärkung
+      D = D_usr;                                                    // D-Anteil on/off
+      KD = KD_usr;                                                  // D-Anteil Verstärkung
+     
+    }
+
+
+int16_t PIDControl::ctrltask (int16_t wsoll, int16_t yist, uint16_t time){
+    
+        setStatus(0);                                               // Regeltask aktiv - Flag aktivieren
+    
+        int16_t e = wsoll - yist;                                   // Regelfehler bestimmen             
+        e_sum = e_sum + e;                                          // Integralanteil bestimmen
+        
+        if(e > 0){                                                  // Regelfehler positiv
+            setStatus(4);                                           // Regelfehler positiv - Flag aktivieren
+            resetStatus(3);                                         // Regelfehler negativ - Flag deaktivieren
+            resetStatus(2);                                         // Regelfehler null - Flag deaktivieren            
+        }
+        
+        if(e < 0){                                                  // Regelfehler negativ
+            resetStatus(4);                                         // Regelfehler positiv - Flag deaktivieren
+            setStatus(3);                                           // Regelfehler negativ - Flag aktivieren
+            resetStatus(2);                                         // Regelfehler null - Flag deaktivieren            
+        }
+                       
+        if(e == 0){                                                 // Regelfehler null
+            resetStatus(4);                                         // Regelfehler positiv - Flag deaktivieren
+            resetStatus(3);                                         // Regelfehler negativ - Flag deaktivieren
+            setStatus(2);                                           // Regelfehler null - Flag aktivieren
+        }
+        
+        int16_t divisor = log2(time);                               // Bestimmung der Zeller um die das geschoben werden soll
+       
+        if(P){                                                      // P-Anteil bestimmen
+            P_var = (KP * e);                                       // u = Kp * e   
+        }
+        else{
+            P_var = 0;                                            // kein P-Anteil vorhanden
+        }
+            
+        if(D){                                                      // D-Anteil bestimmen
+            D_var = KD * time * (e - e_last);                       // u = Kd * Ta * (e - e_last) + P-Anteil 
+            D_var = D_var << 10;                                    // Zeitanpassung, da eingabe in µs  
+        }
+        else{
+            D_var = 0;                                              // kein D-Anteil vorhanden
+        }
+            
+        if(I){                                                      // I-Anteil bestimmen
+            I_var = (KI * (e_sum - awu_value));                     // u = Ki / Ta * (e_sum - awu_value) + P-Anteil + D-Anteil  
+            I_var = I_var  << divisor;                              // Division durch die Zeit
+        }
+        else{
+            I_var = 0;                                              // kein I-Anteil vorhanden
+        }               
+
+        resetStatus(1);                                             // I-Anteil an Grenze geraten
+
+        if(integrallimiter){                                        // Limiteriung des I-Anteils erforderlich?
+            if(e_sum >= i_max){                                     // Limitierung der Integralsumme zur oberen Schwelle
+                setStatus(1);                                       // Fehler I-Anteil über Grenzwerte
+                e_sum = i_max;                                      // Limitierung der Summe
+                awu_value = (e_sum - i_max) * awu_gain;             // Anti-Windup Berechnung
+            }
+
+            if(e_sum <= i_min){                                     // Limitierung  der Integralsumme zur unteren Schwelle
+                setStatus(1);                                       // Fehler I-Anteil über Grenzwerte
+                e_sum = i_min;                                      // Limitierung der Summe
+                awu_value = (e_sum - i_min) * awu_gain;             // Anti-Windup Berechnung
+            }
+        }  
+   
+        u = P_var + D_var + I_var;                                  // Reglerausgang definieren
+        
+        resetStatus(6);                                             // Regelgrenze max überschritten zurücksetzen
+        resetStatus(7);                                             // Regelgrenze min überschritten zurücksetzen  
+    
+        if(u >= u_max){                                             // Limitierung des Regelausgangs zur oberen Schwelle
+            setStatus(7);                                           // Fehler Regelgrenze max überschritten
+            u = u_max;                                              // Ausgabe des Stellgrößen Limits 
+        }
+
+        if(u <= u_min){                                             // Limitierung des Regelausgangs zur unteren Schwelle
+            setStatus(6);                                           // Fehler Regelgrenze min überschritten
+            u = u_min;                                              // Ausgabe des Stellgrößen Limits 
+        }      
+            
+        e = e_last;                                                 // Regelfehler als letzten Regelfehler übernehmen
+        resetStatus(0);                                             // Regeltask aktiv - Flag deaktivieren
+        
+    return u;                                                       // Ausgabe der Stellgröße  
+   
+    }
+
+//====================================================================================================================================
+//                                                   Setter und Getter Funktionen
+//====================================================================================================================================
+   
+bool PIDControl::setKP(bool P_usr, float KP_usr){                   // Setzen des P-Anteils
+    
+    if(!lockctrl){
+        P = P_usr;                                                  // P-Anteil on/off
+        KP = KP_usr;                                                // P-Anteil Verstärkung
+        
+        return true;                                                // Setzen der Werte erfolgreich     
+        }
+    else{ 
+        return false;                                               // Setzen der Werte nicht erfolgreich
+        }   
+    } 
+
+    
+bool PIDControl::setKI(bool I_usr, float KI_usr){                   // Setzen des I-Anteils
+    
+    if(!lockctrl){
+        I = I_usr;                                                  // I-Anteil on/off
+        KI = KI_usr;                                                // I-Anteil Verstärkung
+        
+        return true;                                                // Setzen der Werte erfolgreich     
+        }
+    else{ 
+        return false;                                               // Setzen der Werte nicht erfolgreich
+        }   
+    } 
+
+
+bool PIDControl::setKD(bool D_usr, float KD_usr){                   // Setzen des D-Anteils
+    
+    if(!lockctrl){
+        D = D_usr;                                                  // D-Anteil on/off
+        KD = KD_usr;                                                // D-Anteil Verstärkung
+        
+        return true;                                                // Setzen der Werte erfolgreich     
+        }
+    else{ 
+        return false;                                               // Setzen der Werte nicht erfolgreich
+        }   
+    } 
+
+
+bool PIDControl::setAWU(float awu_gain_usr){                        // Setzen des Anti-Windups
+    
+    if(!lockctrl){
+        awu_gain = awu_gain_usr;                                    // Anti-Windup Verstärkung
+        
+        return true;                                                // Setzen des Wertes erfolgreich     
+        }
+    else{ 
+        return false;                                               // Setzen des Wertes nicht erfolgreich
+        }   
+    }  
+
+void PIDControl::setIlimits(bool integrallimiter_usr, int16_t i_max_usr, int16_t i_min_usr){ // Setzen des Integrallimits
+
+    if(!lockctrl){
+        integrallimiter = integrallimiter_usr;                      // Integrallimits aktivieren
+        i_max = i_max_usr;                                          // maximaler I-Anteil 
+        i_min = i_min_usr;                                          // minimaler I-Anteil   
+    }
+}
+
+void PIDControl::setUlimits(int16_t u_max_usr, int16_t u_min_usr){  // Setzen des Ausgangsgrößenlimits
+
+    if(!lockctrl){
+        u_max = u_max_usr;                                          // maximale Stellgröße
+        u_min = u_min_usr;                                          // minimale Stellgröße  
+    }
+}
+        
+ 
+    
+void PIDControl::lock(){
+         lockctrl = true;                                           //  Einstellung der Regelparamieter sperren             
+    }
+
+
+void PIDControl::unlock(){
+          lockctrl = false;                                         // Einstellung der Regelparamter freigeben 
+    } 
+ 
+    
+uint8_t PIDControl::getStatus(){ 
+    return status;                                                  // Rückgabe des aktuellen Statusvektors
+}
+
+
+void PIDControl::setERFFCT(void (*EXTERN_CTRL_HANDLER)(void)){         // Adresse zur externen Funktion übergeben und Freigabe setzen
+          extfct = true;                                               // Externe Funktion vorhanden. Freigabe setzen.
+          CTRL_HANDLER = EXTERN_CTRL_HANDLER;                          // Funktionspointer der Funktion übernehmen     
+    } 
+
+//====================================================================================================================================
+//                                                   Interne Funktionen
+//====================================================================================================================================
+
+
+int16_t PIDControl::log2(int16_t a){                                // Bestimmt die nächstkleinere Zweierpotenz der Zahl a
+  
+        if(a == time_last){
+            return time_last_result;                                // Aktueller Wert entspricht letztem Wert
+            }               
+        
+         a = time_last;                                             // Speichert aktuellen Wert
+  
+         static const int DeBruijnFolge[32] = { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31};
+
+            a |= a >> 1;                                            // Runden auf die kleinste Stelle
+            a |= a >> 2;
+            a |= a >> 4;
+            a |= a >> 8;
+            a |= a >> 16;
+           
+           time_last_result = DeBruijnFolge[(uint32_t)(a * 0x07C4ACDDU) >> 27];     // Ausgabe der passenden Zweierpotenz
+           
+    return time_last_result; 
+  }
+
+
+void PIDControl::setStatus(int bit){ 
+    
+    status |= (1 << bit);                                           // Setzt das vorher ausgewählte Bit    
+    
+    if((extfct) && (bit >= 5 )){                                    // Wenn externe Funktionen aktiviert sind und ein schwerwiegender Fehler abgelegt wird
+        (*CTRL_HANDLER)();                                          // Aufruf der Externen Funktion   
+    }  
+}
+
+
+void PIDControl::resetStatus(int bit){ 
+
+    int temp = 0xFF;                                                // Maske erstellen
+    temp ^= (1 << bit);                                             // Maske anpassen 
+    status &= temp;                                                 // Resetzen des entsprechenden Bits
+                                     
+}
diff -r 000000000000 -r 1acdcc576936 SWModule/PIDControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWModule/PIDControl.h	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,226 @@
+#include "mbed.h"
+
+#ifndef PIDControl_h
+#define PIDControl_h
+
+/*! Diese Klasse erstellt einen PID-Regler. die einzelnen Regeranteile können bei der Initialisierung seperat einsgestellt werden.
+    Bei der Initialisierung des Reglers bzw. der Klasse wird der Statusvektor resettet und die einzelnen Anteile werden auf null gesetzt und gesperrt.
+    Solange die Variable Lock nicht wahr ist, kann über die Funktionen setKP(), setKI() und setKD() der Regler parametriert werden.
+    Es ist zudem möglich die Regelgrenzen des Regelers festzulegen. Bei Überschreiten der Regelgrenzen wird ein Eintrag in dem Statusvektor erzeugt.
+    Bei einer Änderung im Statusvektor kann eine externe Funktion aufgerufen werden, die dann den Statusvektor auswertet. 
+    Der Regeltask ctrltask sollte in regelmäßigen Abständen aufgerufen werden. Wichtig dabei ist eine Stänige Übergabe des Ist und Soll-Werts sowie die Regelzeit.
+    \image html http://developer.mbed.org/media/uploads/ChrisselH/pid-controller.jpg "Schematischer Regleraufbau ohne Statusvektoren und Fehlermeldungen"
+ * @code
+ * #include "mbed.h"
+ * #include "PIDControl.h"        
+ *
+ * int16_t ist_value;                                   // Ist-Wert der Strecke
+ * int16_t soll_value;                                  // Soll-Wert der Strecke
+ * int16_t stell_value;                                 // Stell-Wert der Strecke
+ *
+ * uint8_t statusvektor;                                // Statusvektor des Reglers
+ *
+ * int main() {
+ *    
+ *     PIDControl PIregler(1,50.8,1,0.5,0,0);          // PI-Regler mit KP = 50,8 und KI = 0,5
+ *
+ *     PIregler.setIlimits(1,6000,1000);                // Aktivierung der maximale und minimale Größe des I-Anteils
+ *
+ *     PIregler.setAWU(5);                              // Die Differenz zwischen I-Anteil und Limit wird mit 
+ *                                                      // Verstärkung zurückgeführt
+ *
+ *     PIregler.setUlimits(7000,500);                   // Limitierung der Stellgröße
+ *
+ *     PIregler.lock();                                 // Sperrt weitere Einstellung an dem Regler
+ * 
+ *      while(1){
+ *      
+ *          stell = PIregler.ctrltask(ist, soll, 1000); // Die Schleife wiederholt sich alle 1kHz  
+ * 
+ *          statusvektor = PIregler.getStatus();        // Status des Reglers wird ausgelesen
+ *
+ *        wait(0.001);                                  // Regler wird alle 1kHz aufgerufen
+ *      }
+ *    }
+ *
+ * @endcode
+ */
+
+class PIDControl
+{
+    public:
+
+        /*! Konstruktor zum Erstellen einer Instanz mit einer vom User festgelegten Größe */
+        /*!
+            \param P <b>P-Anteil</b> Aktivert den P-Anteil, wenn der Wert 1 ist
+            \param KP <b>P-Anteil</b> Verstärkung des P-Anteils
+            \param I <b>I-Anteil</b> Aktivert den I-Anteil, wenn der Wert 1 ist
+            \param KI <b>I-Anteil</b> Verstärkung des I-Anteils
+            \param D <b>D-Anteil</b> Aktivert den D-Anteil, wenn der Wert 1 ist
+            \param KD <b>D-Anteil</b> Verstärkung des D-Anteils
+        */      
+        PIDControl(bool P_usr, float KP_usr, bool I_usr, float KI_usr, bool D_usr, float KD_usr);
+        
+        /*! Destruktor entfernt den Regler */
+        ~PIDControl(){};
+            
+        /*! Reglerprozess. Rückgabewert ist die Führungsgröße */
+        /*!
+            \param usoll <b>SOLL-Wert</b> Soll-Wert der Regelstrecke
+            \param yist <b>IST-Wert</b> Ist-Wert der Regelstrecke
+            \param time <b>Zeitkonstatnte</b> vergangene Zeit seit dem letzen Regeltask in ganzen Mirkosekunden (1ms = 1000µs)
+        */ 
+        int16_t ctrltask (int16_t wsoll, int16_t yist, uint16_t time);
+        
+    
+        /*! Ermöglich Zugriff auf die Reglerparameter des P-Anteils. Rückgabe Wert ist eins, wenn die Reglerwerte gespeichert worden sind.*/
+        /*!
+            \param P <b>P-Anteil</b> Aktivert den P-Anteil, wenn der Wert 1 ist
+            \param KP <b>P-Anteil</b> Verstärkung des P-Anteils
+        */
+        bool setKP(bool P_usr, float KP_usr);
+    
+        /*! Ermöglich Zugriff auf die Reglerparameter des I-Anteils. Rückgabe Wert ist eins, wenn die Reglerwerte gespeichert worden sind.*/
+        /*!
+            \param I <b>I-Anteil</b> Aktivert den I-Anteil, wenn der Wert 1 ist
+            \param KI <b>I-Anteil</b> Verstärkung des I-Anteils
+        */
+        bool setKI(bool I_usr, float KI_usr);
+        
+        /*! Ermöglich Zugriff auf die Reglerparameter des D-Anteils. Rückgabe Wert ist eins, wenn die Reglerwerte gespeichert worden sind.*/
+        /*!
+            \param D <b>D-Anteil</b> Aktivert den D-Anteil, wenn der Wert 1 ist
+            \param KD <b>D-Anteil</b> Verstärkung des D-Anteils
+        */
+        bool setKD(bool D_usr, float KD_usr);    
+        
+        /*! Ermöglich Zugriff auf den Anti-Windup zum begrenzen des I-Anteils*/
+        /*!
+            \param awu_gain <b>Anti-Windup Verstärkung</b> Rückführung der Differenz zwischen Stellgröße und Begrenzung mit einer Verstärkung in den I-Anteil
+        */
+        bool setAWU(float awu_gain_usr);
+                
+        /*! Setzt die Limits der Stellgröße U bzw. des Ausgangs des Reglers*/
+        /*!
+            \param u_max <b>maximales Limit</b> maximale Ausgangsgröße
+            \param u_min <b>minimales Limit</b> minimale Ausgangsgröße
+        */
+        void setUlimits(int16_t u_max_usr, int16_t u_min_usr);
+        
+        /*! Setzt die Limits des Integralanteils */
+        /*!
+            \param integrallimiter <b>Aktiviert den Limiter</b> aktiviert eine seperate Begrenzung des I-Anteils
+            \param i_max <b>maximales Limit</b> maximaler I-Anteil
+            \param i_min <b>minimsler Limit</b> minimaler I-Anteil
+        */
+        void setIlimits(bool integrallimiter_usr, int16_t i_max_usr, int16_t i_min_usr);
+        
+        /*! Sperrt den Zugriff auf die Reglerparameter */
+        void lock();
+        
+        /*! Erlaubt den Zugriff auf die Reglerparameter */
+        void unlock();
+        
+        /*! Liest den Status des Reglers aus */    
+        uint8_t getStatus();
+        
+        /*! Setzt eine Routine die verwendet wird, wenn ein schwerwiegender Fehler im Statusvektor gesetzt wird.*/ 
+        /*!
+            \param BUFFER_HANDLER Adresse zur weiteren Routine
+         */ 
+        void setERFFCT(void (*CTRL_HANDLER)(void));  
+           
+        private: 
+        /*! Setzt ein Bit im Statusvektor. Wenn der Rückgabewert True ist, würde der Wert übernommen*/
+        /*!
+            \param bit  Welches Bit der Zelle gesetzt werden soll
+        */     
+        void setStatus(int bit);
+     
+        /*!ResSetzt ein Bit im Statusvektor. Wenn der Rückgabewert True ist, würde der Wert übernommen*/
+        /*!
+            \param bit  Welches Bit der Zelle zurück gesetzt werden soll
+        */     
+        void resetStatus(int bit);
+        
+        //! Zeitwert der letztes Berechnung des Verschiebungswerts
+        int16_t time_last;
+        //! Dazugehöriger Verschiebungswert
+        int16_t time_last_result;
+         //! Führungsgröße und Rückgabe des Reglertasks
+        int16_t u; 
+        //! Freigabe zur Verwendung externer Funktionen 
+        bool extfct;
+        //! Externe Funktion bei schwerwiegenden Fehlern
+        void (*CTRL_HANDLER)(void);
+        //! Reglereinstellungen können nicht mehr verändert werden.
+        bool lockctrl;
+        //! Limits für den Integralanteil aktiv
+        bool integrallimiter;
+        //! Vorheriger Ístwert des Regelfehlers
+        int16_t e_last;
+        //! Integral über alle bisherigern Werte
+        int16_t e_sum;
+        //! Antiwindup Wert mit Verstärkung awu_gain
+        int16_t awu_value; 
+        //! Regleranteil des P-Regler
+        int16_t P_var;
+        //! Regleranteil des I-Regler
+        int16_t I_var;
+        //! Regleranteil des D-Regler
+        int16_t D_var;  
+    
+        //! Funktion zum bestimmen der zweier Potenz
+        /*!
+            \param a  16-Bit Integer bei der die Zweierpotenz bestimmt werden soll
+        */
+        int16_t log2(int16_t a);
+        
+    
+    protected:
+    
+        //! Aktiviert den Proportional-Anteil
+        bool P;
+        //! Aktiviert den Integral-Anteil
+        bool I;
+        //! Aktiviert den Differnetial-Anteil
+        bool D;  
+        
+        //! Verstärkung für den Proportional-Anteil
+        float KP;
+        //! Verstärkung für den Integral-Anteil
+        float KI;
+        //! Verstärkung für den Differnetial-Anteil
+        float KD;
+        
+        //! Maximale Führungsgröße
+        int16_t u_max;
+        //! Minimale Führungsgröße
+        int16_t u_min;
+        //! Maximaler Integralanteil
+        int16_t i_max;
+        //! Minimaler Integralanteil
+        int16_t i_min;
+        //! Anti-Windup Verstärkung
+        float awu_gain;
+        
+
+        /*! 8-Bit Statusvektor:
+                -  [7] Regelgrenze max überschritten (<b>EXTFCT</b>)<br>
+                -  [6] Regelgrenze min unterschritten (<b>EXTFCT</b>)<br>
+                -  [5] Fehler bei der Berechnung (<b>EXTFCT</b>)<br>
+                -  [4] aktueller IST-Wert < Soll-Wert<br>
+                -  [3] aktueller IST-Wert > Soll-Wert<br>
+                -  [2] Regelabweichung ist null<br>
+                -  [1] I-Anteil Limit erreicht<br>
+                -  [0] Reglertask aktiv<br> 
+            Bei schwerwiegenden Fehlern wird eine externe Routine (<b>EXTFCT</b>) aufgerufen, falls diese angegeben wurde.          
+        */
+        uint8_t status;
+ 
+    };
+    
+    
+
+
+#endif
diff -r 000000000000 -r 1acdcc576936 SWModule/RingBuffer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWModule/RingBuffer.cpp	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,112 @@
+#include "mbed.h"
+#include "RingBuffer.h"
+
+//====================================================================================================================================
+//                                 Konstruktor und Schreib/Lese Funktionen
+//====================================================================================================================================
+
+RingBuffer::RingBuffer(const int size){
+    
+    buffer_size = size;                                                         // Ringbuffergröße festlegen
+    buffer.data = new uint32_t [size];                                          // Setzt die Dimension des Daten Arrays
+    buffer.status = new uint8_t [size];                                         // Setzt die Dimension des Status Arrays
+    buffer.status[0] = 0x00;                                                    // Kein Status vorhanden bei Beginn
+    
+    extfct = false;                                                             // Externe Funktion bei fast vollem Buffer
+    bufferfull = false;                                                         // Buffer ist voll, kein Schreiben möglich 
+    bufferempty = true;                                                         // Buffer ist leer, kein Lesen möglich
+    read_pointer = 0;                                                           // Lesezeiger auf Null setzen
+    write_pointer = 0;                                                          // Schreibezeiger auf Null setzen   
+     
+}
+
+bool RingBuffer::writeBuffer(uint32_t inputdata){                               // Funktion zum beschreiben des Buffers
+
+    if(!bufferfull){                                                            // Prüfen ob der Buffer voll ist
+
+        buffer.data[write_pointer] = inputdata;                                 // Schreibt Daten in die aktuelle Zelle
+        write_pointer++;                                                        // Zählt den Schreibezeiger um eins Hoch
+        buffer.status[write_pointer] = buffer.status[write_pointer - 1];        // Übernehme den vorherigen Statuswert
+         
+        if(write_pointer == buffer_size){                                       // Zeiger am Ende des Buffers
+            write_pointer = 0;                                                  // Schreibezeiger auf Null setzen   
+        }
+    
+        if(extfct && (read_pointer + buffer_size - write_pointer) < 10){       // Externe Methode bei einem Abstand im Fifo von kleiner 10
+            (*BUFFER_HANDLER)();                                               // Aufruf der Externen Funktion   
+        }
+           
+        if(write_pointer == read_pointer){                                      // Schreibzeiger steht auf Lesezeiger
+            bufferfull = true;                                                  // Buffer voll, kann nicht mehr Beschrieben werden
+
+        }
+        else{
+            bufferempty = false;                                                // Buffer ist nicht leer, kann gelesen werden
+     
+        } 
+      return true;                                                              // Rückgabe das der Wert beschrieben worden ist       
+    } 
+      return false;                                                             // Rückgabe das der Wert nicht beschrieben worden ist              
+}
+
+uint32_t RingBuffer::readBuffer(){                                              // Funktion zum beschreiben des Buffers
+
+        uint32_t outputdata;                                                    // Variable zur Übergabe der Daten
+
+    if(!bufferempty){                                                           // Prüfen ob der Buffer leer ist
+
+        outputdata = buffer.data[read_pointer];                                 // Auslesen des Wertes an der aktuellen Stelle
+        read_pointer++;                                                         // Zählt den Lesezeiger um eins Hoch
+             
+        if(read_pointer == buffer_size){                                        // Zeiger am Ende des Buffers
+            read_pointer = 0;                                                   // lesezeiger auf Null setzen   
+        }
+    
+        if(read_pointer== write_pointer){                                       // Lesezeiger steht auf Schreibzeiger
+            bufferempty = true;                                                 // Buffer leer, kann nicht mehr gelesen werden
+        }
+        else{
+            bufferfull = false;                                                 // Buffer ist nicht voll, kann geschrieben werden     
+        }
+        
+    }
+    else{                                                                       // Buffer leer
+        outputdata = 0x00;                                                      // Rückgabe = 0
+    }
+                
+    return outputdata;                                                          // Ausgabe des Werts
+} 
+
+//====================================================================================================================================
+//                                 Setter und Getter Funktionen
+//====================================================================================================================================
+
+uint8_t RingBuffer::getBufferStatus(){ 
+    return buffer.status[read_pointer];                                          // Rückgabe des aktuellen Statuswerts
+}
+
+bool RingBuffer::setBufferStatus(int bit){ 
+    
+    if(bit < 8){
+        buffer.status[write_pointer] |= (1 << bit);                               // Setzt das vorher ausgewählte Bit
+        return true;                                                              // Setzen erfolgreich.       
+     }
+        
+     return false;                                                                // Setzen nicht erfolgreich.        
+}
+
+bool RingBuffer::resetBufferStatus(int bit){ 
+    
+    if(bit < 8){
+        buffer.status[write_pointer] ^= (1 << bit);                               // Resetzt das vorher ausgewählte Bit
+        return true;                                                              // Restzen erfolgreich.       
+     }
+        
+     return false;                                                                // Resetzen nicht erfolgreich.        
+}
+
+
+void RingBuffer::setBF_METHODE(void (*EXTERN_BUFFER_HANDLER)(void)){              // Adresse zur externen Funktion übergeben und Freigabe setzen
+          extfct = true;                                                          // Externe Funktion vorhanden. Freigabe setzen.
+          BUFFER_HANDLER = EXTERN_BUFFER_HANDLER;                                 // Funktionspointer der Funktion übernehmen     
+    }     
\ No newline at end of file
diff -r 000000000000 -r 1acdcc576936 SWModule/RingBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SWModule/RingBuffer.h	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,117 @@
+#include "mbed.h"
+
+#ifndef RingBuffer_h
+#define RingBuffer_h
+
+/*! Diese Klasse erstellt einen 32 Bit Ringbuffer mit einen vom Nutzer vorgegebenen Größenbereich. In dem Ringbuffer können 
+entsprechend 32 Bit Daten für Messaufzeichnungen genutzt werden. Zudem gibt es 8 Bit in einem Statusregister die frei definiert
+werden können. Es gibt für jedes einzelne Bit des Statusregisters eine Setter und Getter Methode. Nachdem der Ringbuffer komplett 
+beschrieben wurde, wird wieder der erste Wert überschrieben. Wenn der Abstand zwischen Lese- und Schreibezeiger zu gering wird,
+kann eine vom User definierte Funktion aufgerufen werden.
+ * @code
+ * #include "mbed.h"
+ * #include "RingBuffer.h"
+ *
+ * int Event_Routine(){ .... }                        // Irgendeine Funktion die bei fast vollem Fifo aufgerufen wird           
+ *
+ * bool write;
+ * uint8_t status;
+ *
+ * int main() {
+ *    
+ *     Ringbuffer adcbuffer(250);                       // Erstellen einer Instanz mit 250 Werten
+ * 
+ *     write = adcbuffer.writeBuffer(16658);            // Schreibt einen Wert in den Buffer. Wenn Rückgabe write
+ *                                                      // true ist wurde dieser erfolgreich beschrieben.
+ *
+ *     adcbuffer.setBF_METHODE(Event_Routine);          // Bei fast vollem Fifo wird die Routine aufgerufen
+ *
+ *     adcbuffer.setBufferStatus(4);                    // Setzt das 4. Bit des Statusregisters
+ *
+ *     adcbuffer.resetBufferStatus(6);                  // Löscht das 6. Bit des Statusregisters
+ *
+ *     status = adcbuffer.getBufferStatus();            // Liest das Statusregister aus
+ *
+ *      while(1){
+ *        printf("Value: %i\r\n", adcbuffer.readBuffer());   // Ausgabe der geschriebenen Werte
+ *      }
+ *    }
+ *
+ * @endcode
+ */
+
+
+class RingBuffer
+{
+
+    public:
+    /*! Konstruktor zum Erstellen einer Instanz mit einer vom User festgelegten Größe */
+    /*!
+        \param size <b>Größe</b> Anzahl der maximal gespeicherten Werte im Buffer
+    */     
+    RingBuffer(const int size);
+    
+    /*! Destruktor entfernt den RingBuffer */
+    ~RingBuffer(){};
+    
+    /*! Schreibt Daten in die aktuelle Zelle. Wenn die Rückgabe true ist, dann wurde der Wert geschrieben. Wenn nicht, ist der Buffer voll.  */
+    /*!
+        \param inputdata <b>Daten</b> 32 Bit Integer Daten für die aktuelle Zelle
+    */     
+    bool writeBuffer(uint32_t inputdata);
+
+    /*! Setzt ein Bit im Statusvektor des Buffers. Wenn der Rückgabewert True ist, würde der Wert übernommen*/
+    /*!
+        \param bit  Welches Bit der Zelle gesetzt werden soll
+    */     
+    bool setBufferStatus(int bit);
+ 
+    /*!ResSetzt ein Bit im Statusvektor des Buffers. Wenn der Rückgabewert True ist, würde der Wert übernommen*/
+    /*!
+        \param bit  Welches Bit der Zelle zurück gesetzt werden soll
+    */     
+    bool resetBufferStatus(int bit);
+    
+    
+    /*! Liest den Status aus der aktuelle Zelle und gibt diesen zurück. */    
+    uint8_t getBufferStatus();
+    
+ 
+    /*! Liest Daten aus der aktuelle Zelle. Wenn die Werte nicht ausgelesen werden konnten, dann ist der Rückgabewert 0 */    
+    uint32_t readBuffer();
+      
+     /*! Setzt eine weitere Routine die verwendet werden kann, wenn der Buffer fast voll ist. Um die Daten z.B. zu übernehmen */ 
+     /*!
+           \param BUFFER_HANDLER Adresse zur weiteren Routine
+     */ 
+    void setBF_METHODE(void (*BUFFER_HANDLER)(void));   
+    
+    protected:   
+    //! Größe des Buffers
+    int buffer_size;
+    //! Lesezeiger der auf die nächste zulesenede Stelle zeigt
+    uint32_t read_pointer;
+    //! Schreibzeiger der auf die nächste zubeschreibene Stelle zeigt
+    uint32_t write_pointer; 
+    //! Buffer ist voll
+    bool bufferfull;
+    //! Buffer ist leer
+    bool bufferempty;
+    //! Freigabe zur Verwendung externer Funktionen 
+    bool extfct;
+    //! Externe Funktion bei fast vollem Buffer aufrufen
+    void (*BUFFER_HANDLER)(void);  
+    
+    private:
+    //! Eigentlicher Datenspeicher mit einem 32Bit Daten- und einem 8Bit Statusvektor    
+    struct buffer          
+    {       uint32_t *data;
+            uint8_t *status;   
+     };
+    //Erstellt eine Instanz des Buffers
+    buffer buffer;       
+            
+};
+    
+
+#endif
diff -r 000000000000 -r 1acdcc576936 TIM/QUADRATURE.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TIM/QUADRATURE.cpp	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,226 @@
+#include "mbed.h"
+#include "QUADRATURE.h"
+#include "cmsis_nvic.h"
+
+//====================================================================================================================================
+//                                   Initialisieren und mappen der Kanäle, Timer etc
+//====================================================================================================================================
+QUADRATURE *QUADRATURE::instance;                                                       // Pointer zur Adresse der Instanz
+
+
+QUADRATURE::QUADRATURE(int tim, int mode, char _CI1_PORT, int _CI1_PIN, int CI1_POL,  char _CI2_PORT, int _CI2_PIN, int CI2_POL): CI1_PORT(_CI1_PORT), CI1_PIN(_CI1_PIN), CI2_PORT(_CI2_PORT), CI2_PIN(_CI2_PIN)
+{   
+  
+    TIMERCARRY = 0;                                                                     // bei neuem Objekt den entsprechenden Timercarry auf 0 setzen
+    instance = this;                                                                    // Instanz zuweisung zum neu generierten Objekt
+    extfct = false;                                                                     // Externe Funktion bei Timer Interrupt deaktiviert
+
+    //Konfiguration des Timers
+       switch(tim){                                                                     // Konfiguration jedes einzelnen Timers, durch Auswahl    
+                    case 1:                                                             // TIM1
+                        RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;                             // Timer 1 aktivieren
+                        tipo = TIM1;                                                    // Pointer auf Timer1 zuweisen
+                        temp_ITM = TIM1_UP_TIM10_IRQn;                                  // NVIC Nummer für den Updateinterrupt Timer 1
+                        NVIC->ISER[0] &= ~(1 << TIM1_UP_TIM10_IRQn);                    // Interrupt Handler für den Timer 1 aktivieren
+                    break;
+                    
+                    case 2:                                                             // TIM2
+                        RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;                             // Timer 2 aktivieren
+                        tipo = TIM2;                                                    // Pointer auf Timer2 zuweisen
+                        temp_ITM =  TIM2_IRQn;                                          // NVIC Nummer für den Updateinterrupt Timer 2
+                        NVIC->ISER[0] &= ~(1 << TIM2_IRQn);                             // Interrupt Handler für den Timer 2 aktivieren
+                    break;
+                    
+                    case 3:                                                             // TIM3
+                        RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;                             // Timer 3 aktivieren
+                        tipo = TIM3;                                                    // Pointer auf Timer3 zuweisen
+                        temp_ITM =  TIM3_IRQn;                                          // NVIC Nummer für den Updateinterrupt Timer 3
+                        NVIC->ISER[0] &= ~(1 << TIM3_IRQn);                             // Interrupt Handler für den Timer 3 aktivieren
+                    break;   
+
+                    case 4:                                                             // TIM4
+                        RCC->APB1ENR |= RCC_APB1ENR_TIM4EN;                             // Timer 4 aktivieren 
+                        tipo = TIM4;                                                    // Pointer auf Timer4 zuweisen
+                        temp_ITM =  TIM4_IRQn;                                          // NVIC Nummer für den Updateinterrupt Timer 4
+                        NVIC->ISER[0] &= ~(1 << TIM4_IRQn);                             // Interrupt Handler für den Timer 4 aktivieren                        
+                    break;                
+
+                    case 5:                                                             // TIM5
+                        RCC->APB1ENR |= RCC_APB1ENR_TIM5EN;                             // Timer 5 aktivieren 
+                        tipo = TIM5;                                                    // Pointer auf Timer5 zuweisen
+                        temp_ITM =  TIM5_IRQn;                                          // NVIC Nummer für den Updateinterrupt Timer 5
+                        NVIC->ISER[1] &= ~(1 << (TIM5_IRQn-31));                        // Interrupt Handler für den Timer 5 aktivieren
+                    break;
+                    
+                    default:                                                            // keinen Timer ausgewählt und Fehlermeldung
+                        printf("\n \n \r \n  Falscher Timer ausgewahlt! \n \n \r");
+                        return;
+                }   
+                
+        tipo->SMCR  = mode;                                                             // Schreibt den aktuellen Modus in das SMCR Register (Slave Mode)
+        tipo->CCMR1 = 0xF1F1;                                                           // Mappen der Capture Inputs 1 und 2 auf Timer Input 1 und 2
+        tipo->CCMR2 = 0x0000;                                                           // Kein mappen der Capture Inputs 3 und 4
+        tipo->CCER  = 0x0011;                                                           // Capture Inputs 1 und 2 aktivieren 
+            
+        // Konfiguration der Pins      
+        setGPIO(CI1_PORT, CI1_PIN, tim);                                                // Setzt den Port Pin für CI1        
+        setGPIO(CI2_PORT, CI2_PIN, tim);                                                // Setzt den Port Pin für CI2
+        
+        // Konfiguration der Polarität 
+        if(CI1_POL ==  1){                                                              // Polarität für CI1 ändern auf fallende Flanke 
+                 tipo->CCER |= 0x0002;                                                   
+            } 
+        if(CI2_POL ==  1){                                                              // Polarität für CI2 ändern auf fallende Flanke 
+                 tipo->CCER |= 0x0020;                                                   
+            } 
+            
+        // Konfiguration der Interrupt Routine
+        NVIC_SetVector(temp_ITM, (uint32_t) &_UPDATE_HANDLER);                          // Adresse zum IRQ Handler des entsprechenden Timers
+        NVIC_SetPriority(temp_ITM, 0);                                                  // Festlegen der Priorität (Höchste, damit das nächste Increment mit gezählt wird)
+        tipo->DIER |= 0x0001;                                                           // Update Interrupt Einstellung im Timer aktivieren
+        
+                                                                         
+    }
+
+
+
+void QUADRATURE::setGPIO(char port, int pin, int tim){                                 // Funktion zum Mappen des Port Pins auf die Alternative Funktion für den Timer Eingang
+    
+     GPIOchoose(port);                                                                 // Wählt den passenden Pointer zum Port aus
+    
+     portpo->MODER  |= (1 <<((2*pin)+1));                                              // Alternative Funktion 0x10 mit Maske (2 Bit pro Pin) 
+     portpo->OTYPER |= (1 << pin);                                                     // Definition als Eingang 0x1 mit Open Drain 
+     
+         if(pin > 7){                                                                  // Ausgänge 8 bis 15 sind im höheren Register AFR[1]
+            if(tim < 3){                                                               // Für Timer 1 und Timer 2 (Alternatve Funktion 01)
+                 portpo->AFR[1] |= (1 << (4*(pin-8)));                                 // Alternative Funktion mit Maske für AF01
+            }
+            else{                                                                      // Für Timer 3, Timer 4 und Timer 5 (Alternative Funktion 10) 
+                 portpo->AFR[1] |= (1 << (4*(pin-8))+1);                               // Alternative Funktion mit Maske für AF02          
+            }   
+         }
+         else{                                                                         // Ausgänge 0 bis 7 sind im im unteren Register AFR[0]
+            if(tim < 3){                                                               // Für Timer 1 und Timer 2 (Alternatve Funktion 01)
+                 portpo->AFR[0] |= (1 << (4*pin));                                     // Alternative Funktion mit Maske für AF01
+            }
+            else{                                                                      // Für Timer 3, Timer 4 und Timer 5 (Alternative Funktion 10)  
+                 portpo->AFR[0] |= (1 << ((4*pin)+1));                                 // Alternative Funktion mit Maske für AF02          
+            }                       
+         }            
+    } 
+
+//====================================================================================================================================
+//                              Eventhandler für Timer und Externer Eingang
+//====================================================================================================================================
+
+void QUADRATURE::UPDATE_HANDLER(void){                                                  // Interrupt Service Routine für Update Events
+    
+            tipo->SR ^= 0x0001;                                                         // Flag löschen (Register xor mit Flag) 
+
+        if (getTIM() > 1){     
+                TIMERCARRY--;                                                           // Carryvariable -1 da Unterlauf
+         }
+         else{
+                TIMERCARRY++;                                                           // Carryvariable 1 da Überlauf
+             }  
+             
+        if(extfct == true){                                                             // Externe Funktion vorhanden?
+                    (*IRQ_HANDLER_EXTERN)();                                            // Aufruf der Externen Funktion
+            }               
+    }
+
+
+//====================================================================================================================================
+//                              Setter- und Getter-Funktionen
+//====================================================================================================================================
+
+void QUADRATURE::startTIM(){
+        NVIC_EnableIRQ(temp_ITM);                                                       // Enable den IRQ Handler
+        tipo->CR1 = 0x0001;                                                             // Starte Timer
+    }
+    
+void QUADRATURE::stopTIM(){
+        tipo->CR1 = 0x0000;                                                             // Stoppe Timer
+        NVIC_DisableIRQ(temp_ITM);                                                      // Disable den IRQ Handler
+    }
+        
+unsigned int QUADRATURE::getTIM(){
+        return   tipo->CNT;                                                             // Gibt aktuellen Timerwert zurück
+    }
+    
+signed short QUADRATURE::getCARRY(){
+        return   TIMERCARRY;                                                            // Gibt aktuellen Timercarry zurück
+    }
+        
+void QUADRATURE::setTIM(int pre, int arr){
+        tipo->PSC = pre;                                                                // Prescaler (Wert + 1)
+        tipo->ARR = arr;                                                                // Auto reload   
+    }
+
+void QUADRATURE::setUpRes(){
+        
+        GPIOchoose(CI1_PORT);                                                           // Wählt den passenden Pointer zum Port von CI1 aus  
+        portpo->PUPDR  |= (1 << ((2*CI1_PIN)));                                         // Setzt den Pull up für den entsprechenden Port Pin von CI1
+
+        GPIOchoose(CI2_PORT);                                                           // Wählt den passenden Pointer zum Port von CI2 aus  
+        portpo->PUPDR  |= (1 << ((2*CI2_PIN)));                                         // Setzt den Pull up für den entsprechenden Port Pin von CI2                
+    }
+        
+void QUADRATURE::setDownRes(){
+
+        GPIOchoose(CI1_PORT);                                                           // Wählt den passenden Pointer zum Port von CI1 aus    
+        portpo->PUPDR  |= (1 << ((2*CI1_PIN)+1));                                       // Setzt den Pull down für den entsprechenden Port Pin von CI1
+
+        GPIOchoose(CI2_PORT);                                                           // Wählt den passenden Pointer zum Port von CI2 aus 
+        portpo->PUPDR  |= (1 << ((2*CI2_PIN)+1));                                       // Setzt den Pull down für den entsprechenden Port Pin von CI2           
+    }
+    
+void QUADRATURE::setIRQ_METHODE(void (*IRQ_HANDLER_METHODE)(void)){                     // Adresse zur externen Funktion übergeben und Freigabe setzen
+          extfct = true;                                                                // Externe Funktion vorhanden. Freigabe setzen.
+          IRQ_HANDLER_EXTERN = IRQ_HANDLER_METHODE;                                     // Funktionspointer der Funktion übernehmen       
+    }
+
+
+//====================================================================================================================================
+//                             Hilfsfunktionen
+//====================================================================================================================================
+    
+void QUADRATURE::GPIOchoose(char port){ 
+  
+        switch(port){                                                                   // Konfiguration jedes Ports durch Auswahl
+                    case 'A':                                                           // Port A
+                        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;                            // Port A aktivieren
+                        portpo = GPIOA;                                                 // Pointer auf Port A zuweisen
+                    break;
+                    
+                    case 'B':                                                           // Port B
+                        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;                            // Port B aktivieren
+                        portpo = GPIOB;                                                 // Pointer auf Port B zuweisen
+                    break;
+                    
+                    case 'C':                                                           // Port C
+                        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;                            // Port C aktivieren
+                        portpo = GPIOC;                                                 // Pointer auf Port C zuweisen
+                    break;   
+
+                    case 'D':                                                           // Port D
+                        RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;                            // Port D aktivieren
+                        portpo = GPIOD;                                                 // Pointer auf Port D zuweisen
+                    break;                
+
+                    case 'E':                                                           // Port E
+                        RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;                            // Port E aktivieren
+                        portpo = GPIOE;                                                 // Pointer auf Port E zuweisen
+                    break;
+                    
+                    default:                                                            // kein Port ausgewählt und Fehlermeldung
+                        printf("\n \n \r \n  Falscher Port ausgewahlt! \n \n \r");
+                }     
+    }
+    
+void QUADRATURE::_UPDATE_HANDLER(void)                                                  // ISR Handler für die Instanz
+{
+    instance->UPDATE_HANDLER();                                                         // Zuordnung des Handlers zum Handler der Instanz
+    }
+
+
diff -r 000000000000 -r 1acdcc576936 TIM/QUADRATURE.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TIM/QUADRATURE.h	Mon Nov 28 17:27:43 2016 +0000
@@ -0,0 +1,206 @@
+#include "mbed.h"
+
+#ifndef QUADRATURE_h
+#define QUADRATURE_h
+
+/*! Die Klasse kann aus den Timern 1 bis 5 verschiedene Encoder generieren. Es kann zwischen verschiendenen Encodermodis gewählt werden. Für den STM32 gibt es für die einzelnen Timer verschiedene Kanäle die zu wählen sind:
+ <CENTER> 
+ <table>
+        <tr>
+            <th>Eingang</th>
+            <th>Timer 1</th>
+            <th>Timer 2</th>
+            <th>Timer 3</th>
+            <th>Timer 4</th>
+            <th>Timer 5</th>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 1</strong></td>
+            <td>PA8</td>
+            <td>PA0</td>
+            <td>PA6</td>
+            <td>PB6</td>
+            <td>PA0</td>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 1</strong></td>
+            <td>PE9</td>
+            <td>PA5</td>
+            <td>PB4</td>
+            <td>PD12</td>
+            <td>-</td>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 1</strong></td>
+            <td>-</td>
+            <td>PA15</td>
+            <td>PC6</td>
+            <td>-</td>
+            <td>-</td>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 2</strong></td>
+            <td>PA9</td>
+            <td>PA1</td>
+            <td>PB5</td>
+            <td>PD13</td>
+            <td>PA1</td>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 2</strong></td>
+            <td>PE11</td>
+            <td>PB3</td>
+            <td>PA7</td>
+            <td>PB7</td>
+            <td>-</td>
+        </tr>
+        <tr style="text-align: center;">
+            <td><strong>CI 2</strong></td>
+            <td>-</td>
+            <td>-</td>
+            <td>PC7</td>
+            <td>-</td>
+            <td>-</td>
+        </tr>
+</table>
+</CENTER>    
+<b>Achtung!</b> Es können Doppelbelegungen vorkommen! Bitte vorher prüfen, ob der Pin nicht schon verwendet wird. Zudem kann es passieren das mehrfach der gleiche Timer genutzt wird. Mit einer 
+Neudeklaration des Timers wird dieser Überschrieben mit den zuletzt verwendeten Parametern. Zudem gibt es einen Interrupt Eventhandler der bei Über- und Unterlauf des Timers eine Timercarry Variable hoch bzw. runter zählt. 
+So kann man bei Frequenzmessungen  den Überlauf mit betrachten. 
+
+ * @code
+ * #include "mbed.h"
+ * #include "QUADRATURE.h"
+ *
+ * int Event_Routine(){ .... }                          // Irgendeine Funktion die bei Timerüberlauf aufgerufen wird              
+ *
+ * int main() {
+ *    
+ *     QUADRATURE encoder(1, 3, 'A', 8, 0, 'A', 9, 0); // Instanz mit Timer 1, Modus 3,
+ *                                                      // CI1: Port A, CI1: Pin 8, rising edge
+ *                                                      // CI2: Port A, CI2: Pin 9, rising edge
+ * 
+ *     encoder.setDownRes();                            // Setzt die Pull Down Widerstände
+ * 
+ *     encoder.startTIM();                              // Startet den Timer
+ *
+ *     encoder.setIRQ_METHODE(Event_Routine);           // Bei Timerüberlauf wird diese Routine aufgerufen
+ *
+ *      while(1){
+ *        printf("Value: %i\r\n", encoder.getTIM());    // Ausgabe des aktuellen Timerwerts als Integer
+ *        printf("Carry: %i\r\n", encoder.getCARRY());  // Ausgabe des aktuellen Timerüberlaufs als signed short 
+ *      }
+ *    }
+ *
+ * @endcode
+ */
+ 
+ class QUADRATURE
+ {
+     
+    public: 
+       /*! Konstruktor zum Erstellen einer Instanz für einen bestimmten Timer und die Input Pins. Nach dem Erstellen der Instanz sollte der Timer nicht für andere
+      Zwecke verwendet werden. Nach dem Erstellen sind die Encoder voll einsatzbereit und kann mit der "startTIM"-Funktion gestartet werden. */
+       /*!
+           \param tim <b>Entsprechender Timer</b> (Die Funktion wird bei der STM32F-Serie nur von Timer 1-5 unterstützt).
+           \param mode <b>Encoder Modus</b><br>
+                        - 1: Zählt hoch/runter auf CI2-Flanke unter Bedingung der Spannung an CI1<br> 
+                        - 2: Zählt hoch/runter auf CI1-Flanke unter Bedingung der Spannung an CI2<br> 
+                        - 3: Zählt hoch/runter auf CI1-Flanke und CI2-Flanke unter Bedinung der Spannung an den jeweiligen anderen Eingang<br> 
+           \param CI1_PORT <b>Capture Input 1 Port</b> Entsprechend den Port z.B. A,B,C,D,E des ausgewählten Eingangs aus der Tabelle entnehmen.
+           \param CI1_PIN <b>Capture Input 1 Pin</b> Entsprechend den Pin zu dem ausgewählten Eingang aus der Tabelle entnehmen.
+           \param CI1_POL <b>Capture Input 1 Polarität</b> Invertiert den Eingang CI1. Standartwert = steigende Flanke
+           \param CI2_PORT <b>Capture Input 2 Port</b> Entsprechend den Port z.B. A,B,C,D,E des ausgewählten Eingangs aus der Tabelle entnehmen.
+           \param CI2_PIN <b>Capture Input 2 Pin</b> Entsprechend den Pin zu dem ausgewählten Eingang aus der Tabelle entnehmen.
+           \param CI2_POL <b>Capture Input 2 Polarität</b> Invertiert den Eingang CI2. Standartwert = steigende Flanke
+      */                   
+      QUADRATURE(int tim, int mode, char _CI1_PORT, int _CI1_PIN, int CI1_POL,  char _CI2_PORT, int _CI2_PIN, int CI2_POL);
+                        
+                        
+    /*! Destruktor der Klasse */        
+     ~QUADRATURE(){};
+     
+    /*! Startet den Timer und den IRQ Handler. */
+    void startTIM();
+    
+    /*! Stoppt den Timer und den IRQ Handler. */
+    void stopTIM();
+    
+    /*! Setzt die Pullup Widerstände beider CI Eingänge */
+    void setUpRes();
+    
+    /*! Setzt die Pulldown Widerstände beider CI Eingänge */
+    void setDownRes();
+    
+    /*! Gibt aktuellen Timerwert als Integer zurück */
+    unsigned int getTIM();
+    
+    /*! Gibt aktuellen Über bzw Unterlaufwert als signed short zurück */
+    signed short getCARRY();
+    
+    /*! Setzt für den Timer den Prescaler und das Autoload register */
+    /*!
+           \param pre <b>Prescaler</b> Standartwert = (0x0000) + 1. Von 0x0000 bis 0xFFFF möglich
+           \param arr <b>Auto Reload</b> Bei diesem Wert beginnt der Timer wieder bei 0x0000. Standartwert = 0xFFFF
+    */
+    void setTIM(int pre, int arr);
+    
+    /*! Setzt den entsprechenden GPIO auf die Alternative Funktion für den Timer Eingang. */
+    /*!
+           \param port <b>GPIO Port</b> Port der geändert werden soll
+           \param pin <b>GPIO Pin</b> Pin der geändert werden soll
+           \param tim <b>Timer</b> Für die Auswahl zwischen den Alternativen Funktionen notwendig
+    */
+    void setGPIO(char port, int pin, int tim);
+    
+    
+    /*! Interrupt Routine bei Überlauf bzw. Unterlauf des Timers. */
+    void UPDATE_HANDLER(void);
+    
+     /*! Setzt eine weitere Routine die verwendet werden kann, wenn der Timer Interrupthandler aufgerufen wird. */ 
+     /*!
+           \param IRQ_HANDLER_METHODE Adresse zur weiteren Routine
+     */ 
+    void setIRQ_METHODE(void (*IRQ_HANDLER_METHODE)(void));
+                        
+      protected:    
+        
+        //! Caputure Input 1 Portname
+        char CI1_PORT;     
+        //! Caputure Input 2 Portname
+        char CI2_PORT; 
+        //! Caputure Input 1 Pin
+        int CI1_PIN;     
+        //! Caputure Input 2 Pin
+        int CI2_PIN;
+        //! Pointer zum zuletzt definierten GPIO
+        GPIO_TypeDef *portpo; 
+        //! Pointer zum aktuell definierten Timer
+        TIM_TypeDef *tipo; 
+         //! Pointer zum aktuell definierten Interrupt Handler
+        IRQn_Type temp_ITM;         
+         //! Freigabe zur Verwendung externer Funktionen 
+        bool extfct;
+         //!  Externe Funktion bei Timer Interrupt aufrufen
+        void (*IRQ_HANDLER_EXTERN)(void);  
+        
+         //! Timer Über und Unterlauf Zähler (Wenn Unterlauf wird decrementiert, wenn Überlauf wird incrementiert)
+        signed short TIMERCARRY;
+        //! Funktion zum Zuweisen der ISR zum Handler der erstellten Instanz
+        static void _UPDATE_HANDLER(void);
+        //! Pointer zur Adresse der erstellte Instanz 
+        static QUADRATURE *instance;    
+         
+        
+        /*! Wählt das passende GPIO register aus und schreibt es in den Pointer portpo */
+        /*!
+           \param port <b>Portname</b> Welcher Port gewählt werden soll z.B. A,B,...
+        */
+        void GPIOchoose(char port);
+        
+        
+                                                    
+     
+};
+
+#endif
\ No newline at end of file