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 STM32F100RB

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 STM32VLDISCOVERY 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_3
Câblage des LED

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

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 GPIOC, il faut mettre à 1 le bit 4 (IOPCEN) du registre RCC_APB2ENR. Puisque nous allons utiliser ces broches pour sortir une information du microcontrôleur (allumer une LED en l’occurrence), nous allons configurer PC8 et PC9 en sortie.

Capture_datasheet_11
GPIOx_CRH: Port configuration register high

Le manuel de référence du composant nous indique qu'il existe un registre GPIOx_CRL, et un registre GPIOx_CRH (avec x le nom du port, ici C) 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_CRL sur la valeur 01 ou 10.

Chaque port comprend 16 broches, qui sont numérotées de 0 à 15.
Pour chaque port, le registre GPIOx_CRL - « ConfiguRation Low » - permet de configurer les broches allant de 0 à 7, et le registre GPIOx_CRH - « ConfiguRation High » - permet de configurer les broches allant de 8 à 15.

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 GPIOx_CRH, dans le groupement de bits CNFy[1:0], soit CNF8[1:0], et CNF9[1:0], dans le cas présenté ici.
Un autre réglage est disponible pour les ports en sortie : la fréquence maximale de rafraîchissement du port.
Elle peut prendre 3 valeurs : 2 MHz, 10 MHz, et 50 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 2 MHz.
On a accès à ce paramètre avec le registre GPIOx_CRH, dans le groupement de bits MODEy[1:0], soit MODE8[1:0], et MODE9[1:0], dans le cas présenté ici. Les broches PC8 et PC9 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 PC8, il faut mettre à 1 le bit 8 du registre GPIOC->ODR, une valeur à 0 de ce même bit éteindra la LED. Pour la broche PC9, c'est le bit 9 qu'il faudra modifier. Vous avez maintenant fini d'écrire le code nécessaire à l'initialisation des broches PC8 et PC9 en sortie push-pull, et fixé la valeur de PC8 à 1 et PC9 à 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.

Code source : Exemple 5A1 - Allumage de la LED bleue de la carte



#include <stm32f10x_lib.h>

void ConfigPortC()
{
    RCC->APB2ENR |= (1 << 4);
    GPIOC->CRH = ((GPIOC->CRH & 0x00000000) | (0x00000022));
}

int main(void)
{
    ConfigPortC('Francais', '');
    GPIOC->ODR |= (1 << 8); /* Allumage de la LED bleue, située sur la broche PC8 */
    while(1)
    {
        
    }
}

void SystemInit (void) /* Fonction qui permet d'effectuer l'initialisation du microcontrôleur STM32F100RB.
				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. */
{
   
}


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 STM32VLDISCOVERY, 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 PC8 et PC9 correspondant aux LED 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 ce 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 5A2 - Un gyrophare



while(1)
{
    GPIOC->ODR &= ~(1 << 9); /* Extinction de LD3 */
    GPIOC->ODR |= (1 << 8); /* Allumage de LD4 */
    for(i = 0; i < 1000000; i++); /* Attente */
    GPIOC->ODR &= ~(1 << 8); /* Extinction de LD4 */
    GPIOC->ODR |= (1 << 9); /* 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 STM32VLDISCOVERY, 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_4
Câblage du bouton-poussoir bleu

D'après le manuel de l'utilisateur de la carte STM32VLDISCOVERY,
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 PORTA, donc le
périphérique GPIOA. La première chose à faire est donc... de
l'activer. Comme nous avions procédé pour activer GPIOC
précédemment, nous mettons à 1 le bit 2 (GPIOAEN) du registre
RCC_AHBENR.

Ensuite, nous allons configurer la broche PA0 en entrée. Il suffit de mettre à 00 les bits MODE0[1:0] du registre GPIOA_CRL. Ç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 GPIOA_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 5A3 - Lecture de l'état logique d'une broche



#include <stm32f10x_lib.h>

int main(void) /* Fonction principale */
{
    RCC->APB2ENR |= (1 << 4); /* Activation de l'horloge du GPIOC */
    GPIOC->CRH = ((GPIOC->CRH & 0x00000000) | (0x00000022)); /* Configuration de PC8 et PC9 en sorties de type « push-pull »,
                            avec une fréquence de rafraîchissement de 2 MHz. */
    RCC->APB2ENR |= (1 << 2); /* Activation de l'horloge du GPIOA */
    GPIOA->CRL = ((GPIOA->CRL & 0x00000000) | (0x00000004)); /* Configuration de PA0 en entrée de type « flottante » */
    while(1)
    {
        while((GPIOA->IDR & (1 << 0)) == 0); /* Attente de l'appui du bouton  */
        GPIOC->ODR |= (1 << 9); /* Allumage de LD3 */
        GPIOC->ODR |= (1 << 8); /* Allumage de LD4 */
        while((GPIOA->IDR & (1 << 0)) != 0); /* Attente du relâchement du bouton  */
        while((GPIOA->IDR & (1 << 0)) == 0); /* Attente de l'appui du bouton  */
GPIOC->ODR &= ~(1 << 9); /* Extinction de LD3 */ GPIOC->ODR &= ~(1 << 8); /* Extinction de LD4 */ while((GPIOA->IDR & (1 << 0)) != 0); /* Attente du relâchement du bouton */ } } void SystemInit(void) /* Fonction qui permet d'effectuer l'initialisation du microcontrôleur STM32F100RB. 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 */ }

Je veux remonter ! | Liste

5) Conclusion

Vous êtes maintenant capable d'utiliser les entrées-sorties tout-ou-rien du STM32F10x 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 (0)

Ajouter un commentaire

Votre pseudo :

Votre commentaire :

Je veux remonter !