TP03
TP03
TP03
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.
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.
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 »
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 ».
UART_HandleTypeDef UartHandle;
//////////////////////////////////////////////////////////////////////////////
////////////////////// UART Low Level Init ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
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 ///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
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;
/**
* @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
Cette fonction retourne « 0 » si les deux tableaux d’entrées sont identiques sinon elle retourne une
valeur supérieure à « 0 ».
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.