Comment faire clignoter les deux leds présentes sur le Launchpad?Pour ce tuto, je vais utiliser le MSP430G2231 (parce qu'il est déjà sur mon launchpad), mais le 2211 fonctionnera tout aussi bien.
Si vous n'avez pas encore fait vos premiers pas avec CCS, je vous invite à aller voir le
tuto-001, qui explique comment installer CCS et comment créer un projet pour MSP430.
Avant d'attaquer le code, il reste encore une étape importante, il va falloir que je vous explique l'architecture physique et logique de ce µC.
(Attention, je vais vous faire chauffer les neurones!)
L'architecture logique et physique du MSP430 sur son LaunchPadComme on peut voir sur le schéma, le µC est équipé de :
- 2kB de mémoire flash
- 128B de RAM
- un CPU avec 16 registres
- un port P1 gérant 8 I/O
Le reste des éléments composants le µC ne nous intéressent pas dans l'immédiat.
Au niveau logique pure, les leds du launchpad sont connectées au port P1, sur les I/O 0 et 6, et du point de vue physique, la led rouge est connectée à la pin 2 qui correspond à P1.0 et la led verte est connectée à la pin 8 qui correspond à P1.6.
Voici donc en vert, les éléments du µC qu'on va utiliser de manière "volontaire".
Maintenant qu'on sait où sont connectées les leds aussi bien au niveau logique que physique, comment passer cette information au µC?
Et bien, il va falloir configurer les registres liés à P1. Sous le nom "barbare" de registre se cachent une série d'adresses de zones mémoire. Pour simplifier, ce sont ces registres qui font l'interface entre la couche logique et la couche physique du µC.
En premier lieu, il nous faut définir le sens des I/O, dans notre cas P1.0 et P1.6 sont des sorties. Le registre qui s'occupe de ça se trouve à l'adresse 0x22, pour simplifier, on l'a nommé "P1DIR" (Port 1 DIRection). Ce registre est un "mot" de 8 bits et chaque bit correspond à un I/0 de P1. Un bit à 1 indique que que l'I/O est une sortie et inversement, un bit à 0 indique une entrée.
Ils faut donc passer les bits 0 et 6 de P1DIR à 1, de cette façon, le µC sait que ses deux pins sont connectées à quelque chose qui attend de recevoir des impulsions.
Ardu, hein?
Mais c'est indispensable d'avoir une bonne idée sur comment les registres fonctionnent pour pouvoir programmer votre µC.
Toutes les actions qui nécessitent une interaction entre le programme et les composants internes - timer, etc. - ou externes via les ports de communication - GPIO, SPI, I²C, etc. - se font via les registres.
Par exemple, pour allumer ou étreindre les leds, il faudra jouer sur le registres "P1OUT".
Maintenant qu'on a une bonne idée de comment ça marche, il est temps de passer au code!
Les mains dans le cambouis… enfin, le code quoi #include <msp430g2231.h>
Ce fichier .h (header) va nous permettre - par exemple - d'utiliser le nom du registre plutôt que son adresse hexadécimale. Ça rend le code beaucoup plus clair, je vous recommande de TOUJOURS inclure le .h correspondant au µC que vous utilisez.
C'est dans ce fichier que sont définies, par exemple, les valeurs de BIT0 et BIT6 que nous allons utiliser par la suite.
Si on va regarder dans son code, on découvrira que BIT0 est défini à la valeur 0x01 ( 0000‿0001₂ ) et BIT6 à la valeur 0x40 ( 0100‿0000₂).
void main(void)
{
On définit une fonction "main".
Le "void" qui précède "main" indique que la fonction ne renverra rien comme résultat, alors que celui entre parenthèse nous indique que la fonction ne requiert aucune valeur en entrée.
WDTCTL = WDTPW + WDTHOLD;
Alors, ça, c'est le truc le plus "ésotérique" du code. Cette ligne de code désactive le "watchdog timer" -
WDT -… Et là, vous allez remarquer qu'une toute petite ligne de code peut mener à une longue explication
D'après ce que j'ai pu décrypter, c'est un système qui permet de détecter si le µC est actif ou si son programme l'a planté, si il est planté, le WDT vas redémarrer le µC.
Et, si j'ai bien compris, c'est à nous de gérer cet outil dans notre logiciel, ce qui est au-delà de mes compétences à l'heure actuelle. Donc, pour gagner du temps, j'ai choisi le désactiver purement et simplement.
WDTCTL (WDT ConTroLler) est donc un registre, mais ce registre est protégé. Pour écrire dedans, il faut utiliser le WDTPW (WDT PassWord). Dans notre cas, on souhaite stopper totalement le WDT, d'ou l'usage de la valeur WDTHOLD (HOLD - suspendre) en combinaison avec WDTPW.
P1OUT &= ~(BIT0 + BIT6);
Et là on a droit à une seconde ligne de code rikiki qui va générer une grosse explication!
Donc, dans cette ligne de code, on s'assure que les leds sont éteintes. Pour ce faire, c'est le registre de 8 bits nommé P1OUT (Port 1 sorties) qu'on doit modifier.
L'I/O P1.0 correspondant au bit 0 de P1OUT et P1.6 correspondant au bit 6 de P1OUT, doivent être à 0 pour que les leds soit éteintes dès le démarrage du µC.
P1OUT | BIT 7 | BIT 6 | BIT 5 | BIT 4 | BIT 3 | BIT 2 | BIT 1 | BIT 0 |
Port 1 | P1.7 | P1.6 | P1.5 | P1.4 | P1.3 | P1.2 | P1.1 | P1.0 |
Valeur binaire | X | 0 | X | X | X | X | X | 0 |
(Les valeurs binaires se lisent de droite à gauche, donc le bit 0 est à droite et le bit 7 à gauche. Les X désignent des emplacements où il on se fiche de la valeur binaire.)
Maintenant, pourquoi utilise "&=" et pas simplement "="?
La combinaison &= c'est comme si on faisait "P1DIR = P1DIR & (BIT0 + BIT6)".
L'opérateur & est ce qu'on appelle un opérateur bitwise, il va effectuer l'opération binaire AND bit à bit* sur les deux membres de l'opération.
(* c'est à dire qu'il va effectuer l'opération & entre le bit 0 du premier membre et du second membre, et ensuite la même chose pour tous les autres bits des membres.)
La table de vérité de la fonction AND est la suivante :
BitA | BitB | BitA&BitB |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
~ opérateur bitwise NOT : donc si Octet1 = 0100‿0001₂, alors ~(Octet1) = 1011‿1110₂.
Si P1OUT = 0100‿1001₂, alors 0100‿1001₂ & 1011‿1110₂ = 00001000₂ on a bien modifié que les bits qu'on voulait éteindre.
P1DIR |= (BIT0 + BIT6);
Wohooo et de trois!
Ne m'en voulez pas, je vais faire bref!
Ici, on veux configurer P1.0 et P1.6 en tant que sorties.
Et en va s'en assurer grâce à l'opérateur bitwise | correspondant à la fonction binaire OR:
BitA | BitB | BitA|BitB |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
Partons du principe que P1DIR vaut 01001000₂, si on applique un OR avec 0100‿0001₂ nous donnera comme résultat 0100‿1001₂.
Le |= nous permet dont de nous assurer que les bits qui doivent être passés à 1 le sont, sans toucher à l'état des autres bits.
for (;;)
{
Une petite boucle for sans arguments, ce qui veut dire qu'elle va tourner éternellement.
(Généralement, une boucle for se construit de cette façon : for(initialisation d'une variable compteur ; comparaison entre la variable compteur et une autre valeur; incrémentation ou décrémentation de la variable compteur){code à exécuter})
C'est bien utile quand on veut faire des logiciels "à cycles" rapidement et simplement.
P1OUT ^= (BIT0 + BIT6);
Gniiii encore un opérateur bitwiiiise
Mais je vous rassure, là, je crois bien qu'on les a tous fait
^ c'est l'opération binaire XOR (ou exclusif)
BitA | BitB | BitA^BitB |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Si P1OUT = 0100‿1001₂, alors 0100‿1001₂ ^ 0100‿0001₂ = 0000‿1000₂ on donc inversé l'état des bits désignés par (BIT0 + BIT6) \o/
__delay_cycles(250000);
}
}
Ahhh, ça, c'est une fonction qui permet de stopper pendant 250000 cycles l'exécution du code.
Ça évite d'avoir les leds qui clignotent trop vite.
Vous pouvez jouer avec cette valeur pour provoquer de jolies crises d'épilepsie… je rigole, ne le faites pas!
Voilà, le code est complet, si vous compilez et programmez votre MSP430 avec ce code, il devrait faire clignoter les deux leds de concert.
Challenge!Je vous propose de chercher comment modifier le code pour que les leds s'allument alternativement!
La modif très simple, si vous avez bien lu le tuto, vous devriez trouve très rapidement.
S'il vous plait, ne postez pas votre réponse.
Méthodes pour me contacterAu cas où vous rencontriez une embûche, si vous voulez discuter ou approfondir les explications ou les explorations à propos de ces tutos, voici quelques méthodes pour me contacter :
- par ce sujet
- par MP
- par mail
- par jabber
- par msn
J'utilise la même adresse mail pour msn et jabber: kodein AT reflexd.com (j'essaye d'éviter les moissonneurs automatiques d'adresse
).