STM32 : Les entrées-sorties

04 mars 2020 rdorigny 0 commentaires

Après avoir vu quelques articles de présentation du STM32 et de son environnement de développement, il est temps de rentrer dans le vif du sujet.

Nous allons commencer petit bras, avec un programme de commande d'entrées/sorties. Il faut bien débuter par quelque chose. L'objectif de notre programme sera simplement de faire clignoter une led, et nous verrons qu'il y a déjà beaucoup de choses à prendre en compte.



Le schéma ci-dessous décrit le principe GPIO. On notera le montage push-pull en sortie.


Préparation du programme

Donc ici, l'idée est de faire clignoter une led et de la commander par un des deux boutons poussoirs de la carte. Pour cela, on va prendre BP1 de la carte Nucleo (qui est rattaché à un GPIO, on verra cela plus tard).

Donc, la première étape consiste à ouvrir le STM32CubeMx en sélectionnant la carte Nucléo F-401RE. A noter, la très grande variété dans le choix des cartes de développement, c'est vraiment impressionnant.


Sur la représentation graphique du STM32, on remarque que la pin PA5 est marqué LD2 [Green led], ce qui semble vouloir indiquer que cette pin est connectée à la led LED2 de la carte par construction. C'est parfait pour notre expérience.

L'onglet Clock configuration est configuré avec les paramètres par défaut de la carte Nucléo. Dans l'onglet Project, il faut préciser le nom et l'emplacement du projet, ainsi que la toolchain en MDK-ARM.


Ensuite, il suffit de cliquer sur le bouton Generate code en haut à droite de l'interface. Un menu apparaît, il faut choisir l'option Open project. Keil UVision s'ouvre sur notre programme généré.


La génération du code par le STM32CubeMX produit un fichier main.c qui est le programme principal, on y trouve des fonctions génériques comme :
  • HAL_Init() initialisation tout le matériel de la carte Nucleo (mémoire, contrôleur d’interruption, base de temps du système et autres fonctions de bas niveau).
  • SystemClock_Config() configure les horloges du STM32.
  • MX_GPIO_Init() initialise les GPIO.
  • MX_USART2_UART_Init() initialise la communication par liaison série.
  • Ensuite, nous avons la boucle infinie du programme. Voilà, ce n'est pas plus compliqué que cela!


    Le code utilisateur doit être impérativement intégré entre les différentes balises BEGIN et END. Tout ce qui sera ajouté au mauvais endroit (c'est à dire en dehors de ces balises) sera écrasé lors de la compilation.


    La fonction MX_GPIO_Init() initialise les GPIO du STM32, ici nous avons besoin de la LED2 et du bouton B1 pour stopper le clignotement de la LED.
    static void MX_GPIO_Init(void)
    {
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    
      /* GPIO Ports Clock Enable */
      __HAL_RCC_GPIOC_CLK_ENABLE();
      __HAL_RCC_GPIOH_CLK_ENABLE();
      __HAL_RCC_GPIOA_CLK_ENABLE();
      __HAL_RCC_GPIOB_CLK_ENABLE();
    
      /*Configure GPIO pin Output Level */
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
    
      /*Configure GPIO pin : B1_Pin */
      GPIO_InitStruct.Pin = B1_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
    
      /*Configure GPIO pin : LD2_Pin */
      GPIO_InitStruct.Pin = LD2_Pin;
      GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
      HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
    
    }
    
    La première étape consiste à activer les horloges sur les ports du STM32.

    Ensuite, on configure la LED sur PA5 à la valeur 0 par HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET) :
  • LD2_GPIO_Port : correspond au port A (faire bouton Go to definition...)
  • LD2_Pin : correspond au port GPIO_PIN_5
  • GPIO_PIN_RESET : correspond à 0

  • Enfin, on configure les GPIO en initialisant les données dans la structure. A noter que les champs :
  • Pin : Spécifie les broches GPIO à configurer;
  • Mode : Spécifie le mode de fonctionnement des broches sélectionnées. Par exemple GPIO_MODE_IT_FALLING correspond au mode d'interruption externe avec détection de déclenchement, sur front descendant, GPIO_MODE_OUTPUT_PP correpond au mode push pull de sortie (montage électronique cascode amplificateur de tension qui relie à la sortie deux composants actifs travaillant en opposition de phase, relié l'un au plus de l'alimentation, l'autre au moins);
  • Pull : spécifie l'activation Pull-up/Pull-Down/No_Pull pour les broches sélectionnées. Il s'agit de placer une résistance de pull pour être compatible avec l'équipement connecté;
  • Speed : spécifie la vitesse des broches sélectionnées. GPIO_SPEED_FREQ_LOW correspond à une vitesse de 2 MHz

  • Enfin, la fonction HAL_GPIO_Init() configure la broche avec les données initialisées dans la structure.

    Le programme

    La documentation du HAL pour les microcontroleurs STM32F4XX est ici. Vous trouverez toutes les fonctions du HAL utiles pour notre programme, et bien plus même! . Globalement, on peut presque considérer que STM produit un framework pour chacun de ses microcontrôleurs. C'est quand même impressionnant cette documentation, avec presque 2000 pages, c'est là que l'on voit que le STM32 est un petit bijou de technologie.

    int main(void)
    {
      /* USER CODE BEGIN 1 */
    
      /* USER CODE END 1 */
      
    
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
    
      /* USER CODE BEGIN Init */
    
      /* USER CODE END Init */
    
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
    
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_USART2_UART_Init();
      /* USER CODE BEGIN 2 */
    
      /* USER CODE END 2 */
     
     
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
    		if (HAL_GPIO_ReadPin(B1_GPIO_Port,B1_Pin)==0)
    			HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);
    		else
    		{
    			HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
    			HAL_Delay(500);
    			HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
    			HAL_Delay(500);
    		}			
      }
      /* USER CODE END 3 */
    }
    

    Notre code est placé entre les balises USER CODE 3. En résumé, on teste la valeur du bouton, s'il est à 0, on éteint la led, sinon on fait changer l'état de la led avec la fonction HAL_GPIO_TogglePin qui spécifie les broches à basculer. HAL_Delay(500) réalise une temporisation de 500ms (0.5s). Et si on appuie sur le BP1, cela arrête le clignotement de LED2.

    Attention, une fois que l'on a chargé le programme, il est nécessaire d’appuyer sur le bouton de reset pour charger et exécuter le code.

    Conclusion

    Voilà, nous avons réalisé notre premier programme. J'ai pris soin de bien décrire toute la démarche avec l'environnement de développement. A vous de jouer. Je conseille vivement l'acquisition de la carte Nucléo qui est vraiment peu coûteuse pour se faire la main.








    Pseudonyme (obligatoire) :
    Adresse mail (obligatoire) :
    Site web :




    © 2020 www.doritique.fr par Robert DORIGNY