Le code du « main.c ».
Ouvrez l' exemple GPIO_IOToggle avec SW4STM32. Si par défaut le
« main.c » n' est ouvert, ouvrez-le.
/* Includes
----------------------------------------------------------------
1
--*/
2
#include "main.h"
Le main.h regroupe d' autres inclusions, afin d' éviter de surcharger le
main.c. Il contient aussi une macro de vérification d' inclusion.
static GPIO_InitTypeDef
1GPIO_InitStruct;
En gros, on renomme la structure GPIO_InitTypeDef en GPIO_InitStruct,
« static » afin que la structure ne soit modifiable que dans ce fichier
( main.c ).
static void
1SystemClock_Config(void) ;
Prototype de la fonction de configuration de l' horloge système.
Observons maintenant ce que contient la fonction
int
1main(void)
int main(void)
1
{
/* This sample code shows how to use GPIO HAL API to toggle
2
LED3 IO
in an infinite loop. */
3
4 /* STM32F3xx HAL library initialization:
5
6
- Configure the Flash prefetch
7
- Configure the Systick to generate an interrupt each 1
msec
8
- Set NVIC Group Priority to 4
- Low Level Initialization
9
*/
1
0 HAL_Init();
1
1
1
2
La ligne
HAL_Init()
1;
sert à initialiser la librairie HAL.
Le prefetch est une optimisation interne des µC ARM, elle sert ici à
participer à la gestion des interruptions par leurs gestions
mémoires.
Le Systick Timer est normalement dédié aux systèmes
d'exploitation en temps réel (RTOS) , mais peut également être
utilisé en tant que décompteur.
NVIC (Nested vectored interrupt controller) ou contrôleur
d'interruption vectorisées imbriquées, on se contentera de savoir
que le niveau de priorité de l' interruption est de 4.
/* -1- Enable GPIO Clock (to be able to program the
1configuration registers) */
2 LED3_GPIO_CLK_ENABLE();
Cela semble être un délai d' attente après l' initialisation de RCC (Reset
and Clock Control) .
/* -2- Configure IO in output push-pull mode to drive external
1LEDs */
2 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
3 GPIO_InitStruct.Pull = GPIO_PULLUP;
4 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
5 GPIO_InitStruct.Pin = LED3_PIN;
6
7 HAL_GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStruct);
Ce block est très intéressant, on configure chaque éléments de la
structure GPIO_InitTypeDef, puis on l'envoie en paramètre dans la
fonction HAL_GPIO_Init();. GPIO_initTypeDef s' appel
maintenant GPIO_InitStruct. Pour rappel :
static GPIO_InitTypeDef
1GPIO_InitStruct;
HAL_GPIO_Init(); est l' équivalent de la fonction pinMode() ; sous
Arduino. Comme les configuration de GPIO on plus de possibilités,
comme ici d' avoir mis une « pull up » en sortie. Vous aurez remarqué
que ça ne se fait pas sur les Arduino, on utilise les « pull up » seulement
sur les entrées. De plus sur les µC ARM, on peut, mais on peut aussi
mettre des « pull down ».
/* -3- Toggle IO in an infinite loop */
1
while (1)
2
{
3
HAL_GPIO_TogglePin(LED3_GPIO_PORT,
4LED3_PIN);
5 /* Insert delay 100 ms */
6 HAL_Delay(100);
7 }
8}
La structure de contrôle while (1){} est l' équivalent de la fonction void
loop(){} pour Arduino, c' est ici qu' on cuisine.
Commande de base pour les GPIOs avec HAL.
HAL_Delay()
1
;
quand à elle appartient à la librairie « hal » , dans le même répertoire . C'
est l' équivalent de la fonction delay() ; d' Arduino. Donc des
millisecondes.
HAL_GPIO_TogglePin
1() ;
est une fonction de la librairie « hal_gpio.h » que l'on trouve dans le
répertoire /votre_carte/Drivers/Votre_Carte_HAL_Driver. Cette fonction
inverse l' état de la sortie à chaque fois qu' elle est appelée.
HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t
1GPIO_Pin);
Lecture des entrées. GPIOx est le PORT, une lettre et GPIO_Pin le
numéro de la broche concerné. La fonction renvoie la valeur « bitstatus »
pouvant être GPIO_PIN_SETou GPIO_PIN_RESET.
HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,
1GPIO_PinState PinState);
Voici les deux valeurs de PinState : GPIO_PIN_SET et GPIO_PIN_RESET.
Configuration des GPIOs.
Dans un premier temps, il faut se familiariser avec les possibilités de
sorties :
Configurations des entrées/ sorties.
Voyons d' un peu plus près les possibilités de configuration des pins avec
HAL. Déjà retrouvons notre structure GPIO_InitTypeDef.
Pin.
typedef struct
1{
2 uint32_t Pin; /*!< Specifies the GPIO pins to be
configured.
3
This parameter can be any value of
4
@ref GPIO_pins */
C' est le numéro (en partant de zero) de la pin (broche) à configurer.
Dans notre exemple, c' est la définition LED3_PIN qui est utilisé. Pour
savoir à quoi elle correspond, faite un clique gauche sur la définition puis
appuyez sur la touche F3 de votre clavier. Eclipse va ouvrir le fichier où
se trouve la définition de LED3_PIN
Mode.
1 uint32_t Mode; /*!< Specifies the operating mode for the
selected pins.
2
This parameter can be a value of @ref
GPIO_mode */
On défini ici le mode d' entrée ou sortie de la broche.
Les Entrées.
GPIO_MODE_INPUT Broche en entrée en mode flottant.
GPIO_MODE_IT_RISING interruption sur front montant.
GPIO_MODE_IT_FALLING interruption sur front descendant.
GPIO_MODE_IT_RISING_FALLING Interruption sur les deux fronts.
GPIO_MODE_EVT_RISING
GPIO_MODE_EVT_FALLING
GPIO_MODE_EVT_RISING_FALLING
Les Sorties.
GPIO_MODE_OUTPUT_PP Broche en sortie en mode Push/Pull.
GPIO_MODE_OUTPUT_OD Broche en sortie en drain ouvert.
GPIO_MODE_AF_PP Fonction alternative en mode Push/Pull.
GPIO_MODE_AF_OD Fonction alternative en mode drain ouvert.
Non défini.
GPIO_MODE_ANALOG
Note. Nous nous occupons ici que de l' essentiel, les fonctions
alternatives ne rentre pas dans le cadre de ce tutoriel. Il en va de même
pour les événements et les interruptions.
Pull.
uint32_t Pull; /*!< Specifies the Pull-up or Pull-Down
activation for the selected pins.
1
This parameter can be a value of @ref
2
GPIO_pull */
c' est ici que l' on configure les Pull Up et les Pull Down. Trois
possibilités :
GPIO_NOPULL Pas de résistance.
GPIO_PULLUP Résistance de tirage vers le haut.
GPIO_PULLUP Résistance de tirage vers le bas.
Les résistances de tirages ont une valeur de 40 kOhms.
Speed.
Le paramètre « speed » n'a d'effet que lorsque la sortie est configuré en
sortie. Il n'a rien à voir avec la fréquence de changement d'état de la
broche, il s'agit du temps de monté et descente du signal. Au lieu d'avoir
un signal carré, il sera « plutôt » trapézoïdale. La description que l'on
peut faire c'est que plus le speed est élevé, plus le signal se rapprochera
d'une forme carrée.
1 uint32_t Speed; /*!< Specifies the speed for the selected
pins.
2
This parameter can be a value of @ref
3
GPIO_speed */
4
ST n'a pas jugé bon d'uniformiser les définitions des valeurs possibles
pour tous ses µCs.
STM32 F0/1/3/L0/1
GPIO_SPEED_LOW
GPIO_SPEED_MEDIUM
GPIO_SPEED_FAST
GPIO_SPEED_HIGH
STM32 F4/L4
GPIO_SPEED_FREQ_LOW
GPIO_SPEED_FREQ_MEDIUM
GPIO_SPEED_FREQ_HIGH
GPIO_SPEED_FREQ_VERY_HIGH
Voyez la différence.
Alternate.
Ce sont les périphériques comme I²C, SPI, USART…
1
uint32_t Alternate; /*!< Peripheral to be connected to the
2selected pins
3 This parameter can be a value of
4@ref GPIOEx_Alternate_function_selection */
}GPIO_InitTypeDef;
Exemple n°1 : clignotement de la LED
intégrée au STM32F103C8T6
Dans ce premier exemple, nous allons contrôler la LED
embarquée STM32 qui est connectée à la broche PC13. Avant
de commencer la programmation, nous devrons d'abord
connecter la carte STM32 à l'ordinateur portable ou au PC.
Pour cela, nous allons utiliser le ST-LINK V2.
Connectez simplement les broches 3,3 V et GND du ST-LINK
V2 aux broches 3,3 V et GND de la carte STM32. Connectez les
broches SWCLK et SWDIO du ST-Link aux broches SWCLK et
SWDIO du STM32.
Enfin, connectez le ST-Link V2 à votre ordinateur portable/PC.
Tout au long de ces exemples, le ST-Link V2 restera connecté à
la carte STM32.
Chaque fois que vous téléchargez un programme sur la carte
STM32, vous devrez connecter le ST-Link V2 à l'ordinateur
portable/PC.
Ouvrez le logiciel STM32CubeIDE. Si vous l'exécutez pour la
première fois, vous recevrez peut-être une notification ou un
message « Sélectionnez un répertoire comme espace de
travail » dans lequel vous souhaitez stocker tous vos projets.
Vous pouvez également utiliser l'adresse par défaut.
Enfin, cliquez sur le bouton Lancer. STM32CubeIDE affichera
l'écran de bienvenue, indiquant que l'IDE a été lancé avec
succès.
Pour démarrer un nouveau projet, allez dans le menu Fichier,
puis Nouveau et cliquez sur Projet STM32. STM32CubeIDE
peut prendre un moment pour charger et télécharger les
bibliothèques nécessaires. Soyez patient pendant ce processus
car cela peut prendre un certain temps en fonction de la
vitesse de votre connexion Internet.
Dans la fenêtre de sélection de cible et pendant que l' onglet
de sélection MCU est actif ; sélectionnez le numéro de pièce
commercial STM32F103C8T6 , sélectionnez-le dans la liste
des MCU , puis cliquez sur le bouton Suivant .
Écrivez le nom du projet, sélectionnez la langue ciblée, le type
binaire cible et le type de projet ciblé. Enfin, cliquez sur le
bouton Terminer.
Dans l'onglet Brochage et configuration, cliquez sur le noyau
du système et sélectionnez SYS, puis cliquez sur Déboguer et
sélectionnez Câble série.
Cliquez sur PC13 et sélectionnez GPIO_Output car la LED
intégrée est connectée à cette broche. Enfin, cliquez sur le
bouton Enregistrer si l'on vous demande Voulez-vous générer
du code ? Cliquez sur Oui, puis appuyez à nouveau sur le
bouton Oui.
STM32CubeIDE va générer le code nécessaire en fonction de
votre configuration de broches et ouvrir la perspective
associée. Cette perspective vous fournit les outils et les vues
appropriés pour le développement et la personnalisation
ultérieurs de votre projet. Pendant que vous êtes sur le fichier
main.c, faites défiler vers le bas. Maintenant, dans la fonction
while(1), nous allons écrire le code pour faire clignoter la LED.
Code de clignotement de la LED
STM32CubeIDE :
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 1);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, 0);
HAL_Delay(100);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.[Link] = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */