quarta-feira, 8 de outubro de 2014

MSP430 + LED 7 segmentos

Para implementar um contador usando mais de um bloco de LED de 7 segmentos é necessário multiplexar o sinal (ligar um bloco por vez), todavia usando-se frequência tal que não seja perceptível ao olhos o "liga/desliga"

Depois de implementar o circuito na protoboard basta rodar o programa abaixo
** Para o caso apresentado, foram utilizados blocos de LED 7Segmentos de anodo comum, o que significa que o MSP fornecerá o GND, assim sendo, quando o MSP fornecer sinal ALTO o led desliga e quando fornecer sinal BAIXO o led acende.

Tutorial em vídeo - https://www.youtube.com/watch?v=ATGpmncioA8
Veja funcionando - https://www.youtube.com/watch?v=JGgaYKlFPNA

_________________________________________________

/*IMPLEMENTAR UM CRONOMETRO COM LED DE 7 SEGMENTOS USANDO O TIMER0_A
*/
#include "io430.h"

int unidade = 0;
int dezena = 0;
int centena = 0;

void main (void)
{
  WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset
  BCSCTL1 = CALBC1_1MHZ;  //ajusta o DCO para 1MHz
  DCOCTL = CALDCO_1MHZ;   //ajusta o DCO para 1MHz
  P1DIR |= 0x7F;  //seta output direction para os bits 0,1,2,3,4,5,6
  P2DIR |= 0x07;  //seta output direction para os bits 0,1,2
  P2OUT |= 0x07;  //apaga com sinal alto
  P1OUT |= 0x7F;  //apaga com sinal alto

/* TESTE DOS LEDS E DOS NÚMEROS EM CADA BLOCO DE LED DE 7 SEGMENTOS
//P2.0 OUT 
  P2OUT |= 0x07;
  P2OUT &= ~0x01;
  //0
  P1OUT |= 0x7F;
  P1OUT &= ~0x3F;
  //1
  P1OUT |= 0x7F;
  P1OUT &= ~0x06;
  //2
  P1OUT |= 0x7F;
  P1OUT &= ~0x5B;
  //3
  P1OUT |= 0x7F;
  P1OUT &= ~0x4F;
  //4
  P1OUT |= 0x7F;
  P1OUT &= ~0x66;
  //5
  P1OUT |= 0x7F;
  P1OUT &= ~0x6D;
  //6
  P1OUT |= 0x7F;
  P1OUT &= ~0x7D;
  //7
  P1OUT |= 0x7F;
  P1OUT &= ~0x07;
  //8
  P1OUT |= 0x7F;
  P1OUT &= ~0xFF;
  //9
  P1OUT |= 0x7F;
  P1OUT &= ~0xEF;

 
//P2.1 OUT
  P2OUT |= 0x07;
  P2OUT &= ~0x02;
  //0
  P1OUT |= 0x7F;
  P1OUT &= ~0x3F;
  //1
  P1OUT |= 0x7F;
  P1OUT &= ~0x06;
  //2
  P1OUT |= 0x7F;
  P1OUT &= ~0x5B;
  //3
  P1OUT |= 0x7F;
  P1OUT &= ~0x4F;
  //4
  P1OUT |= 0x7F; 
  P1OUT &= ~0x66;
  //5
  P1OUT |= 0x7F; 
  P1OUT &= ~0x6D;
  //6
  P1OUT |= 0x7F;
  P1OUT &= ~0x7D;
  //7
  P1OUT |= 0x7F; 
  P1OUT &= ~0x07; 
  //8
  P1OUT |= 0x7F; 
  P1OUT &= ~0xFF;
  //9
  P1OUT |= 0x7F; 
  P1OUT &= ~0xEF;

//P2.2 OUT
  P2OUT |= 0x07; 
  P2OUT &= ~0x04;
  //0
  P1OUT |= 0x7F;
  P1OUT &= ~0x3F;
  //1
  P1OUT |= 0x7F; 
  P1OUT &= ~0x06; 
  //2
  P1OUT |= 0x7F;
  P1OUT &= ~0x5B;
  //3
  P1OUT |= 0x7F; 
  P1OUT &= ~0x4F; 
  //4
  P1OUT |= 0x7F; 
  P1OUT &= ~0x66; 
  //5
  P1OUT |= 0x7F;
  P1OUT &= ~0x6D;
  //6
  P1OUT |= 0x7F;
  P1OUT &= ~0x7D;
  //7
  P1OUT |= 0x7F;
  P1OUT &= ~0x07;
  //8
  P1OUT |= 0x7F;
  P1OUT &= ~0xFF;
  //9
  P1OUT |= 0x7F;
  P1OUT &= ~0xEF;
*/

 
//Setup do timer
  TA0CTL = TASSEL_2 + ID_2 + MC_1;
          /*TASSEL (timer_A clock source select) seleciona a fonte do timer, 2=0x10 que indica SMCLK
          ID (input divider) 0=0x00(/1) > 1=0x01(/2) > 2=0x10(/4) > 3=0x11(/8)    -->QUANTO MAIOR O NUMERO MAIS DEMORA PARA CHEGAR NO VALOR MAXIMO (PISCA MAIS LENTO)
          MC (mode control) 0=0x00(stop) > 1=0x01(up) > 2=0x10(continuous) > 3=0x11(up/down)
               
          UP(periodo diferente de 0xFFFF) conta até o valor armazenado no registrador TACCR0
          e seta a flag CCIFG no registrador TACCTL0 quando atinge o valor de comparação no registrador TACCR0
          e seta a flag TAIFG no registrador TACTL quando o timer passa do valor armazenado no registrador TACCR0 para 0
                 
          CONTINUOUS seta flag TAIFG no registrador TACTL quando zera a contagem
                 
          UP/DOWN timer conta até TACCR0 e depois decrementa até zero (grafico triangular)
          seta flag CCIFG em DOIS MOMENTOS: quando atinge o valor de TACCR0 ou volta para zero
*/
   
  TA0CCTL0 = CCIE; //(capture/compare interrupt enable) habilita a interrupção pela flag CCIFG
  TA0CCR0 = 0x61A8;
  TA0CCTL0 &= ~CCIFG; //limpa flag de interrupção

//Habilita interrupção
  __bis_SR_register(GIE); //habilita interrupção
  //__enable_interrupt(); //outra forma de habilitar interrupção

 
//MULTIPLEXAÇÃO
for (;;) //loop infinito
{
  switch (unidade) {
  case 0:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    break;
  case 1:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x06;
    break;
  case 2:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x5B;
    break;
  case 3:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x4F;
    break;
  case 4:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x66;
    break;
  case 5:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x6D;
    break;
  case 6:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x7D;
    break;   
  case 7:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x07;
    break;
  case 8:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xFF;
    break;
  case 9:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xEF;
    break;
  case 10:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    unidade = 0;
    dezena++;
    break;
  }
  P2OUT &= ~0x04; //acende o led da unidade
 
  switch (dezena) {
  case 0:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    break;
  case 1:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x06;
    break;
  case 2:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x5B;
    break;
  case 3:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x4F;
    break;
  case 4:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x66;
    break;
  case 5:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x6D;
    break;
  case 6:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x7D;
    break;   
  case 7:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x07;
    break;
  case 8:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xFF;
    break;
  case 9:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xEF;
    break;
  case 10:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    dezena = 0;
    centena++;
    break;
  }
  P2OUT &= ~0x02; //acende o led da dezena

  switch (centena) {
  case 0:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    break;
  case 1:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x06;
    break;
  case 2:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x5B;
    break;
  case 3:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x4F;
    break;
  case 4:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x66;
    break;
  case 5:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x6D;
    break;
  case 6:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x7D;
    break;   
  case 7:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x07;
    break;
  case 8:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xFF;
    break;
  case 9:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0xEF;
    break;
  case 10:
    P1OUT |= 0xFF;
    P2OUT |= 0x07;
    P1OUT &= ~0x3F;
    centena = 0;
    break;
  }
  P2OUT &= ~0x01; //acende o led da centena

}
}

#pragma vector = TIMER0_A0_VECTOR
__interrupt void interrupt_timer(void)
{
  unidade++;
  TA0CCTL0 &= ~CCIFG; //limpa flag de interrupção
}
____________________________________________________________________

Nenhum comentário:

Postar um comentário