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
- timer modules
- Quadratur Encoder (Version 1.2 - C. Hoyer 12.8.2015)
- SPI modules
- AD5664 (Version 1.1 - C. Hoyer 23.7.2015)
- software modules
- Ringbuffer (Version 0.9 - C. Hoyer 18.8.2015)
- 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 }