Vous êtes sur la page 1sur 9

TP3 : Initiation a la communication

sérié UART
1 Objectif
1. Manipuler les API destinées à la communication série UART,
2. Gérer les interruptions générées par un port UART,
3. Créer une application en loop-back entre Tx et Rx.

2 Principe
Un UART, pour (Universal Asynchronous Receiver Transmitter), est un émetteur-récepteur asynchrone
universel. C'est le composant utilisé pour faire la liaison entre le processeur et le port série. Pour
envoyer des données en parallèle il faut autant de fils que de bits de données. Il nécessaire donc de
transformer ces données pour les faire passer à travers une liaison série qui utilise un seul fil.
Aujourd'hui, les UART sont généralement intégrés dans les microcontrôleurs comme périphériques.

Une trame UART est constituée des bits suivants :

 un bit de « start » toujours à ‘0’ : servant à la synchronisation du récepteur, Le niveau


logique de repos est le ‘1’,
 les données : la taille peut varier (généralement entre 5 et 9 bits)
 éventuellement un bit de parité paire ou impaire
 et un bit de stop toujours à ‘1’ (la durée peut varier entre 1, 1,5 et 2 temps bit).

Afin de faciliter l'interopérabilité entre périphériques (PC, microcontrôleur, modem, …) des vitesses de
transmission sont normalisées par multiples et sous-multiples de 9600 baud, l'unité baud
correspondant à un bit par seconde :

 110 baud,
 300 baud,
 1 200 baud,
 400 baud,
 800 baud,
 9 600 baud,
 19 200 baud,
 38 400 baud,
 57 600 baud,
 115 200 baud.

Dans la suite du TP on va configurer l’interface USART2 du processeur CortexM4 en une interface UART
en mode émission/réception avec un débit de 9600 Bit/s, un bit de parité « Even », un « Stop » bit et
sans control hardware.

Ensuite, on va utiliser une connexion entre la pin Rx et la pin Tx pour créer une loop-back et comparer
les données envoyées et les données reçues.

3 Création d’un projet


1. Créer un projet TP03,
2. Sélectionner sous le menu « Project » -> « Manage » -> « Run-Time Environment »,
sélectionner « LED API », « Buttons API », « Start up » et il est important de préciser la board
« STM32F4-Discovery ». Cliquer sur « Resolve » et cocher « Classic » sous « STM32Cube
Framework (API) » puis sur « OK ».
3. Ajouter les dossiers « sources » et « headers », ajouter les fichiers « main.c » ,
« main.h », «stm32f4xx_it.c » et «stm32f4xx_it.h.

4. Cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug » afin de
configurer les options de la carte cible sur laquelle le programme sera exécuté. Cette fenêtre
fait apparaître deux options de test : par simulation (à gauche), ou par émulation (à droite), en
utilisant la carte STM32F407VG. Sélectionner l’option émulation (à droite), cocher le bouton
« use » et sélectionner « ST-Link Debugger ».

Cliquer sur le bouton « Settings » et vérifier, sous l’onglet « Debug », que le port utilisé et de type
« SW », sinon le changer.
Cliquer sur l’onglet « Flash Download » de la même fenêtre, et vérifier que la taille de la mémoire Flash
de la cible est de 1 M on Chip.

Cliquer sur l’onglet C/C++ et ajouter le macro « HSE_VALUE=8000000 » qui indique la fréquence du
Crystal installé sur la carte à la fonction « SystemClock_Config(); » qui se trouve par défaut dans le
« Template » du « main.c »

Cliquer sur « OK » pour valider les options de configuration du Debugger choisies.


Re-cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug ». Cliquer sur « Settings »
puis « Trace » changer la fréquence « Core Clock » à 168MHz et cocher la case « Trace Enable » puis
sur « OK ».

A ce stade le code doit être compilable sans fautes.

4 Travail demandé
Partie 1 : UART Driver

1. Sélectionner sous le menu « Project » -> « Manage » -> « Run-Time Environment ». Cocher
sous « UART » et « USART » sous Device->HAL_STM32Cuble_HAL, puis appuyer sur
« Resolve ».

2. Dans le fichier « main.c » déclarer une variable globale comme suit :

UART_HandleTypeDef UartHandle;

3. Puis déclarer une variable locale comme suit :


GPIO_InitTypeDef GPIO_InitStruct;
4. Dans le fichier « main.c » ajouter les lignes de code suivante pour initialiser les pins de l’USART.
Lire attentivement le code et trouver le rôle de chaque instruction. Noter bien que les pin PA2
et PA3 sont les pins Tx et Rx, respectivement.

//////////////////////////////////////////////////////////////////////////////
////////////////////// UART Low Level Init ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

/* Enable peripherals and GPIO Clocks */


/* Enable GPIO TX/RX clock at the Port A*/
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Enable USART2 clock */
__HAL_RCC_USART2_CLK_ENABLE();

/*Configure peripheral GPIO */


/* UART TX GPIO pin configuration */
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* UART RX GPIO pin configuration */


GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

5. Une fois les pins de l’USART2 sont configurées ajouter les lignes de code nécessaires pour
configurer la priorité de l’interruption « system tick » à la priorité la plus haute et celle de
l’USART2 à « 1 » pour « PreemptPriority » et « 0 » pour « SubPriority ». Ensuite, activer
l’interruption relative à l’USART2.
6. Ensuite, ajouter les lignes de codes suivantes pour configurer le port USART2. Lire
attentivement le code et trouver le rôle de chaque instruction.

//////////////////////////////////////////////////////////////////////////////
////////////////////// UART High Level Init ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

/* Configure the UART peripheral */


/* Put the USART peripheral in the Asynchronous mode (UART Mode) */
/* UART configured as follow:
- Word Length = 8 Bits
- Stop Bit = One Stop bit
- Parity = None
- BaudRate = 9600 baud
- Hardware flow control disabled (RTS and CTS signals) */
UartHandle.Instance = USART2;

UartHandle.Init.BaudRate = 9600;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_EVEN;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;

if(HAL_UART_Init(&UartHandle) != HAL_OK) //// UART initialization ////


{
Error_Handler();
}

7. Ajouter la fonction qui servira à gérer l’interruption de l’USART2 dans le fichier


« stm32f4xxit.c » comme suit:
/**
* @brief This function handles UART interrupt request.
* @param None
* @retval None
* @Note None
*/
extern UART_HandleTypeDef UartHandle;
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&UartHandle);
}
8. Dans le fichier « main.c » ajouter la fonction callback qui indique que le transfert sur le Tx s’est
bien déroulé comme suit :

/**
* @brief Tx Transfer completed callback
* @param UartHandle: UART handle.
* @note This example shows a simple way to report end of IT Tx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{ /* Transfer in transmission process is correct */
}
9. Dans le fichier « main.c » ajouter la fonction callback qui indique que la réception sur le Rx
s’est bien déroulée comme suit :

/**
* @brief Rx Transfer completed callback
* @param UartHandle: UART handle
* @note This example shows a simple way to report end of IT Rx transfer, and
* you can add your own implementation.
* @retval None
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
/* Transfer in reception process is correct */
}

10. Dans le fichier « main.c » ajouter la fonction callback qui indique qu’une erreur est survenue
au niveau de l’UART comme suit :

/**
* @brief UART error callbacks
* @param UartHandle: UART handle
* @note This example shows a simple way to report transfer error, and you can
* add your own implementation.
* @retval None
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
{
/* Transfer error in reception/transmission process */
}

11. Compiler le projet à ce niveau le code doit être compilable sans fautes.

A ce niveau le driver du UART est configuré pour générer une interruption quand le transfert Rx
ou Tx se termine ou quand une erreur de transfert survient. Dans la partie suivante on va modifier
la fonction « main » pour faire une loop-back entre Tx et Rx et comparer les données transférées.

Partie 2 : Loop-back

1. Connecter les pins PA2 et PA3 avec un « Jumper » ou un fil.


2. Dans le fichier « main.c » déclarer les macros suivants :
/* Private macro -------------------------------------------------------------*/
#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
#define TXBUFFERSIZE (COUNTOF(aTxBuffer) - 1)
#define RXBUFFERSIZE TXBUFFERSIZE
3. Dans le fichier « main.c » ajouter les variables globales suivantes :

/* Buffer used for transmission */


uint8_t aTxBuffer[] = " **** Hello World !!!!! **** ";
uint8_t aRxBuffer[RXBUFFERSIZE];
__IO ITStatus UartReady = RESET;

4. Dans le fichier « main.c » ajouter une fonction avec la signature suivante :

static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength);

Cette fonction retourne « 0 » si les deux tableaux d’entrées sont identiques sinon elle retourne une
valeur supérieure à « 0 ».

5. Dans le fichier « main.c » ajouter une fonction avec la signature suivante :

int32_t Buttons_Initialize_Int (void) ;

Cette fonction initialise le bouton utilisateur « bouton bleu » en mode interruption.

6. Dans la fonction « main » juste après l’appel de la fonction « SystemClock_Config(); » ajouter


les lignes de code nécessaires pour : initialiser les Leds, initialiser le bouton utilisateur en mode
interruption, changer la priorité du bouton en la plus basse possible et activer l’interruption
du bouton utilisateur.
7. Dans le fichier « main.c » ajouter la fonction callback relative à l’interruption du bouton
utilisateur.
8. Ajouter la fonction qui servira à gérer l’interruption du bouton utilisateur dans le fichier
« stm32f4xxit.c »
9. Dans la fonction « main » juste avant la boucle infinie « while(1) » initialiser la variable
« UartReady » comme suit :

/* Reset listening flag */


UartReady = RESET;

10. Chercher dans le fichier « main.c » la fonction « static void Error_Handler(void) » et modifier
son code de manière à faire clignoter la Led3 avec une période de 250ms en cas d’erreur.
11. Modifer le code de la fonction « void HAL_UART_TxCpltCallback(UART_HandleTypeDef
*UartHandle) » de manière à allumer la Led1 quand le transfert sur le Tx est réussi.
12. Modifer le code de la fonction « void HAL_UART_RxCpltCallback(UART_HandleTypeDef
*UartHandle)» de manière à allumer la Led2 quand la réception sur le Rx est réussie et mettre
la variable « UartReady » à « SET ».
13. Modifer le code de la fonction « void HAL_UART_ErrorCallback(UART_HandleTypeDef
*UartHandle)» de manière à faire clignoter toutes les Leds à une période de 250ms quand il y
a une erreur sur le port UART.
14. Modifer le code de la fonction « void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)» de
manière à tester si la pin qui a généré l’interruption externe correspond à celle du bouton
utilisateur et si la variable « UartReady » est à « RESET » pour envoyer le « aBufferTx » à
travers le port UART.
NB : utiliser la fonction non bloquante offerte par le driver HAL « HAL_StatusTypeDef
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) ».
15. Modifier le contenu de la boucle infinie de la fonction « main » de manière à exécuter le
traitement répétitif suivant :
a. Tester si la variable « UartReady » est à « RESET ». Dans ce cas mettre le processeur à
l’écoute de la pin Rx du port UART.
NB : utiliser la fonction non bloquante offerte par le driver HAL « HAL_StatusTypeDef
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) »
b. Tester si la variable « UartReady » est à « SET ». Dans ce cas comparer le buffer émis
et reçu.
i. S’ils sont différents appeler la fonction « static void Error_Handler(void) »
ii. S’ils sont identiques faire clignoter la Led0 deux fois avec une période de
250ms. Mettre la variable « UartReady » à « RESET » et eteindre les Leds 1,2.
16. Compiler et tester le projet.
17. Dans la fonction « void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) » éliminer le test sur la
variable « UartReady » avant d’envoyer le « aTxBuffer ». Compiler et le votre projet puis
conclure.