Cómo generar una señal PWM de 1 segundo en el MSP430G2553

Hola, estoy haciendo un programa que me genere una señal PWM (Pulse-width modulation, lo que viene siendo una señal cuadrada). El programa lo tengo configurado así:
Código:
void configuroPWM(void)
{
  P1DIR|=BIT6;                  //P1.6 como salida
  P1SEL|=BIT6;                  //Permite al pin 1.6 ser salida especial-> TA0.1
                                //Timer0_A, capture: CCI1A input, compare: Out1 output
  //A continuación, configuramos el Timer_A
  
  TA0CCR0 = 999;	//PWM de 1KHz, tiene un periodo de 1milisegundo.
  TA0CCR1=500; // ciclo de trabajo (tiempo que la señal está a nivel alto) del 50%, la señal
//está a nivel alto 0.5milisegundos.
  TA0CTL = TASSEL_2+MC_1;        //Elegimos como fuente de reloj SMCLK(TASSEL_2) que nos //da una frecuencia de 1MHz
                                //y que cuente en modo ascendente. ACLK -> TASSEL_1. CAP=0, //estamos en modo comparación.
  TA0CCTL1 = OUTMOD_7;             //Configuramos la salida en modo Reset/Set
                                //la salida se pone a 0 cuando la cuenta llegue al valor de //TACCR1(duty cycle)
                                //y se pone a 1 cuando la cuenta llega al valor TACCR0 (periodo)

  //si queremos un PWM de frecuencia 1Khz, por ejemplo, simplemente tendremos
  //que dividir (frecuencia_del_reloj_elegido(en este caso SMCLK=1MHz)/1Khz)-1=TACCR0.
  //En este caso, frecuencia_del_reloj_elegido=1.1MHz
  //En este caso he elegido un duty cicle del 25%

}

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
	
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;  // SMCLK = DCO = 1MHz
    configuroPWM();
    _BIS_SR(LPM0_bits + GIE);
}

En este ejemplo que tengo hecho, el período de la señal PWM es de 1 milisegundo. Si quiero generar una señal PWM con un período de 1 segundo y con esta misma fuente de reloj, el valor que le debería meter a TA0CCR0 sería 999999, valor demasiado grande ya que el valor máximo de TA0CCR0=FFFFh=65535.
No sé como hacer esto, si alguien me puede ayudar sería de gran ayuda.

Un saludo y muchas gracias.
 
No se si es la respuesta que esperabas, pero los PWM de TI son muy veloces. Para esta aplicacion, con un periodo tan lento, yo usaria un timer para generar interrupciones.

Alternativamente, si tenes un reloj de 32768Hz, lo podes usar como fuente de reloj para generar PWM de baja velocidad.
 
El problema es que creo que la fuente de reloj ACLK que proporciona una frecuencia de 32768 es muy inestable. Sabes de otra fuente que sea de baja frecuencia y que sea estable?
 
Sí, tengo el Launchpad pero no sé como se instala el cristal de 32768 que trae externo. Sabes cómo y donde se instala? Y es este reloj externo de 32768 más estable que el ACLK?
Gracias un saludo.
 
Para fijarte como se instala creo que en el sitio de TI vas a encontrar informacion, no es muy dificil. Yo tenia un Launchpad hace mas o menos un anio pero cambie de trabajo asi que no lo tengo mas. Me podria comprar uno, salen dos pesos, pero en estos dias ando en otros temas...

El cristal es muy estable, sin el cristal lo que funciona es, creo, un oscilador RC o algo asi que es como vos dijiste muy inestable. Una vez que el cristal esta instalado, ACLK toma la frecuencia del cristal.
 
Última edición:
El cristal se instala en el pequeño Pad que tiene marcado como Q2, yo tengo dos LaunchPad y en una de ellas soldé el cristal, recomiendo que remuevas los resistores R28 y R29 para desconectar los headers una ves que sueldes el cristal, yo no lo hice cuando lo soldé por que se me olvidó y ya había desconectado el cautín :LOL: mas tarde lo hago cuando suelde otra cosa.
 

Adjuntos

  • LP.jpg
    LP.jpg
    313.4 KB · Visitas: 33
Muchas gracias por vuestra ayuda. He ido al laboratorio de mi facultad para ver en el osciloscopio la señal PWM de 1 segundo seleccionando como señal de reloj ACLK (32768 Hz, sin instalar el cristal de cuarzo de 32KHz) para comprobar que es de 1 segundo el periodo y me he llevado la sorpresa de que el periodo que me sale es de 1.88 segundos, la verdad es que no entiendo por qué sale este período ya que he hecho la siguiente cuenta para calcular el valor de TACCR0:
TACCR0=(32768Hz/1Hz(el período que quiero))-1=32767; TACCR1=16384 si quiero por ejemplo que esté activa el 50% del período.
Os copio el código:
Código:
void configuroPWM(void)
{
  P1DIR|=BIT6;                  //P1.6 como salida
  P1SEL|=BIT6;                  //Permite al pin 1.6 ser salida especial-> TA0.1
                                //Timer0_A, capture: CCI1A input, compare: Out1 output
  
  TA0CCR0=32767;
  TA0CCR1=16384;
  
  TA0CTL = TASSEL_1+MC_1;        //Elegimos como fuente de reloj ACLK(TASSEL_21) que nos da una //frecuencia de 32768 Hz
                                //y que cuente en modo ascendente. ACLK -> TASSEL_1. CAP=0, estamos en modo comparación.
  TA0CCTL1 = OUTMOD_7;             //Configuramos la salida en modo Reset/Set
                                //la salida se pone a 0 cuando la cuenta llegue al valor de TACCR1(duty cycle)
                                //y se pone a 1 cuando la cuenta llega al valor TACCR0 (periodo)

}

Alguién sabe por qué me sale un periodo de 1.88 segundos en vez de 1 segundo?.
 
Momento, no es lo mismo usar el cristal de 32.768KHz al oscilador interno para ACLK, el oscilador empleado para esta tarea es el VLO que tiene una frecuencia típica de 12KHz y pude variar (revisa el datasheet del dispositivo) por ejemplo en el G2553 de 4~20KHz, tienes que soldar el cristal externo y usar LFXT1 como fuente de reloj.
Código:
#include <msp430.h> 

/*
 * main.c
 */
void configuroPWM(void)
{
  P1DIR|=BIT6;                  //P1.6 como salida
  P1SEL|=BIT6;                  //Permite al pin 1.6 ser salida especial-> TA0.1
                                //Timer0_A, capture: CCI1A input, compare: Out1 output

  TA0CCR0=32767;
  TA0CCR1=16384;

  TA0CTL = TASSEL_1+MC_1;       //Elegimos como fuente de reloj ACLK(TASSEL_21) que nos da una //frecuencia de 32768 Hz
                                //y que cuente en modo ascendente. ACLK -> TASSEL_1. CAP=0, estamos en modo comparación.
  TA0CCTL1 = OUTMOD_7;          //Configuramos la salida en modo Reset/Set
                                //la salida se pone a 0 cuando la cuenta llegue al valor de TACCR1(duty cycle)
                                //y se pone a 1 cuando la cuenta llega al valor TACCR0 (periodo)

}

void main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    BCSCTL1 = 0;                //Lipiar registro de control del oscilador antes de asignar
    BCSCTL3 = 0;
    BCSCTL1 = CALBC1_1MHZ;
    DCOCTL = CALDCO_1MHZ;       // SMCLK = DCO = 1MHz
    /*
     * Usar  BCSCTL3 = XCAP_3; para activar la capacitancia de 12.5pf para el cristal
     * En caso de usar el VLO emplear BCSCTL3 = LFXT1S_2; para selecionarlo
     * por algun motivo funciona si lo dejas en blanco cuando le ejecutas con el CCS
     * pero cuando detienes el debug ya no me trabaja el codigo.
     */
    BCSCTL3 = XCAP_3;           //XCAP_3 activa la capacitancia interna de 12.5pf
    configuroPWM();
    _BIS_SR(LPM3_bits + GIE);  //Ya que solo estas usando ACLK puedes usar LPM3 en lugar de LPM0
}

Puse el mismo código en las 2 LaunchPad y conecte el reset de ambas, no tengo osciloscopio pero el cronometro si me marca 1s mientras que la otra me toma ligeramente más de 3 y cuando extraje el MCU de la LaunchPad con cristal y la puse en la otra se tardó más de 26s. El VLO tiene variación de 0,5%/ºC respecto a la temperatura y de 4%/V por el voltaje, si puedes obtener la frecuencia real de tu VLO podrías rehacer los cálculos para implementarlo.
 
Última edición:
Hola muchas gracias a todos y en especial a Nuyel, me estás sirviendo de gran ayuda. Soldé el cristal de 32.768 KHz a la placa y he probado para ver la señal en el osciloscopio y la señal PWM que me sale es de periodo 2.92 segundos, cuando debería de ser 1 segundo. El cristal está bien soldado y el codigo es el mismo que puse antes:
Código:
void configuroPWM(void)
{
  P1DIR|=BIT6;                  //P1.6 como salida
  P1SEL|=BIT6;                  //Permite al pin 1.6 ser salida especial-> TA0.1
                                //Timer0_A, capture: CCI1A input, compare: Out1 output
  
  TA0CCR0=32767;
  TA0CCR1=16384;
  

  TA0CTL = TASSEL_1+MC_1; // elijo ACLK que creo que tomará directamente la señal del cristal de cuarzo de 32768Hz.
  TA0CCTL1 = OUTMOD_7;             //Configuramos la salida en modo Reset/Set
                             
}

Hay que cambiar algún bit de los registros de los relojes? o que hago mal?

Un saludo y gracias
 
Última edición:
Pues a mi me va bien, podrías intentar configurar bien BCSCTL3 = XCAP_3; con eso activas la capacitancia de 12.5pf que requiere el cristal (pagina 290 del manual de la familia MSP430x2xx SLAU144I), el registro de control 2 no es importante ya que no se usan esos relojes, el código que subí funcionó bien y lo probé en el G2231, G2553, G2452 y F2013
 
Hola de nuevo, me han dicho que por qué no pruebo a implementar un contador que se incremente a partir del periodo máximo del reloj y que provoque el pulso cuando se haya llegado al tiempo que quiero, pero la verdad es que no sé o no entiendo bien como debería de hacer esto. Es decir por lo que entiendo es que con el reloj SMCLK=1MHz puedo entonces generar una señal de 1 segundo de período, pero para ello debería de implementar un contador que cuando llegue al valor máximo de TA0CCR0=0xFFFFh=6535 se incremente hasta que llegue al valor 1MHz/65535=1.90736 y entonces me genere el pulso?

En resumen, como podría hacer esto queriendo generar una señal PWM de 1 segundo de duración y con SMCLK=1MHz.

Un saludo y muchas gracias
 
Necesitaria que fuese por software usando la interrupcion del timer, no recuerdo como se configura pero teoricamente podrias elevar el valor a 32bits (o incluso más) combinando un contador adicional que se modifique por el timer.
 
Atrás
Arriba