Différences entre versions de « Guide STM32CubeIDE »

De Polybot Grenoble
Sauter à la navigation Sauter à la recherche
Ligne 123 : Ligne 123 :
 
# Le rapport cyclique est égal au rapport CCRx/CounterPeriod. CounterPeriod nous avons fixé, mais nous pouvons changer le registre CCR1. CCR1=10000 règle le rapport à 0.5 ou 50% dans ce cas.
 
# Le rapport cyclique est égal au rapport CCRx/CounterPeriod. CounterPeriod nous avons fixé, mais nous pouvons changer le registre CCR1. CCR1=10000 règle le rapport à 0.5 ou 50% dans ce cas.
 
# Vous pouvez utiliser la ligne suivante pour piloter un servo de 270°. CCR1 = 200*(2.5+deg/27)
 
# Vous pouvez utiliser la ligne suivante pour piloter un servo de 270°. CCR1 = 200*(2.5+deg/27)
 
==Porter une bibliothèque==
 
 
Cette partie donne des conseils concernant l'utilisation de bibliothèques initialement conçues pour Arduino, Mbed etc.
 
 
Beaucoup de bibliothèque sont disponibles. Afin de pouvoir les utiliser dans vos projets, il est nécessaire de les porter. En effet, chaque outil a sa propre HAL (Hardware Abstraction Layer) et il est donc nécessaire de modifier cette partie du code pour que la bibliothèque soit fonctionnelle. En général, les bibliothèques que vous aurez besoin d’utiliser seront des bibliothèques interfaçant des composants, capteurs, actionneurs et donc les parties du code que vous aurez à modifier concernent les liaisons série, UART, I2C etc.
 
 
Par exemple les code Mbed suivants:
 
 
<syntaxhighlight lang="cpp">
 
void VL53L0X::writeReg(uint8_t reg, uint8_t value)
 
{
 
    char data_write[2];
 
    data_write[0]=reg;
 
    data_write[1]=value;
 
 
    handler_i2c.write(address,data_write,2);
 
}
 
</syntaxhighlight>
 
 
<syntaxhighlight lang="cpp">
 
void wait_custom(int nb_ms)
 
{
 
    wait_ms(nb_ms);
 
}
 
</syntaxhighlight>
 
 
Seront traduit ainsi avec l'HAL fourni par STMicroelectronics:
 
 
<syntaxhighlight lang="cpp">
 
void VL53L0X::writeReg(uint8_t reg, uint8_t value)
 
{
 
    uint8_t data_write[2];
 
    data_write[0]=reg;
 
    data_write[1]=value;
 
 
    HAL_I2C_Master_Transmit(&handler_i2c, address, data_write, 2, 10);
 
}
 
</syntaxhighlight>
 
 
<syntaxhighlight lang="cpp">
 
void wait_custom(int nb_ms)
 
{
 
    HAL_Delay(nb_ms);
 
}
 
</syntaxhighlight>
 
 
Afin de réaliser un portage avec succès, il est nécessaire de lire les documentations des HAL sources et destinations, afin de comprendre leurs différences et points communs. Dans notre exemple, il a été nécessaire de changer le type de données envoyé sur la liaison I2C, la fonction du HAL Mbed acceptait des données de type ''char'' tandis que le HAL fourni par ST accepte des données de type ''uint8_t''.
 
 
 
=<span id="astuces"></span>Astuces & conseils=
 
 
==Balises STM32CubeMX==
 
Lors de la génération (ou regénération) du fichier ''main.c'', STM32CubeMX ajoute des balises de la forme <syntaxhighlight lang="C" inline>/* USER CODE BEGIN X */</syntaxhighlight> et <syntaxhighlight lang="C" inline>/* USER CODE END X */</syntaxhighlight>. Lorsque vous ajoutez du code dans ce fichier, veillez à le faire entre ces balises, sinon votre code sera supprimé si vous regénérez ultérieurement votre projet avec STM32CubeMX.
 
 
Si vous devez ajouter du code à un endroit ou aucune balise n'est disponible, c'est sûrement que vous ne vous y prenez pas de la bonne manière...
 
 
==Projet C et C++==
 
===Explication===
 
Lors de la création d'un projet, nous avons la possibilité de sélectionner le langage cible en tant que C++. Malheureusement, STM32CubeMX ne supporte actuellement pas ce langage. Les fichiers générés par ce dernier seront en C et en particulier le fichier ''main.c''.
 
 
Lorsque l'on veut utiliser, ou produire du code C++, il est nécessaire que le fichier main soit en C++.
 
La solution est alors de renommer le fichier ''main.c'' en ''main.cpp''. Si le langage cible du projet a bien été réglé sur C++, alors le projet compilera avec succès.
 
 
Le problème se produit quand on veut regénerer le projet avec STM32CubeMX. Il va recréer un nouveau fichier ''main.c'' à coté de notre fichier ''main.cpp''. Le nouveau code généré sera donc dans le fichier ''main.c'' et non ''main.cpp''.
 
 
===Résolution du problème===
 
* Fusionner les deux fichiers de manière manuelle dans ''main.cpp'': garder la génération de STM32CubeMX présente dans le fichier ''main.c'' et garder le code présent entre toutes les balises du fichier ''main.cpp''.
 
* Exclure le fichier ''main.c'' du build: clic droit sur ''main.c'' > Ressource Configurations > Exclude from build. Ceci indiquera au compilateur de ne pas compiler ce fichier. Il compilera néanmoins ''main.cpp'' et ne trouvera pas de conflit.
 
 
===Notes===
 
Il est possible que ce problème ne soit plus suite à des futures mises à jour de STM32CubeMX. Lors de la rédaction de ce guide, les projets C++ ne sont pas supportés pleinement.
 
 
==Hello World (Commencer ici!)==
 
A faire
 
 
==UART: utilisation du printf==
 
 
Afin de rediriger le ''printf'' sur une liaison série (et afficher des messages dans une console par exemple) il est nécessaire de réaliser quelques modifications:
 
 
1. Aller dans le fichier ''Core/Src/main.c/cpp''.
 
 
2. Ajouter entre les balises <syntaxhighlight lang="cpp" inline>/* USER CODE BEGIN 0 */</syntaxhighlight> et <syntaxhighlight lang="cpp" inline>/* USER CODE END 0 */</syntaxhighlight> la fonction suivante:
 
 
<syntaxhighlight lang="cpp">
 
int __io_putchar(int ch)
 
{
 
uint8_t c = ch & 0x00FF;
 
HAL_UART_Transmit(&huart2, &c, 1, 10);
 
return ch;
 
}
 
</syntaxhighlight>
 
 
3. Ajouter entre les balises <syntaxhighlight lang="cpp" inline>/* USER CODE BEGIN Includes */</syntaxhighlight> et <syntaxhighlight lang="cpp" inline>/* USER CODE END Includes */</syntaxhighlight> l'include suivant:
 
<syntaxhighlight lang="cpp">
 
#include <stdio.h>
 
</syntaxhighlight>
 
 
Lors de l'utilisation du ''printf'', ayez le réflexe d'ajouter systématiquement <syntaxhighlight lang="cpp" inline>\n</syntaxhighlight> à la fin de chaque trame afin de vider le buffer et bien réaliser la communication.
 
 
Dans ce guide, j'utilise le handler sur UART nommé ''huart2'', pour une carte Nucleo F446RE, c'est la liaison utilisée par le ST-Link. Si vous voulez utiliser une autre liaison, pensez à le remplacer.
 
Pour ajouter une nouvelle liaison série, vous pouvez suivre [[#ajout_uart|ce guide]]).
 
 
==<span id="ajout_uart"></span>Ajout d'une liaison UART==
 
 
À faire.
 
 
==Interruptions==
 
 
===Interruption sur GPIO===
 
 
À faire.
 
 
===Interruption sur UART===
 
 
À faire.
 
 
==PWM et servos==
 
[[Fichier:PWM1.png]]
 
  
 
==Porter une bibliothèque==
 
==Porter une bibliothèque==

Version du 8 février 2021 à 21:38

Suite STM32Cube

Présentation

À faire.

Utilisation de STM32CubeIDE

Installation

Créer un nouveau projet

  • Accéder à File>New>STM32 Project.
  • Choisissez votre cible (généralement dans l'onglet Board Selector) puis Next.
  • Saisissez un nom de projet et le langage cible. Afin d'avoir une compatibilité maximale, choisissez C++ ainsi vous pourrez utiliser des bibliothèques C++ même si le reste de vos sources sont en C. Laissez Binary Type et Project Type par défaut.
  • Répondez Oui à la question Voulez-vous initialiser tous les périphériques avec leurs paramètres par défaut?.
  • Vous êtes maintenant sur la perspective STM32CubeMX. Ici, il va être possible d'ajouter des fonctionnalités supplémentaire (en suivant ces astuces).
  • Lorsque vous avez terminé, sauvegarder le fichier .ioc, cela générera les sources nécessaires.
  • Vous êtes prêt à programmer.

Importer un projet existant

Pour importer un projet existant (après avoir cloner un dépot Git par exemple), il est facile de l'importer sous STM32CubeIDE.

Pour cela, accédez à File>Open project from File System.

Rechercher le projet sur votre ordinateur et cliquez sur Terminer

Astuces & conseils

Balises STM32CubeMX

Lors de la génération (ou regénération) du fichier main.c, STM32CubeMX ajoute des balises de la forme <syntaxhighlight lang="C" inline>/* USER CODE BEGIN X */</syntaxhighlight> et <syntaxhighlight lang="C" inline>/* USER CODE END X */</syntaxhighlight>. Lorsque vous ajoutez du code dans ce fichier, veillez à le faire entre ces balises, sinon votre code sera supprimé si vous regénérez ultérieurement votre projet avec STM32CubeMX.

Si vous devez ajouter du code à un endroit ou aucune balise n'est disponible, c'est sûrement que vous ne vous y prenez pas de la bonne manière...

Projet C et C++

Explication

Lors de la création d'un projet, nous avons la possibilité de sélectionner le langage cible en tant que C++. Malheureusement, STM32CubeMX ne supporte actuellement pas ce langage. Les fichiers générés par ce dernier seront en C et en particulier le fichier main.c.

Lorsque l'on veut utiliser, ou produire du code C++, il est nécessaire que le fichier main soit en C++. La solution est alors de renommer le fichier main.c en main.cpp. Si le langage cible du projet a bien été réglé sur C++, alors le projet compilera avec succès.

Le problème se produit quand on veut regénerer le projet avec STM32CubeMX. Il va recréer un nouveau fichier main.c à coté de notre fichier main.cpp. Le nouveau code généré sera donc dans le fichier main.c et non main.cpp.

Résolution du problème

  • Fusionner les deux fichiers de manière manuelle dans main.cpp: garder la génération de STM32CubeMX présente dans le fichier main.c et garder le code présent entre toutes les balises du fichier main.cpp.
  • Exclure le fichier main.c du build: clic droit sur main.c > Ressource Configurations > Exclude from build. Ceci indiquera au compilateur de ne pas compiler ce fichier. Il compilera néanmoins main.cpp et ne trouvera pas de conflit.

Notes

Il est possible que ce problème ne soit plus suite à des futures mises à jour de STM32CubeMX. Lors de la rédaction de ce guide, les projets C++ ne sont pas supportés pleinement.

Hello World (Commencer ici!)

A faire

UART: utilisation du printf

Afin de rediriger le printf sur une liaison série (et afficher des messages dans une console par exemple) il est nécessaire de réaliser quelques modifications:

1. Aller dans le fichier Core/Src/main.c/cpp.

2. Ajouter entre les balises <syntaxhighlight lang="cpp" inline>/* USER CODE BEGIN 0 */</syntaxhighlight> et <syntaxhighlight lang="cpp" inline>/* USER CODE END 0 */</syntaxhighlight> la fonction suivante:

<syntaxhighlight lang="cpp"> int __io_putchar(int ch) { uint8_t c = ch & 0x00FF; HAL_UART_Transmit(&huart2, &c, 1, 10); return ch; } </syntaxhighlight>

3. Ajouter entre les balises <syntaxhighlight lang="cpp" inline>/* USER CODE BEGIN Includes */</syntaxhighlight> et <syntaxhighlight lang="cpp" inline>/* USER CODE END Includes */</syntaxhighlight> l'include suivant: <syntaxhighlight lang="cpp">

  1. include <stdio.h>

</syntaxhighlight>

Lors de l'utilisation du printf, ayez le réflexe d'ajouter systématiquement <syntaxhighlight lang="cpp" inline>\n</syntaxhighlight> à la fin de chaque trame afin de vider le buffer et bien réaliser la communication.

Dans ce guide, j'utilise le handler sur UART nommé huart2, pour une carte Nucleo F446RE, c'est la liaison utilisée par le ST-Link. Si vous voulez utiliser une autre liaison, pensez à le remplacer. Pour ajouter une nouvelle liaison série, vous pouvez suivre ce guide).

Ajout d'une liaison UART

À faire.

Interruptions

Interruption sur GPIO

À faire.

Interruption sur UART

À faire.

PWM et servos

Prérequis

  • Carte STM32 NUCLEO-F446RE
  • STM32 CubeIDE
  • Servomoteur (facultatif)

Création de projet

Créer un nouveau projet comme décrit dans la section 2.2. (Cible STM32 NUCLEO-F446RE pour ce tuto)

Configuration via CubeMX

Avant de sauvegarder le fichier .ioc (fichier de config STM32CubeMX) et générer le code du projet, nous devons faire quelques configurations supplémentaires.

  1. Nous choisissons le pin PA5 pour générer le PWM (pin connecté à la LED intégrée LD2). Le signal est généré par un timer et donc nous devons “connecter” le pin à ce périphérique. Pour ce faire, veuillez cliquer sur la pâte PA5 (dans la vue ‘’Pinout view’’). D'après le menu qui apparaît, ce pin peut être connecté au canal 1 du timer 2 (TIM2_CH1) et au canal 1 du timer 8 (TIM8_CH1N). Nous choisissons TIM2_CH1 (cliquer pour activer).
    PWM1.png
  2. Ensuite, accéder à la catégorie ‘’Timers’’ (menu à gauche) et sélectionner le TIM2. Activer le canal 1 en mode ‘’PWM Generation’’ et choisir ‘’Internal Clock’’ comme ‘’Clock Source’’.
    PWM2.png
  3. Maintenant, nous devons configurer les horloges du microcontrôleur. Accéder à l'onglet ‘’Clock Configuration’’. Puis enter 180 MHz comme fréquence de processeur (maximale pour ce microcontrôleur) et appuyer sur entrée. CubeMX règle automatiquement la fréquence des périphériques.
    PWM3.png
  4. D'après la documentation du microcontrôleur (p.16) nous voyons que le timer 2 est connecté au bus APB1.
    PWM4.png
    et d'après la vue précédente, les timers de APB1 tournent à 90 MHz (x2 de APB1 peripheral clocks).
    PWM5.png
  5. Revenant sur la configuration du TIM2, nous devons configurer le registres ‘’Prescaler’’ et ‘’Counter Period’’ pour régler la fréquence du signal généré d'après la formule suivante : f_PWM = f_APBx_timer/((PSC+1)*(CounterPeriod+1)). Pour arriver à une fréquence de 50 Hz, nécessaire pour piloter un servomoteur analogique, nous pouvons entrer les valeurs suivantes:
    PWM6.png

Programmation

Accéder au fichier main.c (Core/Src/main.c). Ajouter les lignes suivantes pour démarrer la génération du PWM et contrôler son rapport cyclique (entre les balises /* USER CODE 2 */ ). <syntaxhighlight lang="cpp"> HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); htim2.Instance->CCR1 = 1000; // 10000/20000 = 0.5 (duty cycle) </syntaxhighlight>

  1. Vous pouvez également utiliser la fonction <syntaxhighlight lang="cpp">HAL_TIM_PWM_Stop</syntaxhighlight> pour arrêter le signal.
  2. Le rapport cyclique est égal au rapport CCRx/CounterPeriod. CounterPeriod nous avons fixé, mais nous pouvons changer le registre CCR1. CCR1=10000 règle le rapport à 0.5 ou 50% dans ce cas.
  3. Vous pouvez utiliser la ligne suivante pour piloter un servo de 270°. CCR1 = 200*(2.5+deg/27)

Porter une bibliothèque

Cette partie donne des conseils concernant l'utilisation de bibliothèques initialement conçues pour Arduino, Mbed etc.

Beaucoup de bibliothèque sont disponibles. Afin de pouvoir les utiliser dans vos projets, il est nécessaire de les porter. En effet, chaque outil a sa propre HAL (Hardware Abstraction Layer) et il est donc nécessaire de modifier cette partie du code pour que la bibliothèque soit fonctionnelle. En général, les bibliothèques que vous aurez besoin d’utiliser seront des bibliothèques interfaçant des composants, capteurs, actionneurs et donc les parties du code que vous aurez à modifier concernent les liaisons série, UART, I2C etc.

Par exemple les code Mbed suivants:

<syntaxhighlight lang="cpp"> void VL53L0X::writeReg(uint8_t reg, uint8_t value) {

   char data_write[2];
   data_write[0]=reg;
   data_write[1]=value;
   handler_i2c.write(address,data_write,2);

} </syntaxhighlight>

<syntaxhighlight lang="cpp"> void wait_custom(int nb_ms) {

   wait_ms(nb_ms);

} </syntaxhighlight>

Seront traduit ainsi avec l'HAL fourni par STMicroelectronics:

<syntaxhighlight lang="cpp"> void VL53L0X::writeReg(uint8_t reg, uint8_t value) {

   uint8_t data_write[2];
   data_write[0]=reg;
   data_write[1]=value;
   HAL_I2C_Master_Transmit(&handler_i2c, address, data_write, 2, 10);

} </syntaxhighlight>

<syntaxhighlight lang="cpp"> void wait_custom(int nb_ms) {

   HAL_Delay(nb_ms);

} </syntaxhighlight>

Afin de réaliser un portage avec succès, il est nécessaire de lire les documentations des HAL sources et destinations, afin de comprendre leurs différences et points communs. Dans notre exemple, il a été nécessaire de changer le type de données envoyé sur la liaison I2C, la fonction du HAL Mbed acceptait des données de type char tandis que le HAL fourni par ST accepte des données de type uint8_t.