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)

TIM/QUADRATURE.cpp

Committer:
ChrisselH
Date:
2016-11-28
Revision:
0:1acdcc576936

File content as of revision 0:1acdcc576936:

#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
    }