Jump to content

patolin_01

Members
  • Content Count

    2
  • Joined

  • Last visited

  1. patolin_01

    Stellaris fast analog reads

    Well, here is my 2 cents. Im working on a kind of DSO using the stellaris launchpad, and visual basic 2010. Right now, the stellaris can sample in 1 channel (pin PA7) at different speeds, selectable via serial port commands. Right now, it can sample at 1Msps (890Ksps real), 500Ksps, 250Ksps, 125Ksps using ADC interrupt, and 64ksps, 32ksps, 16ksps, 8ksps, and 2 ksps using timer interrupt. My code samples a 4096 samples buffer, and when receives the "c" command, it sends the values stored in the buffer in ASCII over the serial port, and the its plotted on the VB app. pretty simple, but for me resulted very useful. Here is my code // stelarisDSO v1.0 // 2013-07-20 // buffer de 4096 muestras // #include "Energia.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_ints.h" #include "driverlib/debug.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/adc.h" #include "driverlib/timer.h" #define numDatos 4095 int i=0; int j=1; int adc[numDatos]; unsigned char dataReady=0; unsigned long ulADC0Value[1]; int datosListos=0; int datoActual=0; void setup() { int i; Serial.begin(115200); pinMode(RED_LED, OUTPUT); pinMode(BLUE_LED, OUTPUT); pinMode(GREEN_LED, OUTPUT); for (i=0;i<=4;i++) { digitalWrite(GREEN_LED,1); digitalWrite(RED_LED,1); digitalWrite(BLUE_LED,1); delay(100); digitalWrite(GREEN_LED,0); digitalWrite(RED_LED,0); digitalWrite(BLUE_LED,0); delay(100); } Serial.println("Stellaris DSO"); Serial.println("(c) 2013 www.patolin.com"); Serial.println("Inicio OK. "); Serial.print(SysCtlClockGet()); Serial.println(" hz"); initADC(0,0); ADCIntDisable(ADC0_BASE, 3); initTimer(500); } void loop() { int valor; unsigned timerADC=500; unsigned velADC=0; unsigned char serialIn; char tipoSampling=1; // 0=ADC int, 1=TIMER int // esperamos comando para la velocidad de muestreo while (1) { if (Serial.available()==1) { serialIn=Serial.read(); switch (serialIn) { case 's': // status Serial.println("Ok."); break; case 'c': // devuelve los datos del buffer // esperamos a los datos while (!datosListos) {} // paramos las interrupciones TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); ADCIntDisable(ADC0_BASE, 3); datosListos=0; datoActual=0; //enviamos los datos por el puerto serie Serial.println(numDatos); for (i=0;i<=(numDatos-1);i++) { Serial.println(adc[i]); } // reiniciamos las interrupciones if (tipoSampling==1) { TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); } else { ADCIntEnable(ADC0_BASE, 3); } break; case '1': // 1ksps timerADC=500; tipoSampling=1; break; case '2': // 2ksps timerADC=1000; tipoSampling=1; break; case '3': // 4ksps timerADC=2000; tipoSampling=1; break; case '4': // 8ksps timerADC=4000; tipoSampling=1; break; case '5': // 16ksps timerADC=8000; tipoSampling=1; break; case '6': // 32ksps timerADC=16000; tipoSampling=1; break; case '7': // 64ksps timerADC=32000; tipoSampling=1; break; case '8': // 125ksps timerADC=0000; velADC=0; tipoSampling=0; break; case '9': // 250ksps timerADC=0000; velADC=1; tipoSampling=0; break; case 'A': // 500ksps timerADC=0000; velADC=2; tipoSampling=0; break; case 'B': // 1Msps timerADC=0000; velADC=3; tipoSampling=0; break; } // inicializamos el timer o el ADC segun el caso datosListos=0; datoActual=0; if (tipoSampling==0) { // ADC por interrupcion TimerIntDisable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); initADC(velADC,1); digitalWrite(RED_LED, 0x00); digitalWrite(BLUE_LED, 0x01); } else { ADCIntDisable(ADC0_BASE, 3); initTimer(timerADC); digitalWrite(RED_LED, 0x00); digitalWrite(BLUE_LED, 0x00); } } } } int capturaADC() { ADCIntClear(ADC0_BASE, 3); ADCProcessorTrigger(ADC0_BASE, 3); while(!ADCIntStatus(ADC0_BASE, 3, false)) { } ADCSequenceDataGet(ADC0_BASE, 3, ulADC0Value); return (int)ulADC0Value[0]; } void Timer0IntHandler() { TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT); digitalWrite(RED_LED, j&0x01); j++; adc[datoActual]=capturaADC(); datoActual++; if (datoActual>numDatos) { datosListos=1; datoActual=0; } } void ADC0IntHandler() { ADCIntClear(ADC0_BASE,3); ADCSequenceDataGet(ADC0_BASE, 3, ulADC0Value); adc[datoActual]=(int)ulADC0Value[0]; datoActual++; if (datoActual>numDatos) { datoActual=0; datosListos=1; ADCIntDisable(ADC0_BASE, 3);} } void initTimer(unsigned Hz) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC); unsigned long ulPeriod = (SysCtlClockGet() / Hz) / 2; TimerLoadSet(TIMER0_BASE, TIMER_A, ulPeriod -1); IntEnable(INT_TIMER0A); TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT); TimerIntRegister(TIMER0_BASE, TIMER_A, Timer0IntHandler); TimerEnable(TIMER0_BASE, TIMER_A); } void initADC(int velocidad, int trigger) { /* Velocidad: 0=1msps,1=500ksps,2=250ksps,3=125ksps trigger: 0=processor, 1=always */ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); switch(velocidad) { case 3: SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS); break; case 2: SysCtlADCSpeedSet(SYSCTL_ADCSPEED_500KSPS); break; case 1: SysCtlADCSpeedSet(SYSCTL_ADCSPEED_250KSPS); break; case 0: SysCtlADCSpeedSet(SYSCTL_ADCSPEED_125KSPS); break; default: SysCtlADCSpeedSet(SYSCTL_ADCSPEED_1MSPS); break; } ADCSequenceDisable(ADC0_BASE, 3); if (trigger==0) { ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0); } else { ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_ALWAYS, 0); } ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); //ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); //Secuencia de ejemplo para el medidor de temperatura interno ADCIntRegister(ADC0_BASE, 3, ADC0IntHandler); ADCIntEnable(ADC0_BASE, 3); ADCSequenceEnable(ADC0_BASE, 3); ADCProcessorTrigger(ADC0_BASE, 3); } Im writing a detailed post for my blog, so I hope it can be useful for you guys. You can check a preview (in spanish) in http://patolin.com/blog/2013/07/07/osciloscopio-con-stellaris-launchpad-actualizacion/ Here is a capture image, of a RC transmitter PPM frame, at 125Ksps, 10 bits, using a 4096 sample buffer
  2. patolin_01

    LM4F120 Timer issue

    The real problem arround here, is the interrupt routines definition in the startup.gcc I have been fighting for 2 weeks with Energia, trying to enable the timer 0 and the interrupt based ADC. But when I declare the interrupt functions on the startup.gcc file, the code compiles without problem, and its loaded into the stellaris without errors, or freezings, like the ones that brownfox is having. My code idea was to sample a signal at full speed (1Msps) and have a constant clock signal at 1hz, all interrupt based. Actually Im sampling at 950Ksps, filling a 2048 samples block, without DMA. Im trying to make a DSO like board for my laptop, so its a good start. The code, and some explanation (spanish post, so open google translate in a new window ) is in this url http://patolin.com/blog/2013/05/16/stellaris-launchpad-y-energia-programando-un-cortex-m3-facilmente/ Honestly, using CCS for the stellaris, was not so funny for me. I dont like eclipse, and its pretty slow in my not-so-top-notch laptop, so Energia makes the things more easy for me, and I think that it will help more people to use the launchpads
×