Affichage_Atrylec_com

Vous n'êtes pas seuls dans l'Univers !

Transistor_100

STM32VLDISCOVERY : Ports d'entrées-sorties

Spécial ZanX' à « NonoxX » !

Utiliser les ports d'entrées-sorties du STM32L152RB

Je veux remonter ! | Liste

1) Présentation

Sur le STM32, la quasi-totalité des pattes sont accessibles en entrée-sortie tout-ou-rien. Les broches sont regroupées par paquets de 16, appelés ports.
Chaque port est géré par un périphérique appelé GPIO (« General Purpose Input/Output »).
Par exemple le périphérique GPIOA gère le PORTA, c'est à dire les pattes PA0 à PA15. Ce cours utilisera comme support la carte STM32L-DISCOVERY du fabricant STMicroelectronics.

Je veux remonter ! | Liste

2) L'allumage de LED

Comme toujours sur un microcontrôleur, il faut commencer par configurer l'horloge système.
L'horloge HSI a été choisie directement comme SYSCLK - voir le cours sur les horloges.

Capture_notice_1
Câblage des LED

Nous allons dans un premier temps voir comment allumer des LEDs avec
un STM32. Sur la carte STM32L-DISCOVERY, il y a deux LEDs (LD3
et LD4) que l'on peut utiliser à sa guise. Ces deux LEDs sont connectées
aux broches PB6 et PB7 du composant. On va donc utiliser le
périphérique GPIOB.

Le STM32 étant un composant conçu dans le but de consommer le moins d'énergie possible, tous ses périphériques sont désactivés par défaut. Pour les mettre en route, il faut activer leur horloge. Dans le cas du GPIOB, il faut mettre à 1 le bit 1 (GPIOBEN) du registre RCC_AHBENR. Puisque nous allons utiliser ces broches pour sortir une information du microcontrôleur (allumer une LED en l’occurrence), nous allons configurer PB6 et PB7 en sortie.

Capture_datasheet_10
MODERy[1:0]: Port x configuration bits (0= 0..15)

Le manuel de référence du composant nous indique qu'il existe un registre GPIOx_MODER (avec x le nom du port, ici B) permettant de configurer chaque patte en entrée, en sortie, ou d'autres fonctions. Pour configurer la patte y du port x en sortie, il faut configurer la paire de bits MODEy[1:0] du registre GPIOx_MODER sur la valeur 01.

Le STM32 propose deux modes de sortie :

Dans notre cas comme dans la plupart des applications, nous allons utiliser la sortie en Push-Pull, car il faut pouvoir forcer un 1 logique pour alimenter une LED. Cette configuration se fait par le registre GPIOB_OTYPER, en y plaçant les bits 6 et 7 à 0.
Un autre réglage est disponible pour les ports en sortie : la fréquence maximale de rafraîchissement du port. Elle peut prendre 4 valeurs : 400 kHz, 2 MHz, 20 MHz, et 40 MHz.
Dans notre cas, ça n'a pas vraiment d'importance, on va commander des LED à des fréquences visibles par l’oeil humain - typiquement inférieures à 10 Hz. On va donc choisir le réglage minimal de 400 kHz.
On a accès à ce paramètre avec le registre GPIOB->OSPEEDR.
Les broches PB6 et PB7 sont maintenant configurées correctement pour piloter nos LED. Il ne nous reste plus qu'à les allumer.
Pour allumer la LED LD4, branchée sur la broche PB6, il faut mettre à 1 le bit 6 du registre GPIOB->ODR, une valeur à 0 de ce même bit éteindra la LED. Pour la broche PB7, c'est le bit 7 qu'il faudra modifier.
Vous avez maintenant fini d'écrire le code nécessaire à l'initialisation des broches PB6 et PB7 en sortie push-pull, et fixé la valeur de PB6 à 1 et PB7 à 0. N'oubliez pas de terminer votre programme par une boucle infinie.
Compilez, chargez votre programme sur le composant et appuyez sur le bouton « Reset » de la carte. Si tout s'est bien passé, vous devriez voir s'allumer la LED bleue (LD4), et la LED verte (LD3) devrait rester éteinte.

Je veux remonter ! | Liste

3) Application : un gyrophare

Nous allons maintenant programmer un gyrophare pour les voiture de police d'un pays très étrange et lointain (vous avez reconnu l'Allemagne), dans lequel les couleurs de la police (Polizei) sont le vert et le bleu. On se permettra d'équiper une belle automobile sportive de l'ex-Allemagne de l'Est aux couleurs de la Polizei d'un feu clignotant alternativement bleu et vert. Pour ceux à qui cela évoque quelque-chose, nous n'allons pas utiliser d'interruptions dans ce cours, mais nous y viendrons un peu plus tard. Nous allons nous contenter d'une attente active entre les alternances de couleurs. C'est à dire que entre deux couleurs différentes, nous allons attendre un certain temps en consommant du temps processeur dans une boucle qui ne fait rien d'autre que de passer le temps. Essayez de réaliser ce gyrophare par vous même avec les LED de votre carte STM32L-DISCOVERY, avant de regarder la réponse ci-dessous.

POLIZEI
POLIZEI

Vous avez réussi ? Bravo ! Sinon voyons ensemble ce qu'il fallait faire. Tout d'abord il fallait (comme toujours) configurer l'horloge système. Ensuite, il fallait configurer les ports PB6 et PB7 correspondant au LEDs en sortie, comme nous l'avons fait au paragraphe précédent. Ensuite il fallait lancer notre programme dans une boucle infinie. En C, cela se traduit par exemple par un « while(1) ».

Dans cette boucle nous allons faire dans l'ordre :

1) Eteindre LD3 et allumer LD4,
2) Attendre,
3) Eteindre LD4 et allumer LD3,
4) Attendre.

Pour les opérations d'allumage et d'extinction des LED, vous devriez savoir le faire. Je vous invite à relire le paragraphe précédent si cela vous a posé problème. Pour l'attente par contre, il est possible que ce soit la première fois que vous y ayez à faire. Pour se faire, créez simplement une boucle qui ne fait rien :

Cette boucle suit le comportement suivant :

1) Mettre i à 0,
2) Si i < 1000000
2)1) Augmenter i de 1,
2)2) Aller à 2),
3) Sinon sortir de la boucle.

Et chacune de ces opérations sera traduite par le compilateur en instructions dans le microcontrôleur, et toutes les instructions prennent du temps pour être exécutées (au moins un front d'horloge). En comptant jusqu'à 1000000, nous allons consommer suffisamment de temps pour que le clignotement des LEDs soit visible. Par cette méthode on peut difficilement obtenir des temporisations précise mais elle a l'avantage d'être très simple. Le code complet du gyrophare (hors initialisations) est donc :

Code source : Exemple 5B1 - Un gyrophare



while(1)
{
    GPIOB->ODR &= ~(1 << 7); /* Extinction de LD3 */
    GPIOB->ODR |= 1 << 6; /* Allumage de LD4 */
      
    for(i = 0; i < 1000000; i++); /* Attente */
         
    GPIOB->ODR &= ~(1 << 6); /* Extinction de LD4 */
    GPIOB->ODR |= 1 << 7; /* Allumage de LD3 */      
         
    for(i = 0; i < 1000000; i++); /* Attente */      
}

Je veux remonter ! | Liste

4) Utiliser une broche en entrée

Il peut dans de nombreux cas être utile d'utiliser une broche en entrée, comme par exemple dans le cas d'un bouton. Afin de s’entraîner à mettre en place cette fonction de base, nous allons créer à partir d'un bouton à action momentanée comme celui présent sur la carte STM32L-DISCOVERY, un interrupteur à action maintenue (« latched »).
Avant de nous lancer tête baissée dans la programmation voici une description de ce que nous allons programmer :

1) Initialisations (horloge et ports),
2) Attente bouton appuyé,
3) Allumer la LED,
4) Attente bouton relâché,
5) Attente bouton appuyé,
6) Eteindre la LED,
7) Attendre bouton relâché,
8) Aller à l'étape 2).

Dans un premier temps, configurez correctement l'horloge système, activez l'horloge du GPIOB, configurez PB7 en sortie et éteignez la LED.

Capture_notice_2
Câblage du bouton-poussoir bleu

D'après le manuel de l'utilisateur de la carte STM32LDISCOVERY,
on voit que le bouton utilisateur est connecté à la
broche PA0, et que lorsqu'il est pressé, il renvoie un état logique 1,
un état 0 sinon.
Nous allons donc utiliser des broches du PORTD, donc le
périphérique GPIOC. La première chose à faire est donc... de
l'activer. Comme nous avions procédé pour activer GPIOB
précédemment, nous mettons à 1 le bit 2 (GPIOCEN) du registre
RCC_AHBENR.

Ensuite, nous allons configurer la broche PC0 en entrée. Il suffit de mettre à 00 les bits MODER0[1:0] du registre GPIOC_MODER. Ça y est, notre broche PA0 est configurée en entrée. C'est un peu plus simple que de la configurer en sortie. Pour connaître l'état d'une entrée, on fait appel au registre GPIOC_IDR (« Input Data Register »). Son fonctionnement est simple. Chaque bit de ce registre est l'état des entrées du port. Si le bit 0 est à 1, cela signifie que l'entrée PA0 est à l'état haut. S'il est à 0, l'entrée est à l'état bas. Vous devriez maintenant être capable de programmer cet interrupteur... Voici une solution qui fonctionne (mais qui n'est pas la seule !).

Code source : Exemple 5B2 - Lecture de l'état logique d'une broche


#include <stm32l1xx.h>

void SystemInit(void) /*  Fonction qui permet d'effectuer l'initialisation du microcontrôleur STM32L152RB.
                                                         Cette fonction est appelée par le fichier écrit en langage assembleur, qui a été inclus au début de la création du projet.
                                                         L'appel de la fonction « main('Francais', ''); » est ensuite effectué par le même fichier.  */
{
   RCC->CR |= 1; /*  Allumage du HSI  */
   while((RCC->CR & (1 << 1)) == 0); /*  Attente que le HSI soit stable  */

      
   RCC->CFGR &= ~(1 << 1); /*  Mise à 0 de SW[1] par masquage  */
   RCC->CFGR |= 1 << 0; /*  Mise à 1 de SW[0] par masquage  */

}

int main(void) /*  Fonction principale  */
{
   RCC->AHBENR |= 1 << 1; /*  Activation de l'horloge du GPIOB  */

      
   GPIOB->MODER &= ~(0xF << 12); /*  configuration de PB6 et PB7...  */
   GPIOB->MODER |= ((1 << 12) + (1 << 14)); /*  ...en sortie  */

      
   GPIOB->OTYPER &= ~(0x3 << 6); /*  Configuration de PB6 et PB7 en sortie push-pull  */
      
   GPIOB->OSPEEDR &= ~(0xF << 12); /*  Taux de rafraîchissement : 40kHz  */

      
   RCC->AHBENR |= (1 << 0); /*  Activation de l'horloge du GPIOA  */
      
   GPIOA->MODER &= (~0x3); /*  Configuration de PA0 en entrée  */

      
   while(1)
   {
      while((GPIOA->IDR & (1 << 0)) == 0); /*  Attente de l'appui du bouton   */

               
      GPIOB->ODR |= 1 << 7; /*  Allumage de LD3  */
      GPIOB->ODR |= (1 << 6);
                  
      while((GPIOA->IDR & (1 << 0)) != 0); /*  Attente du relâchement du bouton   */

               
      GPIOB->ODR &= ~(1 << 6);
                  
      while((GPIOA->IDR & (1 << 0)) == 0); /*  Attente de l'appui du bouton   */

               
      GPIOB->ODR |= (1 << 6);
      GPIOB->ODR |= ~(1 << 7); /*  Extinction de LD3  */   
                  
      while((GPIOA->IDR & (1 << 0)) != 0); /*  Attente du relâchement du bouton   */

               
      GPIOB->ODR &= ~(1 << 6);   
   }
}

Je veux remonter ! | Liste

5) Conclusion

Vous êtes maintenant capable d'utiliser les entrées-sorties tout-ou-rien du STM32L15x de façon basique dans vos projets. Dans le cours sur les interruptions, vous verrez une autre manière d'utiliser les entrées, un peu plus complexe, mais qui permet de ne pas occuper le processeur à 100 % rien que pour attendre l'appui d'un bouton.

Commentaires (4)

Atrylec

Le mercredi 24 octobre 2012 à 19:55

Gaby, l'utilisation du bus « I2C » du STM32F100RB est évoqué ici :
LIEN_EXTERNE http://www.atrylec.com/fr/electronique/stm32discovery/l_i2c_stm32F100RB.php

tunimaestro, les interruptions du STM32F100RB sont expliquées ici :
LIEN_EXTERNE http://www.atrylec.com/fr/electronique/stm32discovery/les_interruptions_STM32F100RB.php

Kako,
pour déterminer si un mot de passe saisi par quelqu'un est identique à un mot de passe de référence, tu peux comparer, caractère par caractère, les deux mots en question, je te propose cette petite fonction écrite en langage C :


unsigned char ComparerMots(unsigned char *  MotDePasseATester)
{
   unsigned char k = 0;
   unsigned char MotDePasse = "Confidentiel\0";
   while((k < 255) && (MotDePasseATester[k] != '\0'))   /* Tant que l'on a pas comparé plus de 255 caractères
               et tant que l'on est pas arrivé à la fin
               du mot de passe original */
   {
      if(MotDePasse[k] != MotDePasseATester[k])
      {
         return 0;   /* Les deux mots de passe à comparer ne sont pas identiques */
      }
      k++;
   }
   return 1;   /* Les deux mots de passe à comparer sont identiques,
         ou le mot de passe à tester est plus long
         que le mot de passe original */
}



Attention, dans certains cas, il peut être plus sûr de parcourir toute la chaîne de caractères du mot de passe qui a été soumis pour comparaison, afin de ne pas donner d'indication sur la position du premier caractère qui diffère du bon mot de passe !


Bonne continuation !


Kako

Le jeudi 18 octobre 2012 à 16:49

Ton tuto est genial merci mais je dois gerer une entree d une chaine de caractere pour faire un reconnaisseur de mot de passe comment gerer une telle entree?

tunimaestro

Le mardi 28 août 2012 à 11:35

Oui justement. Pourriez vous nous indiquer où trouver votre cours sur les interruptions ? Merci

Gaby

Le jeudi 8 mars 2012 à 12:07

Ou peut on trouver ton cours sur les interruptions? Proposes tu également un tutoriel sur la communication I2C avec ce module? Merci ^^

Ajouter un commentaire

Votre pseudo :

Votre commentaire :

Je veux remonter !