Pisca Led MSP430 LaunchPad (mspgcc)

Através deste post, vamos fazer o primeiro programa e gravar em um microcontrolador MSP430, mais especificamente o MSPG2231, usando a LaunchPad e o port do GNU gcc para o MSP430.

Para quem não conhece a LaunchPad, é um kit de desenvolvimento da Texas Instruments que custa somente $4.30. Com frete gratúito.

https://estore.ti.com/MSP-EXP430G2-MSP430-LaunchPad-Value-Line-Development-kit-P2031.aspx

Li alguns comentários na internet sobre pessoas que não conseguiram finalizar a compra. Mas eu consegui comprar sem nenhum problema. Fiz o pedido de cinco (dois para mim e os outros três para uns colegas de classe), e fiquei muito satisfeito com a compra.

Antes de escrever o programa, vamos conhecer algumas caracterísitcas do microcontrolador MSPG2231 e da LaunchPad.

O MSPG2231

O MSPG2231 é um microcontrolador da família MSP430, são microcontroladores de baixo consumo de energia, com CPU RISC de 16-bit. Este microcontrolador possui um total de 14 pinos e o que acompanha a LaunchPad vem em encapsulamento DIP.

Como todo microcontrolador, além de CPU e de dispositivos de entrada e saída os microcontroladores desta família possuem uma série de recursos como memória, timers, conversores analógico-digital e digital-analógico entre outros. No momento, vamos nos concentrar em usar as saidas para acender e apagar leds.

A LaunchPad

O que vem com a LaunchPad:

  1. Placa de desenvolvimento LaunchPad (MSP-EXP430G2)
  2. Um cabo USB
  3. Dois microcontroladores da família MSP430
    1. MSP430G2211
    2. MSP430G2231
  4. Quatro conectores de 10 pinos para placas de circuito impresso (dois machos e dois fêmeas)
  5. Um cristal (32kHz)
  6. Guia rápido
  7. Dois adesivos da LaunchPad

O kit de desenvolvimento possui dois leds, um ligado ao pino zero da porta um (P1.0) em um ligado ao pino seis também da porta um (P1.6).

Nosso código fará com que os dois leds fiquem piscando alternadamente, quando um estiver acesso, o outro estará apagado.

Então vamos lá, use seu editor de textos favorito e escreva o seguinte código.
Eu atualmente estou usando o eclipse, mas confesso que sou uma pessoa muito instável quanto a editor, vez por outra mudo de ferramenta.

// blink.c - Exemplo de pisca led
#include <msp430x20x1.h>

void Delay(void);

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;
    P1DIR = 0x41;
    P1OUT = 0x40;

    while(1){
        P1OUT = P1OUT ^ 0x41;
        Delay();
    }
}

void Delay(void) {
    unsigned int dly = 30000;
    while(--dly); {
        // Nothing:D
    }
}

Os passos seguintes, mostram como compilar o código e enviar para o microcontrolador. Para executar a tarefa de compilar, vamos usar o mspgcc, que no post anterior mostrei como instalar no Ubuntu 11.04 – cabe resaltar que ele também pode ser instalado no Windows e no OSX – e para programar o microcontrolador, vamos usar o mspdebug.

Por enquanto, vamos usar o mspgcc da forma mais simples possível, apenas informando o arquivo a ser compilado, no nosso caso blink.c e com o argumento -o informar o arquivo a ser gerado (-o blink.elf).

msp430-gcc blink.c -o blink.elf

Já compilamos o programa. Para grava-lo no microcontrolador vai ser preciso instalar o mspdebug, no ubuntu, esta é uma tarefa muito simples, basta executar o comando a seguir no terminal.

sudo apt-get install mspdebug

Agora sim! Até que enfim, vamos enviar o primeiro programa que fizemos para o microcontrolador, basta executar este comando após instalar o mspdebug.

sudo mspdebug rf2500 "prog blink.elf"

Olha ae o nosso código rodando na LaunchPad.
Agora só falta entender o que cada linha de código fez…

A linha 1 contém apenas um comentário, com o nome do arquivo e o que ele faz.

// blink.c - Exemplo de pisca led

A linha 2 é uma diretiva para que o compilador considere o conteúdo do arquivo msp430x20x1.h durante a copilação deste código.

#include <msp430x20x1.h>

A linha 4 é a declaração da função Delay, que é de fato o tempo entre a alteração dos estados dos leds.

void Delay(void);

Na linha 6 iniciamos a função principal do programa, que vai até a linha 15.

int main(void) {

A linha 7, serve para parar o Watchdog Timer (Um dispositivo de segurança que reincia o microcontrolador caso exista algum problema como por exemplo um loop infinto. De fato caso o Watchdog esteja ativado ele reinicia o microcontrolador ao passar de um determinado tempo, sendo assim softwares mais elaborados, que fazem uso do Watchdog devem se preocupar em reiniciar esta contagem antes dela acabar – uma forma de informar que o sistema está funcionando corretamente – para que o microcontrolador não seja reiniciado).

WDTCTL = WDTPW | WDTHOLD;

A linha 8 é a instrução que define que os pinos 0 e 6 da porta 1 serão utilizadas como pinos de saída. Na tabela abaixo isso se torna mais claro.

O número 0x41 em hexadecimal pode ser escrito como 0b01000001 em notação binária, e cada bit corresponde a um pino da porta, onde 0 configura o pino como entrada e 1 como saída.

Representação de 0x41 em binário Pino da porta Estado do pino
0 P1.7 Pino configurado como entrada
1 P1.6 Pino configurado como saída
0 P1.5 Pino configurado como entrada
0 P1.4 Pino configurado como entrada
0 P1.3 Pino configurado como entrada
0 P1.2 Pino configurado como entrada
0 P1.1 Pino configurado como entrada
1 P1.0 Pino configurado como saída
P1DIR = 0x41;

A linha 9 contém a instrução que leva os pinos da porta um para nível alto ou nivel baixo de acordo com o valor atribuído à P1OUT. Neste caso, como 0x40 pode ser representado por 0b01000000 em notação binária, neste instante apenas o pino 6 da porta 1 estará em nível alto, o pino 1, que também está configurado como pino de saída, estará com nivel baixo, pois seu bit correspondente está com valor 0, como pode ser visto com maior clareza na tabela abaixo.

Representação de 0x40 em binário Pino da porta Nível de tensão no pino
0 P1.7 Nível baixo
1 P1.6 Nível alto
0 P1.5 Nível baixo
0 P1.4 Nível baixo
0 P1.3 Nível baixo
0 P1.2 Nível baixo
0 P1.1 Nível baixo
0 P1.0 Nível baixo
P1OUT = 0x40;

A instrução da linha 11 coloca o microcontrolador em um loop infinito, fazendo com que as instruções dentro deste laço sejam executadas enquanto o programa esteja rodando. While significa enquanto, ou seja, enquanto o resultado da operação entre parnteses for verdadeira, o microprocessador ficará executando as instruções entre as chaves, no caso as instruções da linha 11 até a linha 14.

Em C, qualquer inteiro diferente de 0 equivale a verdadeiro e um inteiro igual a 0 equivale a falso.

Desta forma while(1) é o mesmo que dizer ao microcotrolador para que fique executando as instruções dentro das chaves do while para sempre.

while(1){

Na linha 12, executamos novamente a instrução P1OUT para mudar o nível de tensão nos pinos da porta P1.

Vamos usar a função lógica XOR (^) para modificar o bit 0 e o bit 6 da porta 1 (P1.0 e P1.6).

Lembrando que o estado atual dos niveis de tensão da porta P1 estão definidos para 0x40, vamos executar XOR entre os pinos do estado atual (P1OUT) e 0x41 e em seguida atribuir o resultado desta operação ao estado da porta.

Para facilitar o entendimento vejamos a operação XOR com os arguemntos da operação em suas representações binárias.

Numero em hexadecimal Número em binário
Estado atual da porta (P1OUT) 0x40 0b01000000
Valor fixo usado na operação 0x41 0b01000001
Resultado da operação XOR 0x01 0b00000001

Desta forma uma vez que a instrução desta linha seja executada, caso o estado da porta seja 0x40 (em binário 0b01000000, que equivale ao pino 6 da porta 1 em nível alto) ao final da execução o estado de P1OUT será alterado para 0x01 (em binário 0b00000001, que equivale ao pino 0 da porta 1 em nível alto).

P1OUT = P1OUT ^ 0x41;

A linha 13, desvia o fluxo do programa para a função Delay, que tem como único objetivo gastar tempo, de forma que seja perceptível a olho nú a alteração dos estados dos leds.

Delay();

Entre as linhas 17 e 22 está a função Delay. Esta função não recebe nenhum argumento e não retorna nada, como já foi dito, sua utilidade é gastar tempo e para isso toda vez que ela é chamada, em seu escopo é declarada uma variável de valor inteiro e sem sinal igual a 30000 (unsigned int dly = 30000;) que é decrementada através da instrução –dly.

Como condição do while o próprio valor de dly após o decremento, assim que dly chegar a 0 a função Delay é encerrada, e o fluxo do programa é redirecionado para a função principal (main).

void Delay(void) {
    unsigned int dly = 30000;
    while(--dly); {
        // Nothing:D
    }
}

Após retornar, o microcontrolador irá executar a instrução após a instrução Delay da linha 13 que, neste caso por estar em um loop infinito, será a instrução da linha 12. Novamente o XOR entre o estado atual da porta P1 (P1OUT) e 0x41.

Desta vez P1OUT é 0x01 e o resultado da operação XOR com 0x41 levará o estado de P1 de volta para 0x40.

Assim, o laço infinito em que colocamos o microcontrolado ficará alternando os estados dos pinos P1.0 e P1.6 e em seguida gastar um pouco de tempo para que possamos perceber esta alteração.

É isso ae pessoal, da próxima vez vamos fazer um exemplo mais elaborado usando uma protoboard para acender uma sequencia de leds.

10 pensou em “Pisca Led MSP430 LaunchPad (mspgcc)

  1. Pingback: Acionando uma sequência de LEDs com MSP430 | Terry Laundos (terryvel)

  2. Excelente artigo! Tenho o LaunchPad e compilei o código usando o IAR Workbench do Windows. Funcionou perfeitamente. Obrigado pela aula, aprendi mais do que na universidade.

  3. Obrigado pelo artigo, gostaria muito de tirar dúvidas, básicas.
    – o que a operação:
    WDCTL=WDTPW | WDTHOLD; faz? gostaria de saber a função do ” | ” aqui.
    – por que a constante “dly” recebeu esse valor específico de 30000?

    Meus agradecimento pelo post!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.