7 votos

MSP430 programa sólo funciona durante el modo de depuración

Estoy tratando de recuperar los valores de la ADC en mi MSP430F5529 y enviarlos a mi pc a través de USB, pero me estoy empezando pequeños. Todo lo que tengo ahora mismo tengo algo que recupera el ADC valor y la almacena en ADCResults, si el valor de lectura es más de la mitad de Vcc, a continuación, un LED se enciende.

Tengo pin 6.0 conectado a un sensor de fuerza para que yo pueda ver lo apague y cuando pongo mi dedo hacia abajo o de liberación.

El programa funciona a la perfección cuando se ejecuta en modo de depuración, pero cuando trato de ejecutar fuera de modo de depuración (sólo alimentación de la junta directiva del equipo después de que el código es descargado), no pasa nada cuando pongo mi dedo en el sensor de fuerza.

Cuál es extremadamente extraño es que si me mantenga presionado reset, mientras que poner mi dedo en el sensor de fuerza (poniendo mi dedo hacia abajo hace que el LED se enciende), y suelte el botón de reset el LED permanece encendido hasta que me golpeó reset de nuevo con mi dedo fuera de ella, por lo que parece reset está causando un problema, pero no estoy seguro de cómo.

Al principio pensé que restablecer estaba siendo empujado constantemente alta (o baja, lo que restablece el dispositivo), pero eso no puede ser cierto porque, a continuación, el programa debería funcionar si tuve restablecimiento de abajo, pero no!

Aquí está mi código:

#include "driverlib.h"

volatile uint16_t ADCResults = 0;

void main(void)
{
    //Stop Watchdog Timer
    WDT_A_hold(WDT_A_BASE);

    //P6.0 ADC option select
    GPIO_setAsPeripheralModuleFunctionOutputPin(
        GPIO_PORT_P6,
        GPIO_PIN0
        );

    GPIO_setAsOutputPin(
        GPIO_PORT_P1,
        GPIO_PIN0
        );

    //Initialize the ADC12_A_A Module
    /*
     * Base address of ADC12_A_A Module
     * Use internal ADC12_A_A bit as sample/hold signal to start conversion
     * USE MODOSC 5MHZ Digital Oscillator as clock source
     * Use default clock divider of 1
     */
    ADC12_A_init(ADC12_A_BASE,
                 ADC12_A_SAMPLEHOLDSOURCE_SC,
                 ADC12_A_CLOCKSOURCE_ADC12OSC,
                 ADC12_A_CLOCKDIVIDER_1);

    ADC12_A_enable(ADC12_A_BASE);

    /*
     * Base address of ADC12_A_A Module
     * For memory buffers 0-7 sample/hold for 64 clock cycles
     * For memory buffers 8-15 sample/hold for 4 clock cycles (default)
     * Disable Multiple Sampling
     */
    ADC12_A_setupSamplingTimer(ADC12_A_BASE,
                               ADC12_A_CYCLEHOLD_64_CYCLES,
                               ADC12_A_CYCLEHOLD_4_CYCLES,
                               ADC12_A_MULTIPLESAMPLESDISABLE);

    //Configure Memory Buffer
    /*
     * Base address of the ADC12_A_A Module
     * Configure memory buffer 0
     * Map input A0 to memory buffer 0
     * Vref+ = AVcc
     * Vr- = AVss
     * Memory buffer 0 is not the end of a sequence
     */
    ADC12_A_configureMemoryParam param = {0};
    param.memoryBufferControlIndex = ADC12_A_MEMORY_0;
    param.inputSourceSelect = ADC12_A_INPUT_A0;
    param.positiveRefVoltageSourceSelect = ADC12_A_VREFPOS_AVCC;
    param.negativeRefVoltageSourceSelect = ADC12_A_VREFNEG_AVSS;
    param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE;
    ADC12_A_configureMemory(ADC12_A_BASE,&param);

    //Enable memory buffer 0 interrupt
    ADC12_A_clearInterrupt(ADC12_A_BASE,
                           ADC12IFG0);
    ADC12_A_enableInterrupt(ADC12_A_BASE,
                            ADC12IE0);

    while(1)
    {
        //Enable/Start sampling and conversion
        /*
         * Base address of ADC12_A_A Module
         * Start the conversion into memory buffer 0
         * Use the single-channel, single-conversion mode
         */
        ADC12_A_startConversion(ADC12_A_BASE,
                                ADC12_A_MEMORY_0,
                                ADC12_A_SINGLECHANNEL);

        //LPM0, ADC12_A_ISR will force exit
        __bis_SR_register(LPM0_bits + GIE);
        //for Debugger
        __no_operation();
    }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(ADC12_VECTOR)))
#endif
void ADC12_A_ISR(void)
{
    switch(__even_in_range(ADC12IV,34))
    {
    case  0: break;       //Vector  0:  No interrupt
    case  2: break;       //Vector  2:  ADC overflow
    case  4: break;       //Vector  4:  ADC timing overflow
    case  6:              //Vector  6:  ADC12IFG0
        //Is Memory Buffer 0 = A0 > 0.5AVcc?

          ADCResults = ADC12_A_getResults(ADC12_A_BASE,
                                        ADC12_A_MEMORY_0);
        if(ADCResults
           >= 0x7ff)
        {
            //set P1.0
            GPIO_setOutputHighOnPin(
                GPIO_PORT_P1,
                GPIO_PIN0
                );
        }
        else
        {
            //Clear P1.0 LED off
            GPIO_setOutputLowOnPin(
                GPIO_PORT_P1,
                GPIO_PIN0
                );
        }

        //Exit active CPU
        __bic_SR_register_on_exit(LPM0_bits);
    case  8: break;       //Vector  8:  ADC12IFG1
    case 10: break;       //Vector 10:  ADC12IFG2
    case 12: break;       //Vector 12:  ADC12IFG3
    case 14: break;       //Vector 14:  ADC12IFG4
    case 16: break;       //Vector 16:  ADC12IFG5
    case 18: break;       //Vector 18:  ADC12IFG6
    case 20: break;       //Vector 20:  ADC12IFG7
    case 22: break;       //Vector 22:  ADC12IFG8
    case 24: break;       //Vector 24:  ADC12IFG9
    case 26: break;       //Vector 26:  ADC12IFG10
    case 28: break;       //Vector 28:  ADC12IFG11
    case 30: break;       //Vector 30:  ADC12IFG12
    case 32: break;       //Vector 32:  ADC12IFG13
    case 34: break;       //Vector 34:  ADC12IFG14
    default: break;
    }
}

ACTUALIZACIÓN

He intentado hacer la misma funcionalidad no utilizar los controladores de periféricos de la biblioteca y parece que funciona perfectamente fuera del depurador. Esto me lleva a pensar que algo está mal con Texas Instruments controladores de Periféricos de la Biblioteca.

Aquí está el código que parecía funcionar bien fuera del depurador y doens no utilizar los controladores de Periféricos de la Biblioteca.

#include <msp430.h>

int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC12CTL0 = ADC12SHT02 + ADC12ON;         // Sampling time, ADC12 on
  ADC12CTL1 = ADC12SHP;                     // Use sampling timer
  ADC12IE = 0x01;                           // Enable interrupt
  ADC12CTL0 |= ADC12ENC;
  P6SEL |= 0x01;                            // P6.0 ADC option select
  P1DIR |= 0x01;                            // P1.0 output

  while (1)
  {
    ADC12CTL0 |= ADC12SC;                   // Start sampling/conversion

    __bis_SR_register(LPM0_bits + GIE);     // LPM0, ADC12_ISR will force exit
    __no_operation();                       // For debugger
  }
}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12_ISR (void)
#else
#error Compiler not supported!
#endif
{
  switch(__even_in_range(ADC12IV,34))
  {
  case  0: break;                           // Vector  0:  No interrupt
  case  2: break;                           // Vector  2:  ADC overflow
  case  4: break;                           // Vector  4:  ADC timing overflow
  case  6:                                  // Vector  6:  ADC12IFG0
    if (ADC12MEM0 >= 0x7ff)                 // ADC12MEM = A0 > 0.5AVcc?
      P1OUT |= BIT0;                        // P1.0 = 1
    else
      P1OUT &= ~BIT0;                       // P1.0 = 0

    __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12: break;                           // Vector 12:  ADC12IFG3
  case 14: break;                           // Vector 14:  ADC12IFG4
  case 16: break;                           // Vector 16:  ADC12IFG5
  case 18: break;                           // Vector 18:  ADC12IFG6
  case 20: break;                           // Vector 20:  ADC12IFG7
  case 22: break;                           // Vector 22:  ADC12IFG8
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26: break;                           // Vector 26:  ADC12IFG10
  case 28: break;                           // Vector 28:  ADC12IFG11
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break; 
  }
}

3voto

shash Puntos 668

A veces la razón para este comportamiento es que los ajustes de optimización son diferentes en el modo de depuración, y de alguna variable que el compilador cree que no es necesario es entonces optimizado.

Las correcciones para esto son para agregar "volátil" calificadores a dichas variables, o a su vez la optimización off (o al menos lo baje).

No sé si esta es su respuesta (el hilo becaume TL;DR), pero este dato sin duda debe aparecer como una posible solución para los motores de búsqueda.

2voto

Descargo de responsabilidad: yo no soy un experto en MSP430.

Sugiero el uso de

ADC12_A_disableConversions()

después de

ADC12_A_setupSamplingTimer() 

Extracto de MSP430 DriverLib for MSP430F5xx_6xx Devices


void ADC12_A_startConversion (uint16_t dirección base, uint16_t tartingMemoryBufferIndex, uint8_t conversionSequenceModeSelect)

Esta función permite a los/comienza el proceso de conversión del ADC. Si el sample/hold fuente de señal elegido durante la inicialización se ADC12OSC, entonces la conversión se inicia de inmediato, de lo contrario el elegido sample/hold fuente de la señal se inicia la conversión de un flanco ascendente de la señal. Tenga en cuenta al seleccionar los modos de conversión, que para secuenciados y/o repetido modos, para mantener el sample/hold-y-convertir proceso continuo sin un disparo desde el sample/hold fuente de la señal, las múltiples muestras debe ser activada mediante el ADC12_A_setupSamplingTimer() función. Tenga en cuenta que después se llama a esta función, el ADC12_A_disableConversions() debe ser llamado para volver a inicializar el ADC, vuelva a configurar un búfer de memoria de control, activar/desactivar el temporizador de muestreo, o para cambiar la tensión de referencia interna.

Nota: También hay un buen curso online gratuito para aprender de los sistemas integrados de diseño. Uno de ellos utiliza MSP430. Tengo la lista de algunos de ellos a continuación.


Referencias:

1voto

Stefan Arentz Puntos 151

Me pregunto por qué funciona en modo de depuración, que ha sido un tiempo desde que he trabajado con MSP430 y yo no estoy familiarizado con el driverlib. Pero:

GPIO_setAsPeripheralModuleFunctionOutputPin(
        GPIO_PORT_P6,
        GPIO_PIN0
        );

Seguramente no es la función que desea utilizar para cambiar este pin a una entrada analógica o es? Me gustaría probar:

GPIO_setAsPeripheralModuleFunctionIntputPin(
        GPIO_PORT_P6,
        GPIO_PIN0
        );

Pero como se ha visto en la descripción de las funciones de pin (gracias @CL.) es evidente que la configuración del pin para la función periférica de hecho va a ser suficiente y la dirección es ignorado. Así que es engañoso, pero no un interruptor.

A continuación, hay una pequeña cosa param.endOfSequence = ADC12_A_NOTENDOFSEQUENCE; que probablemente deberían ser param.endOfSequence = ADC12_A_ENDOFSEQUENCE; , pero como sólo se hace en un solo canal de conversión, no importa (es sólo un poco más claro). Y probablemente cambie ADC12IFG0 y ADC12IE0 a ADC12_A_IFG0 y ADC12_A_IE0 (pero son sólo define a los otros valores, por lo que no funcional problema)

Y le falta un break; después de que su caso en el vector de interrupción de la tabla, pero que no afectará el programa de mucho, solo una fuente para futuros errores.

Así que a partir de un firmware perspectiva sólo tengo la menor nitpicks.

Basado en los comentarios, y la lectura a través de la hoja de erratas, me pregunto si una sola __no_operation(); después de la __bic_SR_register_on_exit(LPM0_bits); en el ISR podría resolver el problema. La fe de erratas no menciona explícitamente el caso de los aquí presentes, pero hay problemas que implican la configuración de los modos de bajo consumo, de salir de los modos de bajo consumo y corromper el contador de programa. Así que tal vez es otro caso. Estos efectos podrían no estar presente durante la depuración como la emulación de módulo interfiere con la normal ejecución del núcleo.

Pero también se menciona, que si desactiva el mundial de habilitación de interrupción de su programa también funciona. Lo que me lleva a pensar que el programa se queda atascado en una interrupción, pero no el ADC. Usted no tiene que borrar el indicador de interrupción del ADC ya que se realiza automáticamente cuando la lectura de la memoria de la ADC.

Sólo otra nota en la programación, me gustaría obtener el análisis de la ADC valor de la ISR. Mantenerlos tan pequeño como sea posible, acabo de leer el valor de su variable global y abandonar el modo de baja potencia en la salida. Hacer todas las otras cosas en su aplicación principal. Hay casos donde se necesita un corto posible latencia de interrupción y si hago las cosas dentro de la ISR se bloqueará otras interrupciones (excepto habilitar interrupciones anidadas, pero esos son los malos).

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X