sexta-feira, 8 de abril de 2011

Compreendendo o programa do MSP430-F2013

Neste post, vamos explicar como funciona programa exemplo que faz piscar o led embutido na placa e também compreender um pouco mais sobre operações de tempo na marra. Abaixo vemos o programa exemplo codificado em linguagem C, já que não há um display na placa para escrever “Hello World”, há um led para informar que o micro está respondendo e com este led iremos programar, por enquanto.

#include "msp430.h"

int main(void)
{
   WDTCTL = WDTPW + WDTHOLD;      // Pára o watchdog
   P1DIR |= 0x01;                 // Seta Porta 1 como saída
   volatile unsigned int i;       // Volatile para que o compilador não
                                  // tenha que otimizar erroneamente no assembly

   for (;;)                       // Inicia loop infinito
   {
       P1OUT ^= 0x01;             // Alterna P1 usando X-OR*
       for (i=0;i<10000;i++);     // Gasto decremental de tempo por software
   }
}

Podemos perceber que a alteração da variável P1OUT é feita usando uma operação de *XOR, conhecida como Exclusive OR, comparação lógica que resulta em 1 se compara valores diferentes:

 Valor A
0
0
1
1
 Valor B
0
1
0
1
 A XOR B
0
1
1
0

No exemplo estamos fazendo uma XOR com o valor 1. Então cada vez que essa operação for executada o valor de P1OUT será trocado.

Tomando de base o mesmo programa, vamos modificá-lo para testar o dispositivo. Vamos tentar modificar intuitivamente (tentativa e erro) o tempo que o led fica acesso através do delay gerado pela função for.

void main(void)
{
   volatile unsigned long int i;  // unsigned long int pode receber até 4*10^6
        WDTCTL = WDTPW + WDTHOLD;
   P1DIR |= 0x01;

   for(;;)
   {
      P1OUT ^= 0x01;
       for (i=0;i<100000;i++);  // Delay incremental maior
   }
}

A variável i foi modificada para long pois queriamos testar o maior tempo possível. Fazendo uma análise dos valores empíricos, obteve-se um tempo médio experimental entre uma piscada e outra de 1,70 segundos (i=100000).
Dobrando-se o valor final de i (200000) obtivemos o tempo de 2,8 segundos e quando fizemos o teste dividindo o valor final de i pela metade (50000) resultou em 1,05 segundos. Fazendo a relação entre os tempos e valores de i obtivemos  as seguintes proporções:


led [μs]
2,80
1,70
1,05
for [loop]
200.000,00
100.000,00
50.000,00
T [μs/loop]
1,40E-05
1,70E-05
2,10E-05

T = 1,7 10-5 segundos (17μs)

.

Fazendo uma avaliação do gráfico, depreendemos que o tempo médio do período T é de 1,16(μs), e um loop com i de 0 a 0 teria 0,5(s).

Percebemos que existe uma grande diferença entre os tempos para cada situação. Isso se deve ao overhead de instruções, que é constante e impacta mais os tempos menores e principalmente aos erros de medida.
Com isso podemos fazer uma conta aproximada:

Supondo que queremos um tempo de 60(s) ou 1 minuto.




Então o código para o led piscar a cada 1 minuto deverá ser:

void main(void)
{
   volatile unsigned long int i;   
        WDTCTL = WDTPW + WDTHOLD;
   P1DIR |= 0x01;

   for(;;)
   {
       P1OUT ^= 0x01;
       for (i=0;i<3529411;i++);       // Delay de 60s
   }
}

Com essas informações podemos criar uma primeira função que cria um delay de  t (ms):

void tempo (unsigned long int t)
{
   unsigned long int i;
   unsigned long int max;

   if (t < t_max)            //t_max é o maximo que t pode ter sem estourar           {
       max = t*58823;        // max = t_desejado/t_ciclo
       for (i=0;i<max;i++);  // Delay de 60s
   }
}

No próximo post estaremos aprendendo mais sobe as bibliotecas básicas do MSP e criaremos a nossa própria biblioteca.

Até semana que vem!

Nenhum comentário:

Postar um comentário