Hello,
I am currently working on a project with TM4C129EXL. I need to use a specifc ADC sequence (See the code below). I wanted to change the timer frequency (400000 Hz) , but it seems to run up to about 100000Hz (compared a counter in the timer with a stopwatch).
When I add some code, it runs up to about 15000Hz.
The datasheet gives the maximum number of sample, wich is 2MSPS.
I suppose there is some kind of limitations here. Can you explain? Maybe my code is wrong?
Thank you.
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include <string.h> #include <math.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_gpio.h" #include "driverlib/debug.h" #include "driverlib/fpu.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/adc.h" #include "drivers/pinout.h" #include "drivers/buttons.h" #include "driverlib/fpu.h" #include "driverlib/pwm.h" #include "Custom files/constantes.h" #include "Custom files/maths.h" #include "Custom files/correcteurs.h" // // The error routine that is called if the driver library encounters an error. // #ifdef DEBUG void __error__(char *pcFilename, uint32_t ui32Line) { } #endif // Réglages des paramètres du programme // fréquence d'échantillonnage #define TMR0_FREQ 100000 //Hz // Horloge uint32_t g_ui32SysClock; // Etat de la diode uint8_t LED = 0; // variables analogiques float tension; float temp; float pot; float sinus; float cosinus; float courant[NBECH_COURANT]; float v[NBECH_V]; //vitesse float x[NBECH_X]; //position float *adrTest; float test; int *adrCompteurTemps; uint32_t ADCbuffer[4], thetaSinBuffer[1], thetaCosBuffer[1]; // Initialise le timer 0 void ConfigureTIMER0(void) { // Active le périphérique Timer 0 SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); // Configure the 32-bit periodic timers. TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); TimerLoadSet(TIMER0_BASE, TIMER_A, g_ui32SysClock/TMR0_FREQ); // Setup the interrupts for the timer timeouts. IntEnable(INT_TIMER0A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } // Initialise les ADC et les GPIO associées void ConfigureADC(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); ADCReferenceSet(ADC0_BASE, ADC_REF_INT); ADCReferenceSet(ADC1_BASE, ADC_REF_INT); GPIOPinTypeADC(GPIO_PORTE_BASE,GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0) && !SysCtlPeripheralReady(SYSCTL_PERIPH_ADC1) && !SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE)) {} ////// Désactivation des ADC (sécurité) ADCSequenceDisable(ADC0_BASE,2); ADCSequenceDisable(ADC0_BASE,0); ADCSequenceDisable(ADC1_BASE,0); ////// Configuration des ADC // Séquence courant -> température -> potentiomètre ADCSequenceConfigure(ADC0_BASE,2,ADC_TRIGGER_PROCESSOR,0); //ADC0 Sequence 2 déclenchement processeur priorité 0 (Haute) //positionSin et positionCos sync ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_PROCESSOR,0); ADCSequenceConfigure(ADC1_BASE,0,ADC_TRIGGER_PROCESSOR,0); ////// Configuration des séquences // Séquence courant -> température -> potentiomètre ADCSequenceStepConfigure(ADC0_BASE,2,0,ADC_CTL_CH1); //Courant ADCSequenceStepConfigure(ADC0_BASE,2,1,ADC_CTL_CH9); //vitesse ADCSequenceStepConfigure(ADC0_BASE,2,2,ADC_CTL_CH2); //Température ADCSequenceStepConfigure(ADC0_BASE,2,3,ADC_CTL_CH3|ADC_CTL_IE|ADC_CTL_END); //Potentiomètre // positionSin et positionCos sync ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CTL_CH0|ADC_CTL_IE|ADC_CTL_END); ADCSequenceStepConfigure(ADC1_BASE,0,0,ADC_CTL_CH8|ADC_CTL_IE|ADC_CTL_END); ////// Activations des ADC ADCSequenceEnable(ADC0_BASE,2); ADCSequenceEnable(ADC0_BASE,0); ADCSequenceEnable(ADC1_BASE,0); // Reset des flags d'interuption des ADC ADCIntClear(ADC0_BASE,2); ADCIntClear(ADC0_BASE,0); ADCIntClear(ADC1_BASE,0); } // Fonction d'interuption du timer 0 void Timer0IntHandler(void) { // Reset le flag de l'interuption du timer TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); static int compteurTemps = 0; adrCompteurTemps = &compteurTemps; ////////////////////////////////////////////////////////////////////////// ////// ADC // initialise le flag de l'interuption de l'ADC ADCIntClear(ADC0_BASE,2); // Déclenche la conversion ADCProcessorTrigger(ADC0_BASE,2); while(!ADCIntStatus(ADC0_BASE,2,false)){} // attend la fin de la conversion // Reset le flag de l'interuption de l'ADC ADCIntClear(ADC0_BASE,2); // Lecture des données ADCSequenceDataGet(ADC0_BASE,2,ADCbuffer); // Calculs et enregistrement actualiseEchantillons(courant,NBECH_COURANT); courant[0] = ADCbuffer[0]*GAIN_COURANT-OFFSET_COURANT; actualiseEchantillons(v,NBECH_V); //v[0] = ADCbuffer[1]*GAIN_VITESSE-OFFSET_VITESSE; v[0] = -1.825101272*((ADCbuffer[1]-1848.246159)*1.510773788/1848.246159); temp = ADCbuffer[2]*GAIN_TEMP+OFFSET_TEMP; pot = ADCbuffer[3]*GAIN_POT+OFFSET_POT; // position, sync ADCIntClear(ADC0_BASE,0); ADCIntClear(ADC1_BASE,0); // déclenche les conversions synchronisées ADCProcessorTrigger(ADC1_BASE,(0|ADC_TRIGGER_WAIT)); // ADC-1 en attente de déclenchement ADCProcessorTrigger(ADC0_BASE,(0|ADC_TRIGGER_SIGNAL)); // ADC-0 en déclenchement global while(!ADCIntStatus(ADC0_BASE,0,false)){} // attend la fin de la conversion // Reset le flag de l'interuption de l'ADC ADCIntClear(ADC0_BASE,0); ADCIntClear(ADC1_BASE,0); // Lecture des données ADCSequenceDataGet(ADC0_BASE,0,thetaSinBuffer); ADCSequenceDataGet(ADC1_BASE,0,thetaCosBuffer); // Calculs et enregitrement //max (erreur capteur + erreur monAtan) = 0.152 mm sinus = (thetaSinBuffer[0]*GAIN_SINCOS-OFFSET_SIN)*GAIN_NL_SIN; cosinus = (thetaCosBuffer[0]*GAIN_SINCOS-OFFSET_COS)*GAIN_NL_COS; actualiseEchantillons(x,NBECH_X); x[0] = GAIN_X*monAtan2(cosinus,sinus,3)+OFFSET_X; compteurTemps++; test = (float)compteurTemps/TMR0_FREQ; adrTest = &test; ////////////////////////////////////////////////////////////////////////// ////// Test de fin de timer HWREGBITW(&LED, 0) ^= 1; // (bit 0 du registre de LED) XOR 1 GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, LED); } // Main: Initialisation et boucle infinie int main(void) { ////// Set up // Règle l'horloge sur le cristal à 120MHz g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), CLK_FREQ); // Permet d'utiliser les virgules flottantes (nombres réels) FPULazyStackingEnable(); FPUEnable(); // Active le port des diodes PinoutSet(false, false); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION); while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION)){} GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1); GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1, 0); // Autorise les interuptions IntMasterEnable(); // Configure le timer pour l'échantillonnage ConfigureTIMER0(); // Configure les ADC ConfigureADC(); // initialisation des tableaux de stockage des données initialiseTableau(courant, NBECH_COURANT); initialiseTableau(v, NBECH_V); initialiseTableau(x, NBECH_X); // Lance le timer TimerEnable(TIMER0_BASE, TIMER_A); // Boucle infinie en parallèle du timer while(1) { } } /********************************************* * These functions are defined in another file *********************************************/ void actualiseEchantillons(float tab[], int dim){ float temp; int i; for(i = dim-1; i > 0; i = i--) { temp = tab[i]; tab[i] = tab[i-1]; tab[i-1] = temp; } } void initialiseTableau (float tableau[], int dim){ int i; for(i = 0; i<dim; i++) { tableau[i] = 0.0; } }