dimanche 29 janvier 2012

Faire clignoter des LEDs avec le Launchpad (MSP430)

Voici un petit exercice d'exploration de mon nouveau Launchpad de Texas Instruments:  faire clignoter 6 LEDs l'une à la suite de l'autre, question de comprendre comment modifier l'état de chaque sortie numérique du microcontrôleur.

Je dois dire que je suis encore à la recherche d'une source de documentation qui m'expliquerait clairement les bases de la programmation de mon Launchpad.  Le site de TI explique comment le commander et comment installer les logiciels, et ensuite ça devient plutôt confus.  Les tutoriels sur internet  ne sont pas si nombreux, et réfèrent parfois à des fichiers qui ne sont plus disponibles sur le site de TI!

Le Launchpad MSP430 est muni d'entrées-sorties numériques numérotées P1.0 à P1.7, puis P2.0 à P2.5 .  Mon but était de faire clignoter l'une après l'autre 6 LEDs branchées aux ports P1.0 , P1.1 , P1.2 , P1.3, P1.4, et P2.5.

Dans un premier temps, il faut activer les sorties.  Sur Arduino, il s'agit d'écrire "pinMode(13, OUTPUT);" si on veut, par exemple, que le port numérique numéro 13 soit défini comme une sortie.

Pour le MSP430, c'est un petit peu plus compliqué:  les 8 sorties de la sortie P1 dépendent de l'état de chaque bit d'un nombre binaire stocké dans la variable P1DIR:

  • Si P1DIR vaut 00000000, alors tous les ports P1 sont des entrées.
  • Si P1DIR vaut 00000001, alors seul le port P1.0 est une sortie.
  • Si P1DIR vaut 00000010, alors seul le port P1.1 est une sortie.
  • Si P1DIR vaut 00001111, alors les ports P1.0 , P1.1, P1.2  et P1.3 sont des sorties.
C'est le même principe pour régler l'état (haut ou bas de chaque sortie).  Sur Arduino, on écrit "digitalWrite(13, HIGH);" ou ""digitalWrite(13, LOW);".  Sur le Launchpad, on règle à 0 ou 1 chaque bit d'un nombre binaire:
  • Si P1OUT vaut 00010000, alors le port P1.4 est haut, tous les autres sont bas
  • Si P1OUT vaut 11111111 alors tous les ports P1 sont hauts
  • Si P1OUT vaut 10101010 alors les ports P1.1, P1.3, P1.5 et P1.7 sont hauts.
Mais dans le programme, ce nombre doit être écrit en hexadécimal (du moins je n'ai pas trouvé de façon d'utiliser directement la version binaire).  Pour ce faire, on peut utiliser un des nombreux convertisseurs disponibles sur le web.  Ainsi, pour allumer la LED reliée à P1.0, le nombre binaire 00000001 devient 0x01.  Pour allumer la LED reliée à P1.4, le nombre binaire 00010000 devient 0x10...

L'avantage, c'est qu'on peut déterminer l'état des 8 ports en même temps au moyen d'une directive très courte.  L'inconvénient (irritant majeur en ce qui me concerne), c'est que l'écriture et la lecture du programme par un être humain devient assez arride.

Quand je programme mon Arduino, ou quand je lis un sketch Arduino réalisé par quelqu'un d'autre, j'ai l'impression de lire des instructions en Anglais qui ne sont pas très éloignées de la communication humaine:
        digitalWrite(13, HIGH);
        delay(1000);
        digitalWrite(13, LOW); 
        delay(1000); 
...Un peu comme si je disais à quelqu'un "SVP, pourrais-tu allumer la lumière numéro 13?  Attend un peu... Maintenant, éteint-là, et attend encore...

Alors que P1OUT = 0x10; suivi d'une instruction de calcul répétitif car il n'existe même pas de fonction "delay", ça me semble beaucoup moins clair...

Je continue donc d'en arriver à la même conclusion:  je préfère mon Arduino!

Ci-dessous, mon programme complet pour faire clignoter 6 LEDs:




/****************************************************************
6 LEDs clignotent en alternance.
*****************************************************************/

#include  

void delai(void)
 {
    volatile unsigned int i;
    i = 50000;        // Delai
    do (i--);
    while (i != 0);
 }


void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;         // Stop watchdog timer

  P1DIR |= 0xFF;  // toutes les sorties 1.x sont output car FF 
                  // est l'équivalent de 11111111
  P2DIR |= 0xFF;  // toutes les sorties 2.x sont output car FF 
                  // est l'équivalent de 11111111
    
  for (;;)
  {
    
    P1OUT = 0x01;       // Équivalent de 00000001  Seule la sortie 
                        // 1.0 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x02;       // Équivalent de 00000010  Seule la sortie 
                        // 1.1 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x04;       // Équivalent de 00000100  Seule la sortie 
                        // 1.2 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();

    P1OUT = 0x08;       // Équivalent de 00001000  Seule la sortie 
                        // 1.3 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();
    P1OUT = 0x10;       // Équivalent de 00010000  Seule la sortie 
                        // 1.4 est haute, les autres sont basses
    P2OUT = 0x00;       // Toutes les sorties 2.x sont basses
    delai();
    P1OUT = 0x00;       // Toutes les sorties 1.x sont basses
    P2OUT = 0x20;       // La sortie 2.5 est haute
    delai();
                  
  }
}








Yves Pelletier (Twitter: @ElectroAmateur)

4 commentaires:

  1. Merci pour ce partage.
    Voici la façon d'utiliser directement la version binaire :
    unsigned char P1DIR = 0b11111111;

    RépondreSupprimer
  2. Pour écrire en binaire (ici sur le pin 4) de façon plus lisible :

    #define LED 4
    #define Pous 3
    ...

    P1DIR |= (1<<LED) // définit le bit 4 à 1
    P1OUT |= (1<<LED) // allume la led

    L'opération de décalage étant constante, elle est calculée par le compilateur..

    Pour lire :

    if( !( P1IN & (1<<Pous)) )
    {
    // Le poussoir en pin 3 est actif (ici actif à 0)
    ...
    }

    On peut faire de même pour définir P1DIR en une instruction :

    P1DIR = (1<<LED) | ~(1<<Pous)

    Je n'ai pas de quoi tester sous la main mais l'idée est là

    RépondreSupprimer
  3. C'est encore plus simple de faire clignoter une LED avec Energia! c'est Pareil que Arduino.

    PinMode (P1_2, OUTPUT); // pour la declaration du port a utiliser

    digitalWrite( P1_2, HIGH);
    delay(500);
    digitalWrite (P1_2,LOW);
    delay(500;

    RépondreSupprimer
    Réponses
    1. En effet. Cet article date de 2012. J'ai ensuite publié de nombreux articles concernant Energia et ne suis jamais retourné à Code Composer Studio...

      Supprimer