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)
Committer:
ChrisselH
Date:
Mon Nov 28 17:27:43 2016 +0000
Revision:
0:1acdcc576936
port from priv lib

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ChrisselH 0:1acdcc576936 1 #include "mbed.h"
ChrisselH 0:1acdcc576936 2 #include "QUADRATURE.h"
ChrisselH 0:1acdcc576936 3 #include "cmsis_nvic.h"
ChrisselH 0:1acdcc576936 4
ChrisselH 0:1acdcc576936 5 //====================================================================================================================================
ChrisselH 0:1acdcc576936 6 // Initialisieren und mappen der Kanäle, Timer etc
ChrisselH 0:1acdcc576936 7 //====================================================================================================================================
ChrisselH 0:1acdcc576936 8 QUADRATURE *QUADRATURE::instance; // Pointer zur Adresse der Instanz
ChrisselH 0:1acdcc576936 9
ChrisselH 0:1acdcc576936 10
ChrisselH 0:1acdcc576936 11 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)
ChrisselH 0:1acdcc576936 12 {
ChrisselH 0:1acdcc576936 13
ChrisselH 0:1acdcc576936 14 TIMERCARRY = 0; // bei neuem Objekt den entsprechenden Timercarry auf 0 setzen
ChrisselH 0:1acdcc576936 15 instance = this; // Instanz zuweisung zum neu generierten Objekt
ChrisselH 0:1acdcc576936 16 extfct = false; // Externe Funktion bei Timer Interrupt deaktiviert
ChrisselH 0:1acdcc576936 17
ChrisselH 0:1acdcc576936 18 //Konfiguration des Timers
ChrisselH 0:1acdcc576936 19 switch(tim){ // Konfiguration jedes einzelnen Timers, durch Auswahl
ChrisselH 0:1acdcc576936 20 case 1: // TIM1
ChrisselH 0:1acdcc576936 21 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // Timer 1 aktivieren
ChrisselH 0:1acdcc576936 22 tipo = TIM1; // Pointer auf Timer1 zuweisen
ChrisselH 0:1acdcc576936 23 temp_ITM = TIM1_UP_TIM10_IRQn; // NVIC Nummer für den Updateinterrupt Timer 1
ChrisselH 0:1acdcc576936 24 NVIC->ISER[0] &= ~(1 << TIM1_UP_TIM10_IRQn); // Interrupt Handler für den Timer 1 aktivieren
ChrisselH 0:1acdcc576936 25 break;
ChrisselH 0:1acdcc576936 26
ChrisselH 0:1acdcc576936 27 case 2: // TIM2
ChrisselH 0:1acdcc576936 28 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // Timer 2 aktivieren
ChrisselH 0:1acdcc576936 29 tipo = TIM2; // Pointer auf Timer2 zuweisen
ChrisselH 0:1acdcc576936 30 temp_ITM = TIM2_IRQn; // NVIC Nummer für den Updateinterrupt Timer 2
ChrisselH 0:1acdcc576936 31 NVIC->ISER[0] &= ~(1 << TIM2_IRQn); // Interrupt Handler für den Timer 2 aktivieren
ChrisselH 0:1acdcc576936 32 break;
ChrisselH 0:1acdcc576936 33
ChrisselH 0:1acdcc576936 34 case 3: // TIM3
ChrisselH 0:1acdcc576936 35 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // Timer 3 aktivieren
ChrisselH 0:1acdcc576936 36 tipo = TIM3; // Pointer auf Timer3 zuweisen
ChrisselH 0:1acdcc576936 37 temp_ITM = TIM3_IRQn; // NVIC Nummer für den Updateinterrupt Timer 3
ChrisselH 0:1acdcc576936 38 NVIC->ISER[0] &= ~(1 << TIM3_IRQn); // Interrupt Handler für den Timer 3 aktivieren
ChrisselH 0:1acdcc576936 39 break;
ChrisselH 0:1acdcc576936 40
ChrisselH 0:1acdcc576936 41 case 4: // TIM4
ChrisselH 0:1acdcc576936 42 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // Timer 4 aktivieren
ChrisselH 0:1acdcc576936 43 tipo = TIM4; // Pointer auf Timer4 zuweisen
ChrisselH 0:1acdcc576936 44 temp_ITM = TIM4_IRQn; // NVIC Nummer für den Updateinterrupt Timer 4
ChrisselH 0:1acdcc576936 45 NVIC->ISER[0] &= ~(1 << TIM4_IRQn); // Interrupt Handler für den Timer 4 aktivieren
ChrisselH 0:1acdcc576936 46 break;
ChrisselH 0:1acdcc576936 47
ChrisselH 0:1acdcc576936 48 case 5: // TIM5
ChrisselH 0:1acdcc576936 49 RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; // Timer 5 aktivieren
ChrisselH 0:1acdcc576936 50 tipo = TIM5; // Pointer auf Timer5 zuweisen
ChrisselH 0:1acdcc576936 51 temp_ITM = TIM5_IRQn; // NVIC Nummer für den Updateinterrupt Timer 5
ChrisselH 0:1acdcc576936 52 NVIC->ISER[1] &= ~(1 << (TIM5_IRQn-31)); // Interrupt Handler für den Timer 5 aktivieren
ChrisselH 0:1acdcc576936 53 break;
ChrisselH 0:1acdcc576936 54
ChrisselH 0:1acdcc576936 55 default: // keinen Timer ausgewählt und Fehlermeldung
ChrisselH 0:1acdcc576936 56 printf("\n \n \r \n Falscher Timer ausgewahlt! \n \n \r");
ChrisselH 0:1acdcc576936 57 return;
ChrisselH 0:1acdcc576936 58 }
ChrisselH 0:1acdcc576936 59
ChrisselH 0:1acdcc576936 60 tipo->SMCR = mode; // Schreibt den aktuellen Modus in das SMCR Register (Slave Mode)
ChrisselH 0:1acdcc576936 61 tipo->CCMR1 = 0xF1F1; // Mappen der Capture Inputs 1 und 2 auf Timer Input 1 und 2
ChrisselH 0:1acdcc576936 62 tipo->CCMR2 = 0x0000; // Kein mappen der Capture Inputs 3 und 4
ChrisselH 0:1acdcc576936 63 tipo->CCER = 0x0011; // Capture Inputs 1 und 2 aktivieren
ChrisselH 0:1acdcc576936 64
ChrisselH 0:1acdcc576936 65 // Konfiguration der Pins
ChrisselH 0:1acdcc576936 66 setGPIO(CI1_PORT, CI1_PIN, tim); // Setzt den Port Pin für CI1
ChrisselH 0:1acdcc576936 67 setGPIO(CI2_PORT, CI2_PIN, tim); // Setzt den Port Pin für CI2
ChrisselH 0:1acdcc576936 68
ChrisselH 0:1acdcc576936 69 // Konfiguration der Polarität
ChrisselH 0:1acdcc576936 70 if(CI1_POL == 1){ // Polarität für CI1 ändern auf fallende Flanke
ChrisselH 0:1acdcc576936 71 tipo->CCER |= 0x0002;
ChrisselH 0:1acdcc576936 72 }
ChrisselH 0:1acdcc576936 73 if(CI2_POL == 1){ // Polarität für CI2 ändern auf fallende Flanke
ChrisselH 0:1acdcc576936 74 tipo->CCER |= 0x0020;
ChrisselH 0:1acdcc576936 75 }
ChrisselH 0:1acdcc576936 76
ChrisselH 0:1acdcc576936 77 // Konfiguration der Interrupt Routine
ChrisselH 0:1acdcc576936 78 NVIC_SetVector(temp_ITM, (uint32_t) &_UPDATE_HANDLER); // Adresse zum IRQ Handler des entsprechenden Timers
ChrisselH 0:1acdcc576936 79 NVIC_SetPriority(temp_ITM, 0); // Festlegen der Priorität (Höchste, damit das nächste Increment mit gezählt wird)
ChrisselH 0:1acdcc576936 80 tipo->DIER |= 0x0001; // Update Interrupt Einstellung im Timer aktivieren
ChrisselH 0:1acdcc576936 81
ChrisselH 0:1acdcc576936 82
ChrisselH 0:1acdcc576936 83 }
ChrisselH 0:1acdcc576936 84
ChrisselH 0:1acdcc576936 85
ChrisselH 0:1acdcc576936 86
ChrisselH 0:1acdcc576936 87 void QUADRATURE::setGPIO(char port, int pin, int tim){ // Funktion zum Mappen des Port Pins auf die Alternative Funktion für den Timer Eingang
ChrisselH 0:1acdcc576936 88
ChrisselH 0:1acdcc576936 89 GPIOchoose(port); // Wählt den passenden Pointer zum Port aus
ChrisselH 0:1acdcc576936 90
ChrisselH 0:1acdcc576936 91 portpo->MODER |= (1 <<((2*pin)+1)); // Alternative Funktion 0x10 mit Maske (2 Bit pro Pin)
ChrisselH 0:1acdcc576936 92 portpo->OTYPER |= (1 << pin); // Definition als Eingang 0x1 mit Open Drain
ChrisselH 0:1acdcc576936 93
ChrisselH 0:1acdcc576936 94 if(pin > 7){ // Ausgänge 8 bis 15 sind im höheren Register AFR[1]
ChrisselH 0:1acdcc576936 95 if(tim < 3){ // Für Timer 1 und Timer 2 (Alternatve Funktion 01)
ChrisselH 0:1acdcc576936 96 portpo->AFR[1] |= (1 << (4*(pin-8))); // Alternative Funktion mit Maske für AF01
ChrisselH 0:1acdcc576936 97 }
ChrisselH 0:1acdcc576936 98 else{ // Für Timer 3, Timer 4 und Timer 5 (Alternative Funktion 10)
ChrisselH 0:1acdcc576936 99 portpo->AFR[1] |= (1 << (4*(pin-8))+1); // Alternative Funktion mit Maske für AF02
ChrisselH 0:1acdcc576936 100 }
ChrisselH 0:1acdcc576936 101 }
ChrisselH 0:1acdcc576936 102 else{ // Ausgänge 0 bis 7 sind im im unteren Register AFR[0]
ChrisselH 0:1acdcc576936 103 if(tim < 3){ // Für Timer 1 und Timer 2 (Alternatve Funktion 01)
ChrisselH 0:1acdcc576936 104 portpo->AFR[0] |= (1 << (4*pin)); // Alternative Funktion mit Maske für AF01
ChrisselH 0:1acdcc576936 105 }
ChrisselH 0:1acdcc576936 106 else{ // Für Timer 3, Timer 4 und Timer 5 (Alternative Funktion 10)
ChrisselH 0:1acdcc576936 107 portpo->AFR[0] |= (1 << ((4*pin)+1)); // Alternative Funktion mit Maske für AF02
ChrisselH 0:1acdcc576936 108 }
ChrisselH 0:1acdcc576936 109 }
ChrisselH 0:1acdcc576936 110 }
ChrisselH 0:1acdcc576936 111
ChrisselH 0:1acdcc576936 112 //====================================================================================================================================
ChrisselH 0:1acdcc576936 113 // Eventhandler für Timer und Externer Eingang
ChrisselH 0:1acdcc576936 114 //====================================================================================================================================
ChrisselH 0:1acdcc576936 115
ChrisselH 0:1acdcc576936 116 void QUADRATURE::UPDATE_HANDLER(void){ // Interrupt Service Routine für Update Events
ChrisselH 0:1acdcc576936 117
ChrisselH 0:1acdcc576936 118 tipo->SR ^= 0x0001; // Flag löschen (Register xor mit Flag)
ChrisselH 0:1acdcc576936 119
ChrisselH 0:1acdcc576936 120 if (getTIM() > 1){
ChrisselH 0:1acdcc576936 121 TIMERCARRY--; // Carryvariable -1 da Unterlauf
ChrisselH 0:1acdcc576936 122 }
ChrisselH 0:1acdcc576936 123 else{
ChrisselH 0:1acdcc576936 124 TIMERCARRY++; // Carryvariable 1 da Überlauf
ChrisselH 0:1acdcc576936 125 }
ChrisselH 0:1acdcc576936 126
ChrisselH 0:1acdcc576936 127 if(extfct == true){ // Externe Funktion vorhanden?
ChrisselH 0:1acdcc576936 128 (*IRQ_HANDLER_EXTERN)(); // Aufruf der Externen Funktion
ChrisselH 0:1acdcc576936 129 }
ChrisselH 0:1acdcc576936 130 }
ChrisselH 0:1acdcc576936 131
ChrisselH 0:1acdcc576936 132
ChrisselH 0:1acdcc576936 133 //====================================================================================================================================
ChrisselH 0:1acdcc576936 134 // Setter- und Getter-Funktionen
ChrisselH 0:1acdcc576936 135 //====================================================================================================================================
ChrisselH 0:1acdcc576936 136
ChrisselH 0:1acdcc576936 137 void QUADRATURE::startTIM(){
ChrisselH 0:1acdcc576936 138 NVIC_EnableIRQ(temp_ITM); // Enable den IRQ Handler
ChrisselH 0:1acdcc576936 139 tipo->CR1 = 0x0001; // Starte Timer
ChrisselH 0:1acdcc576936 140 }
ChrisselH 0:1acdcc576936 141
ChrisselH 0:1acdcc576936 142 void QUADRATURE::stopTIM(){
ChrisselH 0:1acdcc576936 143 tipo->CR1 = 0x0000; // Stoppe Timer
ChrisselH 0:1acdcc576936 144 NVIC_DisableIRQ(temp_ITM); // Disable den IRQ Handler
ChrisselH 0:1acdcc576936 145 }
ChrisselH 0:1acdcc576936 146
ChrisselH 0:1acdcc576936 147 unsigned int QUADRATURE::getTIM(){
ChrisselH 0:1acdcc576936 148 return tipo->CNT; // Gibt aktuellen Timerwert zurück
ChrisselH 0:1acdcc576936 149 }
ChrisselH 0:1acdcc576936 150
ChrisselH 0:1acdcc576936 151 signed short QUADRATURE::getCARRY(){
ChrisselH 0:1acdcc576936 152 return TIMERCARRY; // Gibt aktuellen Timercarry zurück
ChrisselH 0:1acdcc576936 153 }
ChrisselH 0:1acdcc576936 154
ChrisselH 0:1acdcc576936 155 void QUADRATURE::setTIM(int pre, int arr){
ChrisselH 0:1acdcc576936 156 tipo->PSC = pre; // Prescaler (Wert + 1)
ChrisselH 0:1acdcc576936 157 tipo->ARR = arr; // Auto reload
ChrisselH 0:1acdcc576936 158 }
ChrisselH 0:1acdcc576936 159
ChrisselH 0:1acdcc576936 160 void QUADRATURE::setUpRes(){
ChrisselH 0:1acdcc576936 161
ChrisselH 0:1acdcc576936 162 GPIOchoose(CI1_PORT); // Wählt den passenden Pointer zum Port von CI1 aus
ChrisselH 0:1acdcc576936 163 portpo->PUPDR |= (1 << ((2*CI1_PIN))); // Setzt den Pull up für den entsprechenden Port Pin von CI1
ChrisselH 0:1acdcc576936 164
ChrisselH 0:1acdcc576936 165 GPIOchoose(CI2_PORT); // Wählt den passenden Pointer zum Port von CI2 aus
ChrisselH 0:1acdcc576936 166 portpo->PUPDR |= (1 << ((2*CI2_PIN))); // Setzt den Pull up für den entsprechenden Port Pin von CI2
ChrisselH 0:1acdcc576936 167 }
ChrisselH 0:1acdcc576936 168
ChrisselH 0:1acdcc576936 169 void QUADRATURE::setDownRes(){
ChrisselH 0:1acdcc576936 170
ChrisselH 0:1acdcc576936 171 GPIOchoose(CI1_PORT); // Wählt den passenden Pointer zum Port von CI1 aus
ChrisselH 0:1acdcc576936 172 portpo->PUPDR |= (1 << ((2*CI1_PIN)+1)); // Setzt den Pull down für den entsprechenden Port Pin von CI1
ChrisselH 0:1acdcc576936 173
ChrisselH 0:1acdcc576936 174 GPIOchoose(CI2_PORT); // Wählt den passenden Pointer zum Port von CI2 aus
ChrisselH 0:1acdcc576936 175 portpo->PUPDR |= (1 << ((2*CI2_PIN)+1)); // Setzt den Pull down für den entsprechenden Port Pin von CI2
ChrisselH 0:1acdcc576936 176 }
ChrisselH 0:1acdcc576936 177
ChrisselH 0:1acdcc576936 178 void QUADRATURE::setIRQ_METHODE(void (*IRQ_HANDLER_METHODE)(void)){ // Adresse zur externen Funktion übergeben und Freigabe setzen
ChrisselH 0:1acdcc576936 179 extfct = true; // Externe Funktion vorhanden. Freigabe setzen.
ChrisselH 0:1acdcc576936 180 IRQ_HANDLER_EXTERN = IRQ_HANDLER_METHODE; // Funktionspointer der Funktion übernehmen
ChrisselH 0:1acdcc576936 181 }
ChrisselH 0:1acdcc576936 182
ChrisselH 0:1acdcc576936 183
ChrisselH 0:1acdcc576936 184 //====================================================================================================================================
ChrisselH 0:1acdcc576936 185 // Hilfsfunktionen
ChrisselH 0:1acdcc576936 186 //====================================================================================================================================
ChrisselH 0:1acdcc576936 187
ChrisselH 0:1acdcc576936 188 void QUADRATURE::GPIOchoose(char port){
ChrisselH 0:1acdcc576936 189
ChrisselH 0:1acdcc576936 190 switch(port){ // Konfiguration jedes Ports durch Auswahl
ChrisselH 0:1acdcc576936 191 case 'A': // Port A
ChrisselH 0:1acdcc576936 192 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // Port A aktivieren
ChrisselH 0:1acdcc576936 193 portpo = GPIOA; // Pointer auf Port A zuweisen
ChrisselH 0:1acdcc576936 194 break;
ChrisselH 0:1acdcc576936 195
ChrisselH 0:1acdcc576936 196 case 'B': // Port B
ChrisselH 0:1acdcc576936 197 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // Port B aktivieren
ChrisselH 0:1acdcc576936 198 portpo = GPIOB; // Pointer auf Port B zuweisen
ChrisselH 0:1acdcc576936 199 break;
ChrisselH 0:1acdcc576936 200
ChrisselH 0:1acdcc576936 201 case 'C': // Port C
ChrisselH 0:1acdcc576936 202 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // Port C aktivieren
ChrisselH 0:1acdcc576936 203 portpo = GPIOC; // Pointer auf Port C zuweisen
ChrisselH 0:1acdcc576936 204 break;
ChrisselH 0:1acdcc576936 205
ChrisselH 0:1acdcc576936 206 case 'D': // Port D
ChrisselH 0:1acdcc576936 207 RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Port D aktivieren
ChrisselH 0:1acdcc576936 208 portpo = GPIOD; // Pointer auf Port D zuweisen
ChrisselH 0:1acdcc576936 209 break;
ChrisselH 0:1acdcc576936 210
ChrisselH 0:1acdcc576936 211 case 'E': // Port E
ChrisselH 0:1acdcc576936 212 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; // Port E aktivieren
ChrisselH 0:1acdcc576936 213 portpo = GPIOE; // Pointer auf Port E zuweisen
ChrisselH 0:1acdcc576936 214 break;
ChrisselH 0:1acdcc576936 215
ChrisselH 0:1acdcc576936 216 default: // kein Port ausgewählt und Fehlermeldung
ChrisselH 0:1acdcc576936 217 printf("\n \n \r \n Falscher Port ausgewahlt! \n \n \r");
ChrisselH 0:1acdcc576936 218 }
ChrisselH 0:1acdcc576936 219 }
ChrisselH 0:1acdcc576936 220
ChrisselH 0:1acdcc576936 221 void QUADRATURE::_UPDATE_HANDLER(void) // ISR Handler für die Instanz
ChrisselH 0:1acdcc576936 222 {
ChrisselH 0:1acdcc576936 223 instance->UPDATE_HANDLER(); // Zuordnung des Handlers zum Handler der Instanz
ChrisselH 0:1acdcc576936 224 }
ChrisselH 0:1acdcc576936 225
ChrisselH 0:1acdcc576936 226