MSP430 El temporizador A no responde correctamente

0

Necesito ayuda con un MSP430F2272. Estoy trabajando en una tarea para la clase donde se supone que debo hacer un generador de funciones. Pongo el código que he escrito hasta aquí abajo. La mayoría de las partes individuales del código funcionan bien, excepto por una cosa: el TimerA, que se supone que controla la frecuencia de la salida, no se dispara correctamente. Después de iniciar el programa, el depurador llega hasta P1DIR = 0x00 en main() antes de ingresar al ISR TimerA0. El problema es inmediatamente después de que se realiza el ISR, salta de nuevo a P1DIR = 0x00 , y luego entra nuevamente en el ISR. El contador del temporizador solo está en 0x0005 y el registro de comparación contiene 0x0064 , por lo que no debería activarse, pero sigue haciéndolo. Si pudiera hacer que eso parara, estoy bastante seguro de que el resto del programa funciona exactamente como lo deseo. ¿Alguien puede ayudar?

#include <msp430.h>
#include "msp430x22x2.h"

/* P4 - Digital Input
 * P2 - DAC Output
 * P3 - ADC Input
 *
 */

char sine[50] = {0x80,0x90,0xA0,0xB0,0xBE,0xCC,0xD9,0xE4,0xED,0xF5,0xFA,0xFE,0xFF,0xFF,0xFC,0xF8,0xF1,0xE8,0xDE,0xD2,0xC5,0xB7,0xA8,0x98,0x88,0x77,0x67,0x57,0x48,0x3A,0x2D,0x21,0x17,0x0E,0x07,0x03,0x00,0x00,0x01,0x05,0x0A,0x12,0x1B,0x26,0x33,0x41,0x4F,0x5F,0x6F,0x7F};
char squr[50] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
char trgl[50] = {0x00,0x0A,0x15,0x20,0x2A,0x35,0x40,0x4A,0x55,0x60,0x6A,0x75,0x80,0x8A,0x95,0xA0,0xAA,0xB5,0xC0,0xCA,0xD5,0xE0,0xEA,0xF5,0xFF,0xFF,0xF5,0xEA,0xE0,0xD5,0xCA,0xC0,0xB5,0xAA,0xA0,0x95,0x8A,0x80,0x75,0x6A,0x60,0x55,0x4A,0x40,0x35,0x2A,0x20,0x15,0x0A,0x00};
char swth[50] = {0x00,0x05,0x0A,0x0F,0x14,0x1A,0x1F,0x24,0x29,0x2F,0x34,0x39,0x3E,0x43,0x49,0x4E,0x53,0x58,0x5E,0x63,0x68,0x6D,0x72,0x78,0x7D,0x82,0x87,0x8D,0x92,0x97,0x9C,0xA1,0xA7,0xAC,0xB1,0xB6,0xBC,0xC1,0xC6,0xCB,0xD0,0xD6,0xDB,0xE0,0xE5,0xEB,0xF0,0xF5,0xFA,0xFF};
    int i = 0;
    int wave_sel = 0;
    char dout = 0x00;

void dac_write(char data){
    int output = 0x0000;
    char temp;
    signed char x;

    P2SEL &= 0xF8; //select digital I/0
    P2DIR |= 0x07; //set directon register P2.0 - P2.2
    P2OUT &= 0xF8; // clear data, clock, and enable
    P2OUT |= 0x04; // set enable high

    temp = data; // format data
    data = data >> 4;
    data &= 0x0F;
    data |= 0xF0;
    output = data;
    output <<= 8;
    data = temp;
    data <<= 4;
    data &= 0xF0;
    output |= data;

    P2OUT &= 0xFB; //set enable low
    for (x = 15; x > -1; x--){  //send out 16 bits of data
        P2OUT |= (output >> x) & 0x01;
        P2OUT |= 0x02;
        P2OUT &= 0xFD;
        P2OUT &= 0xFE;
    }
    P2OUT |= 0x04; // set enable high
}

int main(void) {
WDTCTL = WDTPW + WDTHOLD;   // Stop watchdog timer
TACCTL0 = CCIE;
TACTL = TASSEL_2 + MC_1 + ID_3; //CLK(1MHz) /8
TACCR0 = 100; //25-100 Hz 250-10Hz
TACCR1 = 0xFFFF;
TACCR2 = 0xFFFF;
_BIS_SR(LPM0_bits + GIE);

    P1DIR   = 0x00;
    P2DIR   = 0xFF; //DAC Ouptut
    P3DIR   = 0x00; //ADC Input
    P4DIR   = 0x00; //Digital Input
    P3SEL  |= BIT6 + BIT7;

    ADC10CTL0  = SREF_0 + ADC10SHT_3 + MSC + ADC10ON + ADC10IE;
    ADC10CTL1  = INCH_7 + ADC10DIV_3 + CONSEQ_1;
    ADC10AE0  |= 0xC0; //Turn on ADC of 3.6 and 3.7
    ADC10DTC1  = 2;

    double amp = 0;
    double freq = 0;
    unsigned int ADC[2];

    for(;;)
    {
        wave_sel =P4IN;

        ADC10CTL0 &= ~ENC;
        while (ADC10CTL1 & BUSY);
        ADC10SA = (unsigned int)ADC;
        ADC10CTL0 |= ENC + ADC10SC;

        freq = (double)ADC[0]/1023;
        amp  = (double)ADC[1]/1023;    

        TACCR0 = 25 + (freq*225);
        dout *= amp;
        dac_write(dout);
    }
}

#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1(void)
{}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
    if (wave_sel == 0)
    {
        dout = sine[i];
    }else if (wave_sel == 1)
    {
        dout = squr[i];
    }else if (wave_sel == 2)
    {
        dout = trgl[i];
    }else if (wave_sel == 3)
    {
        dout = swth[i];
    }
    if (i<49){
        i += 1;
    }else{
        i = 0;
    }
}
    
pregunta Zephyr

1 respuesta

1

En el MSP430, los temporizadores son módulos de hardware y se ejecutan cada vez que se ejecuta el reloj al que están conectados. Está ejecutando SMCLOCK (TACTL = TASSEL_2), que probablemente sea el mismo que el reloj de la CPU (MCLOCK). Dependiendo de las opciones de su depurador, Mclock puede o no estar ejecutándose entre puntos de interrupción. Si se está ejecutando, el programa ingresará el ISR después de cada punto de interrupción, ya que pausan la CPU por más tiempo que el período del contador. Cuando la CPU reanude la operación, servirá inmediatamente todas las interrupciones que se activan durante la pausa.

Además, incluso si Mclock no se ejecuta todo el tiempo, no estoy seguro de que el número de ciclos de reloj sea el mismo con y sin el depurador. Además de eso, el temporizador continuará ejecutándose mientras ingresa el ISR y antes de alcanzar el siguiente punto de interrupción, por lo que el valor del contador actual (TAR) no será exacto. Si puede, intente depurar el temporizador de otra manera, como UART.

    
respondido por el pserra

Lea otras preguntas en las etiquetas