Vous êtes sur la page 1sur 68

Polycopié de TP

MODULE : C EMBARQUE
Initiation au PIC16F84

Usage de GPIO pins de STM32F446 / Cortex M4


STM32CUBE_IDE /KEIL U VISION IDE/MICROSHIP

Réalisé par : Encadré par :


MOUAD EL ATMANI Pr. LATIF RACHID

NABIL BOULARTAL

Année Universitaire 2022/2023


TP 1, INITIATION A LA PROGRAMMATION DU PIC 16F877A
PREMIERE APPROCHE DES LOGICIELS UTILISES

Objectif : L’objectif capital de ce premier TP est de se familiariser avec les outils


employés pour réaliser les TPs de ce module. En bref, nous nous intéressons à la
programmation du microcontrôleur PIC de Microship (PIC16F84A) et aux
environnements de conception et de simulation (MikroC et Proteus ISIS).

Les PIC sont des microcontrôleurs RISC (de l'anglais, Reduced Instructions Set
Computer) ; qui signifie : calculateur à jeu réduit d'instructions. Ils sont dédiés aux
applications qui ne nécessitent pas une grande quantité de calculs complexes, mais
qui demandent beaucoup de manipulations d’entrées / sorties. En effet, il existe
plusieurs familles de microcontrôleurs, dont les plus connues sont : Atmel, Motorola,
Microship, Intel,…etc. La famille des PIC à bus de données 8 bits est subdivisée, à
l’heure actuelle, en 3 grandes catégories :
Base-ligne : utilisent des mots d’instruction de 12 bits.
Mid-Range : utilisent des mots d’instruction de 14 bits.
High-End : utilisent des mots d’instruction de 16 bits.

I- Brève découverte du PIC 16F84A

1) La référence :
Les PIC 16FXX sont des microcontrôleurs 8 bits (largeur du bus de données)
conçus en technologie CMOS (faible consommation électrique). Les µC PIC utilisent
une architecture RISC (Processeur à jeu d’instructions réduit) avec 35 instructions
codées en un mot de 14 bits. Pour identifier un pic, on utilise le numéro inscrit sur
son boitier, exemple du PIC 16F84-04 :

16 indique un PIC de la famille Mid-Range (Instructions sur 14


16
bits)

Type de mémoire programme : C ➔ EPROM, CR ➔ ROM, F


F
➔ FLASH.

Référence du PIC
84

La fréquence d’horloge maximale (4 Mhz)


4
2) Le Brochage :
Le 16F84A est un PIC de 18 broches, la figure ci-contre montre le brochage du
circuit. Les fonctions des pattes sont les suivantes :

➢ L’alimentation du circuit est assurée par les pattes


VDD (3 à 6v) et VSS (0v).
➢ L’horloge doit être stabilisée de manière externe au
moyen d’un cristal de quartz connecté aux pattes OSC1/CLKIN et
OSC2/CLKOUT.
➢ La patte 4 est appelée MCLR. Elle permet lorsque
la tension appliquée est égale à 0V de réinitialiser le
microcontrôleur.
➢ Les broches RB0 à RB7 (portB) et RA0 à RA4 (portA)
permettent au microcontrôleur de dialoguer avec le
monde extérieur (périphériques). Elles peuvent être configurées en
entrée ou en sortie. Certaines de ces broches ont aussi d’autres
fonctions tels que interruption,compteur (RB0/INT ; RA4/TOCKL)

a) Exemple d’alimentation :

b) Exemple d’horloge :
Pour fonctionner correctement, le microcontrôleur nécessite la présence d'une
horloge qui doit être câblée entre les bornes « OSC1 et OSC2 ». Cette horloge peut
être réalisée de différentes façons :
3) Structure interne :

La structure générale du PIC 16F84


comporte 4
blocs comme le montre la figure 2 :
➢ Mémoire de programme
➢ Mémoire de données
➢ Processeur
➢ Ressources auxiliaires
(périphériques)

La mémoire de programme contient les instructions pilotant l’application à


laquelle le microcontrôleur est dédié. Il s’agit d’une mémoire non volatile (elle garde
son contenu, même en l’absence de tension), elle est de type FLASH c’est à dire
qu’elle peut être programmée et effacée par l’utilisateur via un programmateur et
un PC. Pour le PIC 16F84 cette mémoire est d’une taille de 1024x14 bits, c’est à
dire qu’elle dispose de 1024 emplacements (de 000h à 3FFh) contenant chacun 14
cases car dans le cas du PIC, les instructions sont codées sur 14 bits. On peut donc
stocker 1024 instructions.
La mémoire de donnée est séparée en deux parties :
➢ une mémoire RAM de 68 octets puisque le bus de donnée est de huit bits.
Cette RAM est volatile
(les données sont perdues à chaque coupure de courant). On peut y lire et écrire des
données.
➢ une mémoire EEPROM de 64 octets dans laquelle on peut lire et écrire des
données (de huit bits soit un octet) et qui possède l’avantage d’être non volatile (les
données sont conservées même en l’absence de tension). La lecture et l’écriture dans
cette mémoire de données sont beaucoup plus lentes que dans la mémoire de données
RAM.
Le processeur est formé de deux parties :
➢ une unité arithmétique et logique (UAL) chargée de faire des calculs.
➢ un registre de travail noté W sur lequel travail l’UAL.
Les ressources auxiliaires qui sont dans le cas du PIC16F84
➢ ports d’entrées et de sorties.
➢ temporisateur (timers)
➢ interruptions
➢ chien de garde

Le PIC 16F84A, dispose de 2 ports :


⚫ Port A
⚫ Port B

A chaque port correspondent 2 registres :


Un registre direction pour programmer les lignes en entrée ou en sortie : TRISA,
TRISB.
Un registre de données pour lire ou modifier l’état des broches : PORTA, PORTB.
Pour déterminer les modes des ports (I/O), il faut sélectionner leurs registres TRISX :
Le positionnement d’un bit à "1" programme la broche correspondante en entrée.
Le positionnement d’un bit à "0" programme la broche correspondante en sortie.

II- MikroC PRO et Programmation du PIC 16F877A


La principale différence entre le microcontrôleur et le microprocesseur est que le
microcontrôleur possède en interne le programme qu'il devra effectuer en fonction de
l'application pour lequel il a été conçu.
Le langage machine est le langage compris par les processeurs. Ce langage est
difficile à maitriser puisque chaque instruction est codée par une séquence propre de
bits. Afin de faciliter la tâche au programmeur, on a créé différents langages plus ou
moins évolués (langage de haut niveau).
Pour programmer un microcontrôleur, il est possible d'utiliser différents types de
langages de programmations de haut niveau ; tels que : C, C++, JAVA,…etc. Le
programme réalisé est ensuite compilé dans le langage assembleur conçu par le
constructeur du microcontrôleur. Le programme ainsi compilé sera injecté, par la
suite, du PC dans la mémoire programmable du microcontrôleur.
En effet, les lignes des programmes que nous écrivons avec les différents types de
langages constituent ce qu’on appel un programme source (xxxx.m, xxx.c,…etc). Le
microcontrôleur ne comprend pas ces programmes. Pour que le microcontrôleur
puisse comprendre nos programmes, il faut les compiler (Build) en langage machine,
qui est une suite de codes machine (fichiers avec l’extension xxx.hex).
Le langage MikroC PRO (pour PIC) a trouvé une large application pour le
développement de systèmes embarqués sur la base de microcontrôleur. Il assure une
combinaison de l'environnement de programmation avancée IDE (Integrated
Development Environment), et d’un vaste ensemble de bibliothèques pour le matériel,
de la documentation complète et d’un grand nombre des exemples.
Le MikroC PRO est un compilateur C pour PIC bénéficier d’une prise en main très
facile. Il a une capacité à pouvoir gérer la plupart des périphériques rencontrés dans
l'industrie (Bus I2C, 1Wire, SPI, RS485, Bus CAN, cartes compact Flash, signaux
PWM, afficheurs LCD et 7 segments...etc.), de ce fait il est un des outils de
développement incontournable et puissant.
• Pour installer MikroC, télécharger depuis les serveurs et faire l’installation.
• L’environnement de démarrage du logiciel MikroC PRO est le suivant :

• Pour débuter un projet, il faut suivre les étapes suivantes :


✓ Créer un nouveau dossier; dans le disque dure de votre PC.
✓ Créer un nouveau projet (Project / New Projet Wizard / Next).
✓ Sélectionner le type du PIC (P16F84A / Next).
✓ Préciser le Clock (8.000000 MHz / Next).
✓ Spécifier le chemin d’enregistrement (Ouvrir / chemin du dossier créé) puis
donner un nom
type mikroC Project (*.mcppi) et Enregistrer.
✓ Une fois cette première étape terminée, saisissez votre programme, compilez,
corriger les erreurs
et exécuter.
III- Proteus ISIS et vérification de l’application par simulation
C’est un très bon logiciel de simulation en électronique. C’est un éditeur de schémas
qui intègre un simulateur analogique, logique ou mixte. Proteus ISIS est capable de
vérifier et simuler le comportement du PIC 16F84A.
En effet, la simulation permet d’ajuster et de modifier les paramètres du circuit étudié
comme si on manipulait un montage électronique réel. Ceci permettra d’accélérer le
prototypage et de réduire le coût de réalisation.

IV- Exemples pratiques de programmation du PIC 16F84A


Application 1: (Lancer Proteus ISIS et l’éditeur MikroC PRO)
• Réaliser le premier circuit de test qui permet de faire clignoter une LED (ON durant
1 sec et OFF durant 1 sec) ?
.

Decimal Binarry Octal Hexadecimal


Remarque : Il est possible d’accéder
0 0b00000000 00 0x00 individuellement à 1 seul bit du PORT.
A titre d’exemple,A titre d’exemple on écrit:
1 0b00000001 01 0x01 TRISB.F0 = 0 ;
128 0b10000000 0200 0x80 PORTB.F0 = 1 ;
255 0b11111111 0377 0xFF PORTB.F0 = 0 ;

• Visualiser le contenu du fichier enregistré avec l’extension .hex ?

:020000001628C0
:0E0006008312031321088A00200882000800DC
:1000140003208A110A128000840AA00A0319A10A83
:08002400F003031D0A28080087
:10002C00831603130610831206140B30FB002630C4
:10003C00FC005D30FD00FD0B2128FC0B2128FB0B87
:10004C0021280000000006100B30FB002630FC00BD
:10005C005D3
0FD00FD0B3028FC0B3028FB0B3028ED
:08006C000000000019283928EA
:02400E004A2F37
:00000001FF

Application 2:
Supposant le montage suivant permettant de contrôler 8 diodes LED :
1) Nous proposons faire clignoter les LEDs branchées au port B du microcontrôleur de
deux façons différentes :
- Si RA0 = 0, tous les diodes LEDs clignotent avec une période d’une seconde.

- Si RA0 = 1, les diodes LEDs doivent clignoter chaque 500 ms comme indiqué dans
la figure ci-dessous.

Ecrire un programme C permettant de contrôler les LED.


2) - Si RA0=0, les 8 diodes LED clignotent pendant 2 secondes,
- Si RA0=1, on obtient le cycle répétitif suivant :

Diodes LED allumés Durée


D0D1 1s
D2D3 2s
D4D5 3s
D6D7 4s
Aucune diode 1s
Ecrire un programme C permettant de commander les diodes LED.
1.
*********************************************************************
Enbinaire:
*********************************************************************
#define B1 RA0_bit //Déclaration du boutton
int i;
void main()
{
TRISA=0b00000001; //le bit 0 de TRISA configuré comme entré
TRISB=0b00000000; //les bits de TRISB configuré comme sortie
PORTB=0b00000000; //Les leds sont initialement éteinteswhile(1)
{if(B1==0)
{
PORTB=0b11111111; //Les leds sont allumés
Delay_ms(500); //attente de 500 ms
PORTB=0b00000000; //Les leds sont éteintes
Delay_ms(500); //attente de 500 ms
}else
{
PORTB=0b01010101; //1 leds sont allumés et 0 Les leds sont éteintes
Delay_ms(500); //attente de 500 ms
PORTB=0b10101010;
Delay_ms(500);
}
}
}
*********************************************************************
En hexadecimal
*********************************************************************
#define B1 RA0_bit //Déclaration du bouttonint i;void main()
{
TRISA=0x01; //le bit 0 de TRISA configuré comme entré
TRISB=0x00; //les bits de TRISB configuré comme sortie
PORTB=0x00; //Les leds sont initialement éteinteswhile(1)
{if(B1==0)
{
PORTB=0xFF; //Les leds sont allumés
Delay_ms(500); //attente de 500 ms
PORTB=0x00; //Les leds sont éteintes
Delay_ms(500); //attente de 500 ms
}else
{
PORTB=0x55; // 0b01010101 pour 1 les leds sont allumés et 0 Les
leds sont éteintes
Delay_ms(500); //attente de 500 ms
PORTB=0xAA; // 0b10101010 pour 1 les leds sont allumés et 0 Les
leds sont éteintes
Delay_ms(500);
}
}
}
2.

*********************************************************************
En binaire
*********************************************************************
#define B1 RA0_bit //Déclaration du boutton B1 dans la broche 0 du
//PORTA
int i;
void main()
{
TRISA=0b11111111;
PORTB=0b00000000;while(1)
{if(B1==0)
{for(i=0; i<2; i++){
PORTB=0b11111111; Delay_ms(500);
PORTB=0b00000000; Delay_ms(500);
}
}else
{
PORTB=0b00000011; Delay_ms(1000);
PORTB=0b00001100; Delay_ms(2000);
PORTB=0b00110000; Delay_ms(3000);
PORTB=0b11000000; Delay_ms(4000);
PORTB=0b00000000; Delay_ms(1000);
} } }

*********************************************************************
En hexadecimal
*******************************************************************
#define B1 RA0_bit //Déclaration du boutton B1 dans la broche 0 du
//PORTA
int i;
void main()
{
TRISA=0xFF; //0b11111111
TRISB=0x00;
PORTB=0x00;while(1)
{if(B1==0)
{for(i=0; i<2; i++){
PORTB=0xFF; Delay_ms(500);
PORTB=0x00; Delay_ms(500);
}
}else
{
PORTB=0x03; Delay_ms(1000);
PORTB=0x0C; Delay_ms(2000);
PORTB=0x30; Delay_ms(3000);
PORTB=0xC0; Delay_ms(4000);
PORTB=0x00; Delay_ms(1000);
} } }

 Afficheurs 7 segments:
Application 3:
On veut commander un afficheur à 7 segments afin de réaliser un compteur modulo 10
à l’aide d’un microcontrôleur 16F84A.

1. Ecrire un programme C qui permet de réaliser le fonctionnement suivant :


- Compteur modulo 10 commandé par la position 1 du switcher (RA0).
- Décompteur modulo 10 commandé par la position 2 du switcher (RA1).
Remarque : MikroC vous permet de déterminer le code 7 segments ; en allant dans :
Tools → SevenSegment Editor.
Le tableau suivant vous permet aussi de déterminer le code 7 segments:
int i,CHIFFRE[10]={63, 6, 91, 79, 102, 109, 125,7, 127, 111};

void main()
{ TRISA=0b00000011;
TRISB=0b00000000;
//int i;

PORTB = 0;while(1)
{if(RA0_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[i]; delay_ms(1000); //De 0 à 9
}
}if(RA1_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[9-i]; delay_ms(1000); //De 9 à 0
}
}
}
}

Autrement:
*********************************************************************
Methode 1 En binaire:
*********************************************************************
void main()
{
TRISA=0b00000011; // Configuration du port A (Broche RA0 et RA1 en
entrée)
TRISB=0b00000000; // Configuration du port B en sortie
PORTA = 0; // Initialisation du port A
PORTB = 0; // Initialisation du port B
while(1)
{if(RA0_Bit == 1)
{
PORTB = 0b00111111;//Affichage du chiffre 0
delay_ms(100);
PORTB = 0b00000110;//Affichage du chiffre 1
delay_ms(100);
PORTB = 0b01011011;//Affichage du chiffre 2
delay_ms(100);
PORTB = 0b01001111;//Affichage du chiffre 3
delay_ms(100);
PORTB = 0b01100110;//Affichage du chiffre 4
delay_ms(100);
PORTB = 0b01101101;//Affichage du chiffre 5
delay_ms(100);
PORTB = 0b01111101;//Affichage du chiffre 6
delay_ms(100);
PORTB = 0b00000111;//Affichage du chiffre 7
delay_ms(100);
PORTB = 0b01111111;//Affichage du chiffre 8
delay_ms(100);
PORTB = 0b01101111;//Affichage du chiffre 9
delay_ms(100);

}if(RA1_Bit == 1)
{
PORTB = 0b01101111;//Affichage du chiffre 9
delay_ms(100);
PORTB = 0b01111111;//Affichage du chiffre 8
delay_ms(100);
PORTB = 0b00000111;//Affichage du chiffre 7
delay_ms(100);
PORTB = 0b01111101;//Affichage du chiffre 6
delay_ms(100);
PORTB = 0b01101101;//Affichage du chiffre 5
delay_ms(100);
PORTB = 0b01100110;//Affichage du chiffre 4
delay_ms(100);
PORTB = 0b01001111;//Affichage du chiffre 3
delay_ms(100);
PORTB = 0b01011011;//Affichage du chiffre 2
delay_ms(100);
PORTB = 0b00000110;//Affichage du chiffre 1
delay_ms(100);
PORTB = 0b00111111;//Affichage du chiffre 0
delay_ms(100);

}
}
}

*********************************************************************
Methode 2 En decimal:
*********************************************************************
int i,CHIFFRE[10]={
63, // Code du digit 0
6, // Code du digit 1
91, // Code du digit 2
79, // Code du digit 3
102, // Code du digit 4
109, // Code du digit 5
125, // Code du digit 6
7, // Code du digit 7
127, // Code du digit 8
111 // Code du digit 9
};

void main()
{
TRISA=0b00000011; // Configuration du port A (Broche RA0 et RA1 en
entrée)
TRISB=0b00000000; // Configuration du port B en sortie

PORTB = 0; // Initialisation du port B


while(1)
{if(RA0_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[i]; //Comptage De 0 à 9
delay_ms(100);
}
}if(RA1_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[9-i]; // Comptage De 9 à 0
delay_ms(100);
}
}
}
}

*********************************************************************
Methode 3 En Hexadecimal:
*********************************************************************
int i, CHIFFRE[] ={
0x3F, // Code du digit 0
0x06, // Code du digit 1
0x5B, // Code du digit 2
0x4F, // Code du digit 3
0x66, // Code du digit 4
0x6D, // Code du digit 5
0x7D, // Code du digit 6
0x07, // Code du digit 7
0x7F, // Code du digit 8
0x6F, // Code du digit 9
};
void main()
{
TRISA=0x03; // Configuration du port A (Broche RA0 et RA1 en entré
e)
TRISB=0x00; // Configuration du port B en sortie

PORTB = 0x00; // Initialisation du port B


while(1)
{if(RA0_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[i]; //Comptage De 0 à 9
delay_ms(100);
}
}if(RA1_Bit == 1)
{for(i=0;i<10;i++) {
PORTB = CHIFFRE[9-i]; // Comptage De 9 à 0
delay_ms(100);
}
}
}
}

 Minuterie:
Application 4:
On veut réaliser une minuterie d’escalier à 3 temps réglable (3min, 6min, 9min) à l’aide
d’un microcontrôleur 16F84A.

Le principe de fonctionnement est le suivant :


- Une impulsion sur l’un des boutons poussoir BPi, la LED D s’allume pendant un
temps T puis s’éteint.
- Deux impulsions successives est sans effet.
- Le temps est réglable par un commutateur C à trois positions.
Ecrire un programme C qui répond au cahier de charge.
#define BP RA0_Bit //Déclaration des boutons
#define Led RA2_Bit //Déclaration de LED
#define C1 RB5_Bit //Déclaration Switch1
#define C2 RB6_Bit //Déclaration Switch2
#define C3 RB7_Bit //Déclaration Switch3
void main(){
TRISA=0b00000001; //0x01 en hexadecimal
TRISB=0b11100000;//0xE0 en hexadecimal
while(1){
if(BP==1 && C1==1)
{
Led = 1; delay_ms(180000); Led = 0;
}if(BP==1 && C2==1)
{
Led = 1; delay_ms(360000); Led = 0;
}if(BP==1 && C3==1)
{
Led = 1; delay_ms(540000); Led = 0;
}
}
}
TP 2, PROGRAMMATION DU PIC 16F877A
GESTION DE L’AFFICHAGAGE LCD 2X16 ET DU CLAVIER
MATRICIEL

Objectif : A l’aide des microcontrôleurs, il est possible de réaliser des montages avec
une véritable gestion de l’information et des protocoles pour la communication de
données (entrées/sorties). Il devient possible d’utiliser, pour l’interface utilisateur, des
périphériques "évolués" comme des claviers matriciels ou encore des afficheurs à
cristaux liquides (LCD). Nous nous intéressons dans ce 2 ème TP à la gestion du
clavier matriciel et de l’afficheur LCD 2x16.

I- L’afficheur LCD 2x16


La figure ci-dessous montre le brochage d’un afficheur LCD 2x16 :

Le tableau suivant donne une description rapide de la fonction de chaque broche :


En observant le brochage
de l’afficheur, on
constate qu’il
faut un minimum de 6
sorties pour le
commander. En effet, si
on utilise l’adressage sur
4 bits et que l’on se prive
de la
lecture dans l’afficheur
(ce n’est pas nécessaire,
donc on
relie R/W à la masse), il
nous faut commander les
six
broches : EN, RS, D4,
D5, D6, et D7.

Le compilateur MikroC utilise des fonctions (bibliothèques) pour simplifier aux


utilisateurs l’exploitation des afficheurs LCD. On utilise souvent l’instruction "sbit"
pour affecter chaque broche du LCD à une broche du PIC.
Remarque : Utiliser "LCD Library" à partir du help du MikroC.

Ainsi, d’autres fonctions peuvent être utilisées :


Lcd_Out : affiche un texte à la position spécifiée, exemple Lcd_Out (1, 1, ''TP3")
Lcd_Out_Cp : affiche un texte à la position courante, exemple Lcd_Out (1, 1, ''ici")
Lcd_Chr : affiche un caractère à la position spécifiée, exemple Lcd_Chr (1, 3, ''T")
Lcd_Cmd : envoi une commande au LCD, exemple Lcd_Cmd(_LCD_CLEAR) ;
II- Gestion de l’affichage d’un message via le PIC 16F877A et

l’afficheur LCD 2x16

Application 1:

Soit le montage de la figure ci-dessous. Ecrire un programme C qui répond au


fonctionnement suivant :
• Lorsqu’on appuie sur le bouton B1 seul, l’afficheur affiche ’BONJOUR’ et la
diode D1 clignote.
• Lorsqu’on appuie sur le bouton B2 seul, l’afficheur affiche ‘BONSOIR’ et la
diode D2 clignote.
• Lorsqu’on appuie sur le bouton B3 seul, l’afficheur affiche ‘SALAM’ et la
diode D3 clignote.
• Pour les autres cas, rien ne se passe.
#define B1 //Button B1 sur
RB2_bit la broche 2 du PORTB
#define B2 //Button B2 sur
RB1_bit la broche 1 du PORTB
#define B3 //Button B3 sur
RB0_bit la broche 0 du PORTB
#define D1 //LED D1 sur la
RC0_bit broche 0 du PORTC
#define D2 //LED D2 sur la
RC3_bit broche 3 du PORTC
#define D3 //LED D3 sur la
RC6_bit broche 6 du PORTC
//Declaration des pinesde LCD
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
char msg1[]="BONJOUR";
char msg2[]= "BONSOIR";
char msg3[]="SALAM";
void main()
{ TRISB = 0b11111111;//0xFF en hexadecimal,configuration du PORTB
//comme entree
TRISC = 0b0000000; //0x00 en hexadecimal,configuration du PORTC comme
//sortie
TRISD = 0b00000000;/0x00 en hexadecimal,configuration du PORTD comme
//sortie
Lcd_Init();//Initialisation de LCD
Lcd_Cmd(_LCD_CLEAR);//Effacer le contenu de l’ecran LCD
Lcd_Cmd(_LCD_CURSOR_OFF);//Supprimer le curseur
D1 = 0; D2 = 0; D3 = 0; //LEDs D1,D2 et D3 initialement eteint

while(1)
{if(B1==1 && B2==0 && B3==0)
{
Lcd_Out(1, 1, msg1); //Commande affiche le contenu du tableau msg1
//sur la 1er ligne et la 1er colonne de LCD
D1 = 1; delay_ms(500);
D1 = 0; delay_ms(500);
}else if(B1==0 && B2==1 && B3==0)
{
Lcd_Out(1, 1, msg2);//Commande affiche le contenu du tableau msg2
//sur la 1er ligne et la 1er colonne de LCD
D2=1;delay_ms(500);D2=0;delay_ms(500);
}else if(B1==0 && B2==0 && B3==1)
{
Lcd_Out(1, 1, msg3);//Commande affiche le contenu du tableau msg3
//sur la 1er ligne et la 1er colonne de LCD
D3=1;delay_ms(500);D3=0;delay_ms(500);
}else
{
Lcd_Cmd(_LCD_CLEAR);//Effacer le contenu de l’ecran LCD

D1 = 0; D2 = 0; D3 = 0;//LEDs D1,D2 et D3 reinitialiser comme eteint


}}}

III- Gestion de l’affichage via le PIC 16F877A, l’afficheur LCD

2x16 et un clavier matriciel (keypad)


Application 2:
A titre d’exemple, un clavier matriciel 4x4 est composé de 4 lignes ( L1 L2 L3 L4) et
de 4 colonnes ( C1 C2 C3).
Lorsqu’une touche est enfoncée, une connexion entre une ligne et une colonne est
établi.

Le brochage dit "matrice carrée" (comme le montre la figure) nécessite l'utilisation


d'un port parallèle, obligatoirement bidirectionnel, complet (8 bits de P0 à P7). Le
poids faible de ce port sera réservé pour les colonnes et initialisé en entrée avec la
valeur "1111" tandis que son poids fort est affecté aux lignes et initialisé en sortie
avec la valeur "0000".
Codage du clavier matriciel : On sait déjà qu'une touche enfoncée provoque un
court-circuit entre la ligne et la colonne correspondantes. Si ce court-circuit est
matérialisé par un niveau logique 0 et tout le reste est à 1, on peut alors facilement,
établir le tableau de la figure suivante :
Décodage du clavier matriciel : L'acquisition d'une touche se fera par scrutation
(examen), en effectuant une lecture permanente de l'état du clavier. A l'appui d’une
touche, le microcontrôleur
se dépêche pour explorer judicieusement les codes, déjà établis théoriquement, dans le
tableau précédent.
Application 3:
La figure ci-dessous montre l'utilisation d'un clavier 4*4 et un écran LCD
alphanumérique.
Ecrire un programme C qui permet de lire un caractère à partir du clavier et l’affiche
sur l’écran LCD.

char keypadPort at PORTD;//Declaration du clavier sur le PORTD


sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB4_bit;
int kpi;
void main ( )
{
Lcd_Init ( ) ;//Initialisation de LCD
Lcd_Cmd (_LCD_CLEAR);//Effacer l'écran LCD
Keypad_Init ( );//Initialisation du KeyPad
Lcd_Out (1,1,"Tapez une touche"); //Commande pour afficher "Tapez
une touche"
delay_ms (1000);
Lcd_Cmd (_LCD_CLEAR);//Effacer l'écran LCD
do{
kpi = 0;
//Boucle qui attend un clic
do
kpi = Keypad_Key_Click ( );//Keypad_Key_Click( ) ecoute le boutton
//presser
while (!kpi);

//switch sur kpi


switch (kpi) {
case 1:
kpi = 55; break; // 7
case 2: kpi = 52; break; // 4
case 3: kpi = 49; break; // 1
case 4: kpi = 32; break; // Espace
case 5: kpi = 56; break; // 8
case 6: kpi = 53; break; // 5
case 7: kpi = 50; break; // 2
case 8: kpi = 48; break; // 0
case 9: kpi = 57; break; // 9
case 10: kpi = 54; break; // 6
case 11: kpi = 51; break; // 3
case 12: kpi = 61; break; // =
case 13: kpi = 47; break; // /
case 14: kpi = 42; break; // x
case 15: kpi = 45; break; // -
case 16: kpi = 43; break; // +
}
Lcd_Chr (1, 2, kpi);//Affichage du caractere correspendant au code
//ASCII sur kpi dans la 1er ligne et 2eme colonne de l’ecran LCD

}while (1);}
TP 2, INITIATION A LA PROGRAMMATION DU Cortex M4
NUCLEO STM32F446RE

Le Cortex-M4 est un microcontrôleur de la série Cortex-M développé par ARM et qui


est utilisé dans le microcontrôleur STM32F446RE utilisé dans ce TP. Il a été conçu pour
les applications embarquées nécessitant des performances élevées et une faible
consommation d'énergie. Il prend en charge une variété de fonctionnalités telles que
la gestion des interruptions, le traitement des signaux numériques, la conversion
analogique-numérique, ainsi que les fonctions de mémoire et de communication
standard. Le Cortex-M4 est souvent utilisé dans des applications telles que les
systèmes de contrôle industriel, les systèmes de sécurité, les systèmes de contrôle de
moteur, les systèmes d'éclairage intelligents, etc. Il est considéré comme un choix
populaire pour les ingénieurs en raison de sa flexibilité et de sa capacité à développer
rapidement.

Il est important de noter que pour programmer ce type de microcontrôleur, il faut


utiliser un IDE approprié.
Parmi les IDE utilisés se trouvent Cube IDE et KEIL.
Nous allons commencer par Cube IDE.

I-Introduction de CUBE IDE :


STM32CubeIDE est une plateforme de développement C/C++ avancée qui propose des
fonctionnalités de configuration de périphériques, de génération de code, de
compilation et de débogage pour les microcontrôleurs et microprocesseurs STM32.
Pour commencer, il est nécessaire de télécharger la version 1.10.0 de STM32CubeIDE
sur le site Web indiqué ci-dessous.
https://www.st.com/en/development-tools/stm32cubeide.html#get-software

Vous devez remplir le formulaire en fournissant une adresse e-mail valide pour recevoir le
lien de téléchargement dans votre boîte de réception.
2. Une fois STM32CubeIDE installé, il est temps de l'ouvrir et de sélectionner votre répertoire
de travail, comme illustré sur la figure.

3. Après avoir choisi votre répertoire de travail, vous accéderez à la première fenêtre.

Cliquez sur "Démarrer un nouveau projet STM32", puis sélectionnez le numéro de


série de votre carte, "NUCLEO-F446RE" dans ce cas.
II-ARM Cortex-M4 Architecture
Introduction
ARM est une société de propriété intellectuelle de semi-conducteurs fondée en 1990,
issue de la collaboration entre Apple Computer, Acorn Computer Group et VLSI
Technology.
En 1991, ARM a présenté sa conception de processeur ARM6 et VLSI Technology a été
le premier à accorder une licence pour sa conception. Depuis, de nombreuses autres
grandes sociétés de semi-conducteurs, telles que Texas Instruments,
STMicroelectronics, Freescale, Broadcom, Atmel et nVIDIA, ont également acheté les
conceptions IP d'ARM. ARM a développé de nombreux processeurs et IP qui ont été
achetés par plus de 250 entreprises. Parmi ses produits, on trouve la famille ARM
Cortex, basée sur les architectures ARMv4, ARMv5, ARMv6 et ARMv7. La famille ARM
Cortex se subdivise en trois profils, comme indiqué ci-dessous :

Cortex-A : Les processeurs de ce profil sont utilisés dans les appareils à haute
performance tels que les téléphones mobiles.
Cortex-R : Les processeurs de ce profil sont principalement utilisés dans les
applications en temps réel, où la priorité est de réduire le temps de réponse. Il existe
plusieurs versions d'ARM Cortex R.

Cortex-M : Les processeurs de ce profil sont utilisés pour les systèmes embarqués
basés sur des microcontrôleurs. La famille Cortex-M inclut les modèles Cortex-M0,
Cortex-M0+, Cortex-M1, Cortex-M3, Cortex-M4 et Cortex-M7.

ARM Cortex M à plusieurs versions :


Cortex-M0 : est la version la plus basique et la plus légère du Cortex-M d'ARM.
Il est principalement utilisé dans les applications qui requièrent une faible
consommation d'énergie et une faible empreinte mémoire
Cortex-M0+: Il s'agit d'une version améliorée du Cortex-M0, avec une
performance accrue et une gestion améliorée de l'énergie. Il est souvent utilisé
dans les applications qui nécessitent une faible consommation d'énergie et une
faible empreinte mémoire, telles que les capteurs et les systèmes de contrôle
de moteur de petite taille.
Cortex-M3: Il s'agit d'une version plus avancée du Cortex-M, basée sur
l'architecture ARMv7, avec un jeu d'instructions étendu et une capacité de
traitement accrue. Il est utilisé dans une large gamme d'applications,
notamment les systèmes de contrôle de moteur, les dispositifs de sécurité et
les produits de consommation.
Cortex-M4: Il s'agit d'une version encore plus avancée du Cortex-M, basée sur
l'architecture ARMv7, avec un jeu d'instructions étendu et une capacité de
traitement accrue. La principale différence par rapport à la version Cortex-M3
est l'ajout d'une unité de traitement du signal numérique (DSP) intégrée, ce qui
le rend particulièrement adapté aux applications audio et vidéo.
Cortex-M4F : Il s'agit d'une version du Cortex-M4 qui inclut une unité de calcul
flottant (FPU). Il est souvent utilisé dans les applications qui nécessitent un
traitement du signal numérique à haute performance, telles que la
reconnaissance de la parole et les systèmes de navigation.

ARM Cortex-M4
Le Cortex-M4 est un processeur 32 bits conçu pour des performances de traitement
élevées, une gestion de 4 Go d'espace d'adressage mémoire, un traitement rapide
des interruptions et une faible consommation d'énergie. Il possède une architecture
Harvard pipeline à 3 étages, idéale pour les applications embarquées nécessitant un
traitement haut de gamme. Carte mémoire :
ARM Cortex-M4 Registre
Le Cortex-M4 a des registres de 32 bits, comprenant :
1- 13 registres généraux, numérotés de R0 à R12.
2- Le Pointeur de pile (SP), aliasé en Main Stack Pointer et Process Stack Pointer,
numéroté R13.
3- Le Registre de liaison (LR), numéroté R14.
4- Le Compteur de programme (PC), numéroté R15.
5- Des registres spéciaux, tels que le Registre d'état du programme (PSR), les
registres de masque d'exception et le Registre de contrôle.

Les registres les plus importants à connaître pour le moment sont les suivants, nous en discuterons plus en
détail lors des prochaines séances :
1- Registres à usage général : Les registres R0 à R12 sont destinés aux opérations
de données et sont divisés en deux ensembles : - Registres bas : Les registres R0 à
R7 font partie de cet ensemble et sont accessibles par toutes les instructions. -
Registres hauts : Les registres R8 à R12 font partie de cet ensemble et ne sont
accessibles que par des instructions 32 bits, et non par des instructions 16 bits.
2- Compteur de programme (PC) : Le registre R15 est utilisé comme compteur de
programme. Il stocke l'adresse de la prochaine instruction à exécuter. Dans une
valeur de PC de 32 bits, le bit [0] est toujours mis à zéro afin que le PC reste aligné
sur les limites d'instruction des mots (32 bits) ou des demi-mots (16 bits).
3-Registre d'état du programme (PSR) : Le registre d'état du programme est
constitué de divers indicateurs tels que les indicateurs de traitement arithmétique
et logique et les indicateurs d'état d'exécution. Le PSR est une combinaison du
registre d'état du programme d'application (APSR) et du registre d'état du
programme d'exécution (EPSR).
4-Registre de liaison (LR- R14) : Le registre de liaison (LR) est le registre R14, et il
stocke les informations de retour pour les sous-routines, les appels de fonction et
les exceptions. Le registre de liaison est accessible en mode privilégié ou non
privilégié.

Les périphériques de base du processeur Cortex-M4 :


La section suivante décrit les périphériques de base du processeur Cortex-M4 :
1-Nested Vectored Interrupt Controller (NVIC) : Il s'agit d'un contrôleur intégré
d'interruptions qui prend en charge la configuration d'interruptions externes avec un
maximum de 240 interruptions. Il permet d'attribuer une priorité programmable allant
de 0 à 255, où 0 est le niveau de priorité le plus élevé. Il gère également la chaîne
d'interruptions.
2-Unité à virgule flottante (FPU) Cette unité peut effectuer des opérations en virgule
flottante en simple précision (32 bits). Elle gère les opérations d'addition, de
soustraction, de multiplication et d'accumulation, ainsi que les opérations de racine
carrée. Elle offre également des conversions entre les formats de données en virgule
fixe et en virgule flottante.

BOARD STM32F446RE (NUCLEO 64) :


Cette carte composée de :
Noyau : Processeur Arm® 32 bits Cortex®-M4 avec FPU, fréquence jusqu'à 180 MHz, .
Mémoires : 512 K-octets de mémoire Flash 128 K-octets de SRAM Contrôleur de
mémoire externe flexible avec un bus de données jusqu'à 16 bits : SRAM, PSRAM,
SDRAM/LPSDR SDRAM.
Broches : Jusqu'à 114 ports d'E/S avec possibilité d'interruption, Jusqu’à 111 E/S
rapides jusqu'à 90 MHz ,Jusqu'à 112 E/S tolérantes à 5 V (les autres 3 .3 V).
Communication Jusqu'à 20 interfaces de communication, Jusqu'à 4× interfaces I2C, 2×
CAN ….
TIMER : Jusqu'à 17 timers : 2x chien de garde, 1x timer SysTick et jusqu'à 12 timers 16
bits et deux 32 bits jusqu'à 180 MHz, chacun avec un maximum de quatre timers. ;
Clock : Oscillateur à cristal de 4 à 26 MHz, RC interne de 16 MHz réglé en usine
(précision de 1 %) ,Oscillateur 32 kHz pour RTC avec calibration, RC interne de 32 kHz
avec calibrage, on a comme exemple :
Horloge haute vitesse externe (HSE) : il s'agit généralement d'un
oscillateur à cristal externe. Elle peut être utilisée comme horloge
principale du système ou comme source d'horloge pour le PLL..
Horloge basse vitesse externe (LSE) : il s'agit généralement d'un
oscillateur à cristal externe fonctionnant à une fréquence inférieure à
celle de l'HSE. Elle peut être utilisée comme source d'horloge pour le
module RTC (horloge temps réel).
Oscillateur interne haute vitesse (HSI) : il s'agit d'un oscillateur RC
interne à fréquence de 16 MHz. Il est utilisé comme source d'horloge
par défaut lorsque le système est alimenté.
Oscillateur interne basse vitesse (LSI) : il s'agit d'un oscillateur RC
interne à fréquence d'environ 32 kHz. Il peut être utilisé comme source
d'horloge pour le module RTC ou comme source d'horloge pour le
watchdog timer.
La source d'horloge utilisée par le microcontrôleur STM32F446RE dépend de la
configuration de l'arbre d'horloge et des besoins spécifiques du système. Elle est
généralement configurée à l'aide des registres de configuration ou bien de la
configuration graphique.

III-TP1 : Usage de GPIO pins de STM32


Dans ce TP, nous allons expliquer comment initialiser les broche GPIO (General-
Purpose-Input-Output) du Microcontrôleur de STM32, pour contrôlez des LEDS, et
faire une simulation dans Isis Proteus version 8.13 :
Durant Ce TP on doit suivre deux méthodes :
1- Configuration Graphique de GPIO avec l’interface CUBE STM32 et La
bibliothèque HAL
2- Configuration Manuel de GPIO avec les registres

PARTIE 1
Pour Configurer n’importe quel GPIO d’un stm32 il faut suivre les étapes suivantes :

1- Initialiser de l’horloge principale de la carte.


2- Activer et configurer les broches

Pour cette partie, nous allons suivre les étapes mentionnées ci-dessus pour une
configuration graphique.
Bibliothèque HAL (Hardware Abstraction Layer)
HAL (Hardware Abstraction Layer) fourni par STMicroelectronics pour une utilisation
avec les microcontrôleurs STM32.
Le pilote HAL est une couche de logiciel qui fournit une interface standardisée pour
interagir avec les fonctionnalités matérielles des microcontrôleurs STM32. Il est conçu
pour simplifier le processus de développement de logiciels pour le STM32 en
fournissant un ensemble d'API (interfaces de programmation d'applications) qui
peuvent être utilisées pour accéder aux périphériques matériels du microcontrôleur
de manière cohérente et portable. Le pilote HAL est écrit en C et est destiné à être
utilisé avec le langage de programmation C, bien qu'il puisse également être utilisé
avec d'autres langages pouvant s'interfacer avec le code C.

Application 1:
1- L’initialisation de l’horloge principale de la carte.

NB : nous allons travailler avec une carte différente STM32F401VE

afin de pouvoir faire une simulation en Proteus

Pour configurer l'horloge système sur notre carte à l'aide de l'interface graphique (GUI)
de l'outil STM32Cube, voici les étapes à suivre :
.

1- Ouvrir STM32CubeMX et créer un nouveau projet pour votre microcontrôleur


STM32.
2- Dans l'onglet de Configuration de l'horloge, sélectionner la source d'horloge pour
l'horloge système dans la liste déroulante "Source d'horloge". Elle peut être un
oscillateur externe ou interne, tel que HSI (oscillateur interne à haute vitesse) ou LSI
(oscillateur interne à basse vitesse).
3- Configurer les paramètres de l'oscillateur choisi en cliquant sur le bouton "Modifier"
à côté de son nom. Cela ouvrira la fenêtre de configuration de l'oscillateur, où vous
pourrez déterminer la fréquence de l'oscillateur et les autres options de configuration.
4- Configurer les diviseurs d'horloge système en cliquant sur le bouton "Configuration"
à côté de l'étiquette "Configuration de l'horloge". Cela ouvrira la fenêtre de
configuration de l'horloge, où vous pourrez définir le prédiviseur AHB, le prédiviseur
APB1 et le prédiviseur APB2."
2- Configuration de GPIO .

Pour configurer une broche GPIO à l'aide de STM32CubeMX, voici les étapes à
suivre : Dans l'onglet Pinout & Configuration, choisir la broche GPIO à
configurer sur le diagramme de la pinout.

Dans le panneau de configuration, sélectionnez le mode souhaité pour la


broche GPIO dans la liste déroulante "Mode".
Dans cette partie, nous allons travailler avec le port A et configurer les
broches PA1, PA2 et PA3 en tant que sortie (GPIO_Output).

Cliquez sur le bouton "Générer le code" ou Cliquez sur icone comme la figure ci-dessous .

Après le code généré dans le fichier Main.C ainsi toutes les bibliothèques nécessaires de votre espace de travail.
Code Généré

int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the
Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
}
}

HAL_Init(); Sert à initialiser la librairie HAL,elle doit être la première instruction à être exécutée dans le
programme principal (avant d'appeler toute autre fonction HAL), elle effectue ce qui suit : Configurer le Flash
prefetch, les caches d'instructions et de données.
SystemClock_Config(); Ce bloc sert a configurerez horloge de système
void SystemClock_Config(void)

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


/** Configure the main internal regulator output voltage

*/

__HAL_RCC_PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

/** Initializes the RCC Oscillators according to the specified parameters

* in the RCC_OscInitTypeDef structure.

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;//selction l’oscillateur interne

RCC_OscInitStruct.HSIState = RCC_HSI_ON;//definir le statut de RCC

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; //active le PLL

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

RCC_OscInitStruct.PLL.PLLM = 8;//predivision de l’horloge pour les périphériques de STM32

RCC_OscInitStruct.PLL.PLLN = 84;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 2;

RCC_OscInitStruct.PLL.PLLR = 2;

MX_GPIO_Init(); Ce block est très intéressant, on configure chaque broche de PORT A


static void MX_GPIO_Init(void)

GPIO_InitTypeDef GPIO_InitStruct = {0};

/* GPIO Ports Clock Enable */

__HAL_RCC_GPIOA_CLK_ENABLE();// active l”horloge de port A

/*Configure GPIO pin Output Level */

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_RESET);//define l’état par

default (reset)

/*Configure GPIO pins : PA1 PA2 PA3 */

GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;//sélectionner le pins

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//configure le mode de broche(sortie)

GPIO_InitStruct.Pull = GPIO_NOPULL;//configure les resistance pull up pull down

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;//chosiir la fréquence de sortie

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);//envoyer le pointeur de structure vers la mémoire pour

enregister ces informations

La structure de contrôle while (1){}: ici on écrit notre programme .


Code de Clignoter de 3 LEDS et Simulation Sur Proteus
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,
GPIO_PIN_SET);//allumer led
HAL_Delay(300);//delay
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,
GPIO_PIN_RESET);//éteindre les leds
HAL_Delay(300);delay

HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,


GPIO_PinState PinState);
Cette fonction utilise le registre GPIOx_BSRR pour permettre les accès atomiques en
lecture/modification.
De cette façon, il n'y a aucun risque qu'une IRQ se produise entre l'accès en lecture et
l'accès en modification
Paramètres:
GPIOx : pour sélectionner le périphérique GPIO pour le périphérique ou x peut être
(A..I)
GPIO_Pin : spécifie le bit de port à écrire.
GPIO_PinState : État de la broche spécifie la valeur à écrire dans le bit sélectionné
GPIO_PIN_RESET : pour effacer la broche du port (0)
GPIO_PIN_SET : pour définir la broche du port (1)
HAL_DELAY(uint16_t) : C' est l' équivalent de la fonction delay() avec entree en ms.

Apres Pour compiler et générer fichier hex on doit activer option comme la figure ci-dessous

Et après nous devons cliquer sur Build


Dans Proteus, nous devons créer le schéma indiqué et intégrer le fichier hex dans notre
microcontrôleurSTM32F401VE (applique aux versions de Proteus supérieures à v8.8).

Apres on lance la simulation on doit remarquer que les 3 LEDS clignote avec un Delay de 300ms

Application 2:
Sur le même Project, Essayez de modifier le code précédent afin d'avoir 6 LEDS qui clignotent
séquentiellement
Application 3:
Sur le même Project, Essayez de réaliser un compteur 0 a 9 avec afficheur 7SEG-CAT sur la PORT D de
notre microcontrôleur.
Remarque : il faut suivre les mêmes étapes de configuration des GPIOs
II-PARTIE 2
Dans cette section, nous configurons les GPIOs directement à l'aide des registres en nous
basant sur la datasheet du microcontrôleur.
Microcontrôleur GPIO pins :
Le microcontrôleur utilisé dans ce TP, le STM32F401VE, est basé sur le cortex M-4 d'ARM et dispose de 6 ports :
PORTx avec x=(A, B, C, D, E, H). Chaque port a une plage d'adresses associée, comme décrit ci-dessous :

Nous pouvons observer que chaque port est alloué une quantité de mémoire
déterminée, en raison de ses différentes fonctionnalités et de ses registres spéciaux
associés. Pour configurer les GPIO sur notre carte, nous allons suivre les étapes
suivantes :
1-Activer l'horloge du port GPIO:
Il est important de savoir que chaque registre correspond à une adresse physique
spécifique définie par le fabricant. Ainsi, nous devons d'abord définir l'adresse de
chaque pointeur dans notre programme. Par exemple :
#define RCC_AHB1ENR (*((volatile unsigned long *) 0x40023830))
Cette ligne de code définit une constante qui pointe vers une adresse mémoire
spécifique dans le registre RCC, et peut être utilisée pour lire ou écrire des valeurs à
cette adresse. Pour simplifier cette tâche, nous incluons le fichier stm32f401xe.h, qui
contient les déclarations des registres associées à leurs adresses physiques. C'est la
meilleure façon, pour les débutants, d'éviter les erreurs potentielles. Par défaut,
l'option d'horloge est désactivée pour tous les ports GPIO du microcontrôleur afin
d'économiser de l'énergie. Pour activer l'horloge d'un port, nous utilisons le registre
RCC_AHB1ENR qui est mappé à l'adresse physique 0x40023830.

Les bits 0-6 et le bit 7 sont utilisés pour activer la clock


Par Example si nous voulons activer l’horloge de PORT A, est se fait de la manière suivante :
RCC->AHB1ENR |=0X01; // activer horloge pour A
RCC->AHB1ENR |=0X02; // activer horloge pour B
RCC->AHB1ENR |=0X04; // activer horloge pour C
RCC->AHB1ENR |=0X10; // activer horloge pour E

2-Configurer le mode de fonctionnement :


Dans cette partie on va configurer le registre GPIOX_MODER ,
GPIOA_MODER est mappé sur l’adresse 0X4002 0000.

Dans ce registre chaque 2 bits est associé a un pin avec la relation 2y,2y+1 (avec y est
le numéro de pin).
Alors on :
00 : configurer la broche comme entré (par défaut )
01 : configurer la broche comme sortie
10 : le mode de fonctionnement alternatif
11 : mode analogique
Alors si je vous mettre le PA2 comme une sortie :
GPIOA->MODER |=(1<<4) ; //PA2output
Si je vous mettre plusieurs broches en sortie PA1, PA3, PA5, PA6 ;
GPIOA->MODER |= (1<<2)| (1<<6)| (1<<10)| (1<<12) ;
Vous pouvez utiliser des valeurs décimales, binaires ou hexadécimales, ou encore le
décalage selon votre méthode préférée.
3-Configurer le type de sortie du pin
Dans cette partie on va configurer le registre GPIOX_OTYPER .
GPIOA_OTYPER est mappé sur l’adresse : 0x40020004 (Adresse de base de GPIOA+
adresse offset de OTYPER).
Alors dans ce registre on a juste 16 bits qu’on peut configurer les autres sont réservés.
Si je mets :
0 : sortie push-pull (par défaut)
1 : sortie open-drain
Une sortie push-pull est capable de fournir du courant à la charge connectée et de la
mettre à la masse. Cela signifie que la sortie peut être utilisée pour envoyer des
signaux logiques à haut niveau (1) ou à bas niveau (0).
Une sortie open-drain, en revanche, ne peut pas fournir de courant à la charge. Elle ne
peut que la mettre à la masse. Pour envoyer un signal logique à haut niveau (1), il faut
utiliser une résistance de pull-up pour maintenir la tension à haut niveau lorsque la
sortie open-drain est mise à la masse. Pour envoyer un signal logique à bas niveau (0),
la sortie open-drain est mise à la masse directement.
Alors si je vous mettre le PA2 Sortie push-pull :
GPIOA->OTYPER &=~(0x1 << 2);
4-Configurer la vitesse du pin
Dans cette partie on va configurer avec le registre GPIOx_OSPEEDR.
GPIOA_OSPEEDR est mappé sur l’adresse : 40020008

Dans ce registre chaque 2 bits est associé a un pin avec la relation 2y,2y+1 (avec y est
le numéro de pin).
Alors on :
00 : faible vitesse
01 : vitesse moyenne
10 : vitesse élevée
11 : très haute vitesse
Alors si je veux mettre PA2 comme une vitesse élevée , je vous mettre 0 dans bit[4] et
1 dans le bit[5]
GPIOA->OSPEEDR &= ~ (0x1 << 4) ; //mettre 0 dans bit 4 (c’est optionnel c’est la valeur
par défaut mais pas toujours pour les autres GPIO)
GPIOA->OSPEEDR |= (0x1 << 5) ;;// mettre 1 le bit 5

5-configuration pull-up/pull-down
Dans cette section, nous allons configurer à l'aide du registre GPIOx_PUPDR. Ce
registre nous permet d'utiliser des résistances internes pull-up ou pull-down. Chaque
2 bits sont associés à un pin selon la relation 2y, 2y+1 (où y est le numéro du pin).
Alors on :
00 : No pull-up, pull-down
01 : pull-up
10 : pull-down
11 : Reserved

Par exemple si je vous mettre PA13 sans pull-up et sans pull-down


GPIOA ->PUPDR &=~(0x1 << 26) ; j’ai le bit 27 est par défaut 0 par contre le bi1 26 par défaut
à 1 donc je Dois le mettre à 0.

5-Ecrire sur un port


Pour écrire sur un port de sortie sur un microcontrôleur STM32, vous pouvez utiliser
le registre GPIOx_ODR
Ce registre permet d'écrire des valeurs sur les broches, par exemple en mettant le bit PA2 à 1 (high) et le bit PA3 à
0:
GPIOA->ODR |= (1<<2) ; // mettre PA2 à A
GPIOA->ODR &= ~(1<< 3); // mettre PA3 à 0
Il existe un autre registre pour écrire sur un PORT, c’est le registre GPIOx_BSRR
Se registre contient deux parties :
- Bit 0 à 15 sert à mettre 1
- Bit 16 -31 mettre 0

Application :
En suivant les étapes précédentes, nous voulons créer une fonction de configuration
du port. Trois LED sont connectées à la PORTA (broches 1, 2 et 3) ;
Void GPIO_Config(void){
RCC->AHB1ENR |=0X01; // activer le clock de la port A
GPIOA->MODER |=(0x1<<2 | (0x1<<4)| (0x1<<6); // configurer PA1,2,3 comme sortie .
GPIOA->MODER &= (unsigned) ~ (0x1 << 3) | (unsigned)( ~(0x1<<5)) | (unsigned)( ~(0x1<<7));// cette instruction
n’est pas
nécessaire dans
notre cas
GPIOA->OTYPER &=(unsigned)~(0x7 << 1); // definir sortie avec push pull
GPIOA->OSPEEDR |= (0x1 <<3) | (0x1 << 5) | (0x1 << 7); // Définir la vitesse plus élevés
}
void delay_ms(uint32_t ms){
// Convertir le délai en nombre de cycles d'horloge
uint32_t delay = ms * (SystemCoreClock / 1000);
while (delay--) {// Boucle de délai en utilisant l'instruction NOP
__NOP(); }
}
//Fonction Main
int main(){
GPIO_Config() ; // appel de fct en haut pour configurer les port
While(1){
GPIOA->ODR |= 0x7 << 1; //écrire 1 sur pin (1,2,3) càd allumer les leds
delay_ms(1000); //delay
GPIOA->ODR &=(unsigned) ~(0x7<<1);//écrire 0
delay_ms(1000);
} //end while
}//end main
On écrivant ce code dans IDE Keil U Vision comme ci -dessous :

On ajoute l’option de génération de fichier. hex dans Keil :


Le fichier se trouve dans le dossier \Objects de votre projet, et il peut être simulé sur Proteus.
Application 2:
Réaliser les mêmes applications de la première partie, mais uniquement en utilisant les registres et l'IDE Keil (sans
utiliser de bibliothèque HAL).
Partie 2 : solution des applications par la méthode
graphique HAL

I-Atelier 1 : exemple avec méthode graphique


Partie 1 :
Dans cette partie, six LED sont connectées aux broches PA1 à PA6 et nous devons faire clignoter trois
LED de manière successive. Voici le code correspondant à cette partie :
While(1){
//allumer les leds
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3, GPIO_PIN_SET);
HAL_Delay(300); //delay
//eteindre les leds
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3,
GPIO_PIN_RESET);
HAL_Delay(300);//delay
}

Partie 2 :
Dans cette partie on va clignoter les leds brancher sur PA1-PA6 séquentiellement l’une après l’autre.
Pour réaliser cette partie on a utilisé deux méthodes :
1-Méthode 1 (méthode simple )
While(1){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);//allumer
HAL_Delay(300);//delay
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);//eteindre
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);//allumer
HAL_Delay(300);//delay
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);//eteindre
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);//allumer
HAL_Delay(300);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
HAL_Delay(300);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_Delay(300);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
HAL_Delay(300);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);

}
Ce code allume et éteint chaque broche l'une après l'autre avec un délai de 300ms entre
chaque broche avec la fonction HAL_Delay(300).
2-Méthode 2 (méthode avec boucle for( ;;))
Pour résoudre cette application le code précédent utilise 18 ligne,
Par contre on peut les simplifier et optimiser notre code en utilisant ce code suivant :

While(1)
{
short i; //declaration local d’un variable
for(i=1;i<7;i++)
{
HAL_GPIO_WritePin(GPIOA, 1<<i, GPIO_PIN_SET);\\allumer
HAL_Delay(300);\\delay de 300 ms
HAL_GPIO_WritePin(GPIOA,1<<i, GPIO_PIN_RESET);\\eteindre
}
}

Partie 3:
Dans cette partie, nous allons utiliser un afficheur 7 segments pour afficher un
compteur allant de 0 à 9 sur le PORT D de notre microcontrôleur. Nous allons
travailler sur le même projet que les parties 1 et 2 et ajouter les modifications
nécessaires pour atteindre notre objectif. Pour commencer, nous devons
activer l'horloge du PORT D en utilisant l'instruction suivante :

__HAL_RCC_GPIOD_CLK_ENABLE();
Après l’activation de l’horloge, maintenant il faut configurer les broches utilisés,
c’est-à-dire PD0-PD6 comme sorties :
GPIO_InitStruct.Pin=
GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;

//sélectionner les pins avec leur nom


GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
// configure le mode de pin avec sortie push -pull
GPIO_InitStruct.Pull = GPIO_NOPULL;
// pas de pull_up ou pull_down
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
// determiner la fréquence de sortie
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
// dans cette instruction on a envoyé un pointeur qui pointe sur les information pour les appliqués Sur
port D

Ou bien on peut utiliser ce code suivant :


for(int i=0;i<7;i++)
{
GPIO_InitStruct.Pin = 1<<i; //choisir le pin
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//mode de sortie
GPIO_InitStruct.Pull = GPIO_NOPULL;
//no pul up or down utilsé
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
//choix de la Vitesse de sortie
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

}
Remarque La fonction Static void MX_GPIO_Init() déjà générée dans la partie 1 sera
utilisée pour écrire toutes les configurations nécessaires.
Nous allons maintenant passer à la fonction Main() pour écrire notre
programme qui inclura la déclaration d'un tableau de 10 éléments, représentant
chaque numéro en hexadécimal
//la déclaration d’un tableux de 10 éléments qui contient les présentation de chaque
numéro en hexadécimal/
char value[10] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//char value[10] ={63,6,91,79,102,109,125,7,127,111}
while (1)
{

short i; //declaration d’un variable short


for(i=0;i<10;i++)
{
//allumer les leds de 7seg
HAL_GPIO_WritePin(GPIOD, value[i], GPIO_PIN_SET);
HAL_Delay(300);delay
//eteindre les leds de 7 seg
HAL_GPIO_WritePin(GPIOD,value[i], GPIO_PIN_RESET);
}
}
Vous pouvez trouver tous les codes cités en haut dans le lien suivant :

https://github.com/Mouad-elatmani/Cortex_M4_STM32
solution des applications par la méthode du
registre
L’IDE utilisée dans cette partie est le KEIL U VISION 5.(voir annexe).
On va répéter toutes les applications faites en méthode graphique mais en utilisant
cette fois les registres
Partie 1 :
Dans cette partie on a 6 leds brancher sur les pins PA1 -PA6, et nous devons
clignoter 3 .
Voici le code de cette partie qui sera divisé en deux partie (configuration des
pins et code principale) :
Configuration des broches :
void GPIO_Init(void){
// définir PA1-PA6 commme sortie
GPIOA->MODER |=(0x1<<2) | (0x1<<4)| (0x1<<6)| (0x1<<8)| (0x1<<10)| (0x1<<12);
GPIOA->MODER &= (unsigned)~(0x1<<3)|(unsigned)~(0x1<<5)|(unsigned)~(0x1<<7)
|(unsigned)~(0x1<<9)|(unsigned)~(0x1<<11)|(unsigned)~(0x1<<13);
GPIOA->OTYPER &=(unsigned)~(0x7F<<1); //configurer les broches comme sortie push-pull
GPIOA->OSPEEDR |= (0x1 <<3) | (0x1 << 5) | (0x1 << 7); // définir le vitesse élevée
GPIOA->OSPEEDR |= (0x1 <<3) | (0x1 << 5) | (0x1 << 7)
| (0x1 << 9)| (0x1 << 11)| (0x1 << 13); // Définir la vitesse
plus élevés}
Alors GPIO_Init est une fonction qui contient les configurations des broches utilisées lors de
nos programme , alors pour le code principal est :
#include "stm32f401xe.h"
void GPIO_Init(void);
void delay_ms(uint32_t ms)
{
uint32_t delay = ms * (SystemCoreClock / 1000); // Convertir le délai en nombre de
cycles d'horloge
while (delay--)
__NOP(); // Boucle de délai en utilisant l'instruction NOP}
int main()
{
GPIO_Init();
while(1){
GPIOA->ODR |= 0x7 << 1; //allumer led avec décalage
delay_ms(500);
GPIOA->ODR &=(unsigned) ~(0x7<<1);//éteindre
GPIOA->ODR |= 0x7 << 4;//allumer
delay_ms(500);//delay
GPIOA->ODR &=(unsigned) ~(0x7<<4);//eteindre
}
}

Application 2:
Dans cette partie on va réaliser un compteur 0-9 avec un afficher 7 seg-cat sur PORT D
de notre microcontrôleur.
Voici le code utilisé pour configurer les broches :
void GPIO_config_D(void){
RCC->AHB1ENR |=0X08; // active l’horloge de du port D
GPIOD->MODER |=0x1555; //PD0-PD6 comme sortie
GPIOD->OTYPER &=(unsigned)~(0x7F);//sortie pull-push
GPIOA->OSPEEDR |=0x2AAA;
}
Alors le code pour réaliser un compteur est :
#include "stm32f401xe.h"
GPIO_config_D();
char value[10] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay_ms(uint32_t ms)
{
uint32_t delay = ms * (SystemCoreClock / 1000); // Convertir le délai en nombre de
cycles d'horloge
while (delay--)
__NOP(); // Boucle de délai en utilisant l'instruction NOP}
int main()
{
GPIO_config_D();
while(1){

for(int i =0;i<10;i++)
{
GPIOD->ODR |= value[i];//allumer leds de 7seg
delay_ms(250);//delay
GPIOD->ODR &=(unsigned) ~(value[i]);//eteindre leds 7segs
}
}
}

Tous les codes précédents sont faits avec un système d’horloge par défauts, mais si
vous voulez définir votre horloge qui dépend de votre application (par exemple
travailler avec une horloge extérieure)
Voici le code suivant :
Ce code configure l'horloge pour utiliser l'oscillateur externe (HSE) et configure le PLL
pour utiliser l'HSE comme source, avec des valeurs de PLLM, PLLN et PLLP définies. Il
vérifie également que l'HSE est prêt à être utilisé et que le PLL est prêt avant de
sélectionner le PLL comme horloge système.
//Active Horologe extern
RCC->CR |= RCC_CR_HSEON;
// attendre que l’horloge soit prêt
while (!(RCC->CR & RCC_CR_HSERDY)); // dans notre cas simulation sur Proteus on a pas besoin de cette
instruction
// configuration de PLL
RCC->PLLCFGR = RCC_PLLCFGR_PLLSRC_HSE | // déterminer HSE comme une source de PLL
(192 << 6) | // PLLM = 8
(4 << 16) | // PLLN = 192
(2 << 27); // PLLP = 4
// Active le register PLL
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY));
// Sélectionner PLL comme source Horloge
RCC->CFGR |= RCC_CFGR_SW_PLL ;
// Wait for PLL to be selected as system clock
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
Donc on peut jouer sur le registres et sélection l’horloge qui répond au besoin de notre application.

Remarque :
Il est important de noter que ces étapes sont très détaillées et nécessitent une bonne
compréhension de la puce STM32F401VE et de ses registres. Il est fortement recommandé de
consulter la documentation du fabricant et de lire le manuel de l'utilisateur pour obtenir des
informations détaillées sur la configuration de l'horloge. Ou bien les configurer avec la méthode
graphique
Application3: Application LED avec Botton d'interruption et

déclencheurs

Maintenant, nous allons aborder une autre application qui concerne les interruptions.
Nous allons d'abord donner une brève introduction sur les interruptions

Introduction
Les interruptions et les déclencheurs dans Cortex-M4 font référence au mécanisme
par lequel le processeur est informé d'un événement et arrête temporairement sa
tâche actuelle pour gérer une demande de haute priorité.
Les interruptions sont des événements asynchrones qui sont générés par des
périphériques externes ou internes, tels qu'un temporisateur ou un périphérique de
communication, et déclenchent le processeur pour appeler une routine de service
d'interruption spécifique (ISR).
L'ISR gère l'événement et renvoie le contrôle au programme principal une fois terminé.
Les déclencheurs sont utilisés pour implémenter les changements de contexte et les
exceptions logicielles.
Le processeur peut également prioriser et gérer l'ordre dans lequel les interruptions
sont traitées.

Le contrôleur d'interruptions vectorisé imbriqué (NVIC) est un module dans


l'architecture du processeur Cortex-M4 qui gère et priorise les demandes
d'interruption.
Il fournit un système d'interruptions hiérarchiques, permettant au processeur de
traiter plusieurs sources d'interruptions et de déterminer la priorité de chaque
demande
Objectif de cette application
Dans cette application, nous allons utiliser Proteus pour mettre en place une
simulation comprenant une LED, un bouton et un microcontrôleur STM32F44O1VE. Le
but est de créer un programme en langage C qui configure une interruption externe et
contrôle l'état de la LED à l'aide d'un bouton.

Configuration dans proteus

Configuration dans CubeMX : PA1 PIN 0 (INPUT) ET PIN 1 (OUTPUT)


Code de Programme en C

#include "GPIO.h"
#include "EXTI.h"

void Toggle_Led_ISR(void); // ProtoType de Fonction Toggle Led


void Led_Button_INIT(void); // ProtoType de Fonction Led Button
//void EXTI_EnableClock(void); // ProtoType de Fonction EXTI_EnableClock
//void EXIT_INIT(char , int, char); // ProtoType de Fonction EXIT_INIT

int main(void) {
EXTI_EnableClock();// Active l'horloge d'interruption externe
EXIT_INIT(0, 0, FALLING);//Configure l'interruption externe à l'aide
de la fonction EXIT_INIT
Led_Button_INIT();// configurer la LED et le bouton.

while(1){
}
return 0;
}

void Toggle_Led_ISR(void){//fonction appelée pour basculer (interrupteur)


l'état d'une LED lorsqu'une interruption est déclenchée.
(*EXTI_PR) |= (0x01 << 0x00); //Effacer le drapeau d'interruption
if (GPIO_ReadPin(0, 1) == 0){ //l'état actuel de la LED Si 0 (eteindre)
GPIO_WritePin(0, 1, 1); //utilisée pour basculer l'état de la
LED en activant ou en désactivant le bit correspondant.
}
else if (GPIO_ReadPin(0, 1) == 1){ // si l'état actuel de la LED 1
(Allume)
GPIO_WritePin(0, 1, 0);
}
}

void Led_Button_INIT(void)//fonction initialise les broches associées à la


LED et au bouton-poussoir.
{
GPIO_EnableClock(0);
GPIO_Init(0, 0, INPUT, PULL_UP);
GPIO_Init(0, 1, OUTPUT, PUSH_PULL);
}

Construire et générer et le fichier Hex


Mettre le fichier hex dans notre mcu dans proteus
Application4: Application Périphérique UART pour la transmission et la réception
de données en série

Introduction
L'USART (Universal Asynchronous/Synchronous Receiver-Transmitter) est un
périphérique couramment présent dans les microcontrôleurs dotés d'un processeur
Cortex M4. Il permet la transmission et la réception de données série entre le
microcontrôleur et un autre appareil, avec la possibilité de fonctionner en mode
asynchrone ou synchrone pour la communication entre microcontrôleurs.

Objectif
Dans cette application , nous allons configurer un microcontrôleur avec un processeur
Cortex M4 (STM32F401) en écrivant un code en C. Ce code initialisera la transmission
de données (une chaîne de caractères "SEAI 2022 !") à travers l'USART de PA2.
Nous pourrons récupérer ces données en utilisant un outil de terminal virtuel dans
Proteus.

Configuration dans Proteus

Code de Programme en C

#include "GPIO.h"
#include "USART.h"
void TRANSMIT_DATA (char *Data); // Prototype de la fonction TRANSMIT_DATA
void TRANSMITTER_PIN_INIT (void); // Prototype de la fonction
TRANSMITTER_PIN_INIT

int main(void) {
//initialise la communication USART avec un débit en bauds de 0x683,
//un mode de transmission, une longueur de mot de 8 bits et un
suréchantillonnage de 16x.

USART_INIT(0x683, TRANSMITTER, 8, 16);

TRANSMITTER_PIN_INIT(); //configure la broche PA2 de l'émetteur, qui


est connectée au module USART
char Data[] = {"SEAI 2022 !"}; //un tableau de caractères chaîne "SEAI
2022 !"
TRANSMIT_DATA(Data); //transmettre la chaîne "SEAI 2022 !"
while(1){}
return 0;
}

void TRANSMIT_DATA (char *Data)


//prend un pointeur vers une chaîne comme argument
//et envoie les données de la chaîne sur le périphérique USART.
{
unsigned char i =0;// Init de compteur pour la lentgh de chaine de
caractere
while(Data[i])//boucle while pour envoyer chaque caractère de la chaîne
un par un.
{
USART_DR = Data[i];//Le caractère est placé dans le registre de
données USART (USART_DR) et la fonction attend la transmission
while (((USART_SR>>6)&1)==0){}//La boucle attend que le drapeau
vide du registre de données de transmission (USART_SR bit 6) soit défini,
indiquant que les données ont été transmises, avant de passer au caractère
suivant.
i++;
}
}

void TRANSMITTER_PIN_INIT (void){


// initialiser les broches GPIO utilisées pour l'émetteur USART.
GPIO_EnableClock(0); //active l'horloge pour le port GPIO A
GPIO_Init(0, 2, ALTERNATE_FUN, PUSH_PULL);//configure la broche 2
comme une fonction alternative avec le type push-pull
(*GPIOA_AFRL) |=0x07 <<8; // La fonction alternative est réglée sur
USART2 sur AF7.
}

Simulation Sur Proteus Isis


ANNEXE
I-Introduction de Keil U Vision IDE :
Keil uVision est un environnement de développement intégré (EDI) conçu pour la programmation de
microcontrôleurs. Il offre une gamme complète de fonctionnalités de développement, y compris l'édition de code,
la compilation, le débogage et la simulation. Keil uVision est utilisé pour développer des applications pour une large
gamme de microcontrôleurs et est particulièrement populaire pour le développement de projets basés sur des
microcontrôleurs ARM.
Dés que vous installez le logicielle , la première fenêtre et comme ce montre la figure :

Maintenant il faut cherchez dans la barre des outils de < pack installer> cette partie nous permettons de
télécharger tous les devices et les bibliothèques que nous allons utiliser.

Après o choisit la famille de microcontrôleur on écrivant leur nom dans la barre de recherche :STM32F401VEHX ,
Une fois la famille ou bien le microcontrôleur télécharger, il faut revenir au keil pour créer le premier projet ,
Cliquer sur <new uvison projet> et sélectionne la série de votre microcontrôleur et cliquer sir ok :

Lorsqu’on clique sur OKI une fenêtre de <manage time environnement> est s’ouvre, dans cette fenêtre on
sélectionne le core et les startups et on clique sur ok :

Maintenant notre projet est créé.


Par la suite il faut créer le fichier .c qui va contenir notre programme développé on cliquant sur <ADD NEW
ITEM > ,et de créer un fichier .c
POURQOUI STM32F401VE ?
On a travaillé avec ce microcontrôleur il donne la possibilité de simuler note programme dans ISIS car a
les même architecture et adressage des registres de STM32F446RE.
Donc le même code s’applique aussi sur laSTM32F446RE.
Cette photo montre la ressemblance entre les adresse de les deux microcontrôleurs
References:
Datasheet de STM32F401x : STM32F401xB/C and STM32F401xD/E advanced Arm®-based 32-bit MCUs - Reference manual
DatasheetSTM32F446xx :
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwin_Y2xt7j8AhXC6aQKHRVVDicQFnoECAk

QAQ&url=https%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Freference_manual%2Fdm00135183-stm32f446xx-advanced-arm-based-32-bit-

mcus-stmicroelectronics.pdf&usg=AOvVaw1xMhfIcYj5KZGwMN-VVjUR

Livres:
Mastering STM32 A step-by-step guide to the most complete ARM Cortex-M platform, using a free and
powerful development environment based on Eclipse and GCC Carmine Noviello
Discovering the STM32 Microcontroller Geoffrey Brown
The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors joseph yiu

Vous aimerez peut-être aussi