NotesCours136 2020
NotesCours136 2020
Programme Professeur
Technologie de systèmes ordinés Pierre Chouinard
1. 1.2
ANALYSE IDENTIFICATION
DU DES RÉSULTATS
DÉSIRÉS
PROBLÈME
1.3
IDENTIFICATION
DES ENTRÉES
NÉCESSAIRES
PROBLÈME
2.1
IDENTIFICATION.
DES ÉTAPES POUR
RÉSOUDRE LE.
PROBLÈME.
ÉCRIRE L'ALGO.
2. 2.2
RÉSOLUTION VÉRIFICATION. DE
DU LA VALIDITÉ DE
L'ALGORITHME.
PROBLÈME JEU D'ESSAI.
tant que
non valide
2.3
CORRECTION
DE
L'ALGORITHME
Exemple (Pseudocode):
DÉBUT
Instruction 1. // Notez l'indentation de 3 espaces et le point
Instruction 2. // terminal des instructions.
FIN. // Notez le point à la fin du bloc
Menu Mouvements.
Menu Temps.
1.1.2. LIRE:
Instruction nous permettant de lire de l'information venant de l'extérieur du microprocesseur.
Par défaut (si rien n'est spécifié), l'information est lue au clavier.
Exemple:
Menu Capteurs
1.1.3. ÉCRIRE:
Instruction permettant d'écrire de l'information vers l'extérieur du microprocesseur.
Par défaut (si rien n'est spécifié), l'écriture se fait à l'écran.
Exemples:
ÉCRIRE "Bonjour". // Affiche à l'écran la suite de caractère "Bonjour".
// Les guillemets (" ") indique que c'est une chaine de
// caractère (suite de caractères) qui sera utilisée.
ÉCRIRE Nom. // Affiche à l'écran le contenu de la variable Nom.
Menu Interaction
Menu Interaction
1.1.4. Affectation ( = ):
Permet de mettre le résultat d'une opération dans un espace mémoire (variable).
Exemples:
TempC = 10. // Affecte la valeur 10 dans la variable TempC.
Menu Mathématique
Autre exemple:
NBoucle = 23.
NBoucle = NBoucle + 1. // On augmente le contenu de NBoucle de 1.
Menu Mathématique
Exemple de programme:
//////////////////////////////////////////////////////////////////
//
// Concepteur: Daniel Côté Date: 31/08/2010
//
// Description: Calcul la superficie d'un terrain en mètres carrés.
//
// En entrée: La longueur et la largeur sont entrées au clavier.
// En sortie: La superficie est affichée à l'écran.
//
//////////////////////////////////////////////////////////////////
DÉBUT
ÉCRIRE "Entrez la longueur du terrain".
LIRE Longueur.
ÉCRIRE "Entrez la largeur du terrain".
LIRE Largeur.
La condition est un test qui donne comme résultat VRAI ou FAUX. Si le test donne VRAI, les
instructions sont exécutées. Si le test donne FAUX, on passe par-dessus les instructions et le
programme se poursuit avec les instructions situées après le FIN SI.
Exemples:
SI ( Temperature > 25 ) // Notez l'opérateur de comparaison >.
Part le ventilateur. // Met 1 à P1_1.
FIN SI.
DEBUT
LIRE Distance au PORT1.
SI (Distance > 250)
Avancer.
FIN SI.
FIN.
F
Opérateurs disponibles avec POB: en C: Menu Logique
Supérieur à: > > V
Supérieur ou égal à: >= >=
Inférieur à: < <
Inférieur ou égal: <= <=
Égal: = ==
Différent: ! !=
Exemple:
SI ( Interrupteur == 1 ) // Notez l'opérateur d'égalité ==.
Allume la lumière.
SINON // Interrupteur à 0.
Éteint la lumière.
FIN SI.
DEBUT
LIRE Distance au PORT1.
SI (Distance > 250)
Avancer.
SINON
Tourner à gauche 90.
FIN SI. F
FIN.
1.1.7. Boucle:
TANT QUE (Condition)
Instruction1.
Instruction2.
FIN TANT QUE. // Fin du bloc.
Très important: La condition doit devenir fausse à un certain moment, car sinon, on boucle à
l'infini.
Généralement, une instruction dans la boucle modifie la condition.
Exemple:
LIRE Touche. // Initialisation de Touche avant le test.
TANT QUE (Touche != 'Q') // Notez le symbole différent de: != .
ÉCRIRE Touche. // 'Q': manière de représenter le code
LIRE Touche. // de la lettre Q en langage C.
FIN TANT QUE.
DEBUT
LIRE Distance au PORT1.
TANT QUE(Distance > 250)
Avancer.
LIRE Distance au PORT1.
FIN TANT QUE.
FIN.
== : Égalité. Vérifie si les deux membres sont identiques. Si c'est le cas, le résultat est VRAI.
SI( Hauteur == 12 )
!= : Différent de. Vérifie si les deux membres sont différents. Si c'est le cas le résultat est VRAI.
ET : Ce mot relie deux conditions. Le résultat sera VRAI si les deux conditions sont VRAI.
Autrement le résultat est FAUX.
OU : Ce mot relie deux conditions. Le résultat sera VRAI si une des conditions est VRAI. Si les deux
conditions sont fausses, le résultat est FAUX.
Exemples:
SI( Heure > 17) // équivalent à: SI( 17 < Heure)
// ou: SI( Heure >= 18 )
SI( Etat == 0) // équivalent à: SI( 0 == Etat)
LIRE Touche.
TANT QUE((Touche != 'Q') ET (Touche != 'q'))
Instructions.
LIRE Touche.
FIN TANT QUE.
- Affectation: =
- Test: <, >, ==, !=, <=, >=, ET, OU, NON
Équivalent en C: && || !
Exercice:
1.2.1. LIRE:
Amène de l'information dans le CPU.
LIRE Variable au Port. // Lire une donnée (8 bits) sur les broches du CPU.
// La donnée est mémorisé dans Variable.
Exemple:
LIRE ConvTemp au Port1. // Le convertisseur pour la température est
// sur le port 1.
LIRE Bit a P3_2. // Lire l'état d'un bit du CPU ( ici c'est le bit 2 du Port3).
Exemple:
LIRE BoutonStart à P1_4. // Le bouton est sur le bit 4 du port 1.
1.2.2. ÉCRIRE:
Sort de l'information du CPU.
ÉCRIRE Variable au Port. // Écrit une donnée 8 bits (contenue dans Variable) sur les
// broches du CPU.
Exemples:
ÉCRIRE VitesseMoteur au Port2. // Le contenu de VitesseMoteur est transmis
// au port2.
ÉCRIRE EtatLed a P3_5. // Transmet la valeur de EtatLed (1 bit: 0 ou 1) sur le bit 5 du Port3.
Problèmes:
Lumière
Voie ferré:
1- Si un train croise un des capteurs, on allume la lumière. La longueur des trains est toujours plus
grande que la distance entre les deux capteurs.
- CapteurOuest est branché sur P3_2. Si on lit 0, le capteur est actif.
- CapteurEst est branché sur P3_4. Si on lit 0, le capteur est actif.
- Lumière est branchée sur P3_5. Un 0 allume la lumière. Un 1 éteint la lumière.
Écrire l'algorithme:
Petite modification: On ajoute un capteur (P3_3) sur le rail au milieu de la route. Ça nous permettra
de détecter une condition erronée CapteurOuest et CapteurEst actif mais pas le
nouveau. Dans ce cas on active une alarme (0 à P3_6).
1.3.1. Nombre.
Un nombre représente une valeur numérique.
Exemple 1: Surface = 8 * 7.
1.3.2. Caractères.
Représente le caractère alphanumérique que nous voulons manipuler.
En fonction du langage de programmation utilisé, des outils vont nous permettre de manipuler les
différents types de données.
2. Introduction au langage C
En langage C, chaque algorithme sera transformé en fonction. Un programme est formé d'une ou de
plusieurs fonctions. Il y a au moins une fonction obligatoire en C. C'est la fonction main( ).
Équivalence:
Pseudocode C
//Principal void main(void)
DÉBUT {
// Instructions. // Instructions.
// Instructions. // Instructions.
FIN. }
Équivalence:
Pseudocode C
SI( Test) if(Test)
{
// Instructions. // Instructions.
// Instructions. // Instructions.
FIN SI. }
2.1. LIRE:
LIRE Touche. Touche = getchar(); // Keil (stdio.h)
La fonction getchar( ) fait partie de la définition de base du C. Elle est présente sur tous les
compilateurs.
getchar( ): Attend qu'une touche soit pesée au clavier. Une fois la touche pesée, la fonction retourne
le code ASCII de la touche et l'affiche à l'écran.
Code ASCII: Code numérique donné à chaque caractère afin de pouvoir le traiter dans les ordinateurs.
Faites une recherche sur Internet avec "Table ASCII".
Pour atteindre les différents codes il faut avoir la bonne configuration de clavier sur le PC ou encore
utiliser la touche 'Alt' de gauche et entrer le code décimal du caractère avec le pavé numérique.(démo)
Si je pèse sur la touche 'A' , que contient la variable Clavier? ( 'A' ou 0x41 ou 65 )
En fait c'est tout ça à la fois. Ça dépend de ce qu'on veut représenter. En TSO nous utiliserons
surtout la valeur en hexadécimal (0x41) ou encore la représentation du caractère ('A').
Exemple:
Pseudocode C
LIRE température. Temperature = getchar( );
2.4. ÉCRIRE:
Pseudocode C
ECRIRE "Message" printf("Message"); // (stdio.h)
La fonction printf( ) affiche à l'écran tout ce qui est entre les guillemets.
ECRIRE Température printf("%d", Temperature); // %d format d'affichage
// entier décimal.
printf("%f", Temperature); // %f en point flottant.
L'utilisation du symbole %, permet d'afficher le contenu d'une variable avec le format voulu. Si on
veut afficher % il faudra le mettre deux fois dans les guillemets ("%%").
2.4.1. Liste des principaux formats que vous utiliserez avec printf( )
Format Description:
%d Nombre entier 16 bits (négatif ou positif). %bd 8 bits
%f Nombre à point flottant.
%c Caractère correspondant au numéro du code ASCII fournit.
%x Nombre hexadécimal (lettre en minuscule a,b,c,d,e,f ). %bx 8 bits
%X Nombre hexadécimal (lettre en majuscule A,B,C,D,E,F). %bX 8 bits
%#X Ajoute 0x devant le nombre hexadécimal. (petit bug si 0)
%s Chaine de caractères.
%u Nombre entier 16 bits non signé (positif seulement). %bu 8 bits
Exemples:
Pseudocode C
ÉCRIRE "La moyenne est: ".
ÉCRIRE Moyenne. printf("La moyenne est: %f", Moyenne);
ÉCRIRE 'C'. printf("%c", 'C'); ou printf("%c", 0x43);
ou printf("C");
ÉCRIRE Nom. // Nom: chaine. printf("%s", Nom);
ÉCRIRE 12.26. printf("%5.2f", 12.26); ou printf("12.26");
Instructions Affichage
fValeur = 23.17;
printf("Valeur = %f", fValeur); Valeur = 23.170000
printf("Valeur = %4.2f ", fValeur); Valeur = 23.17
printf("Valeur = %5.2f ", fValeur); Valeur = 23.17
printf("Valeur = %7.2f ", fValeur); Valeur = 23.17
printf("Valeur = %07.2f ", fValeur); Valeur = 0023.17
iHeure = 8; iMin = 24; iSec = 7;
printf("Time = %d:%d:%d",iHeure,iMin,iSec); Time = 8:24:7
printf("Time = %2d:%2d:%2d",iHeure,iMin,iSec); Time = 8:24: 7
printf("Time = %02d:%02d:%02d",iHeure,iMin,iSec); Time = 08:24:07
printf("\nPort 3 = %02bu", P3); Port 3 = 207
printf("\nPort 3 = 0x%02bX", P3); Port 3 = 0xCF
Les notions de lecture et d'écriture à une adresse en C, seront vues dans votre prochain cours de C à
l'hiver prochain.
Le deuxième type de commentaire sera utilisé pour soustraire une partie de notre programme à la
compilation. Ce sera utile pour isoler les problèmes. Ce type de commentaire commence par la barre
oblique suivit de l'étoile. Il se termine lorsque le compilateur trouve une étoile suivit de la barre
oblique.
Exemple:
if ((fThermo < 25.0) || (fThermo > 35.0)) // Erreur?
{
cCloche = 0; // Active Cloche.
printf("\nCorrigez la temperature.\n");
}
/* else // OK (25 <= Temp <= 35).
{
cCloche = 1; // Desactive Cloche.
}
*/
Le bloc "else" ne sera pas compilé car il est entre les marques de commentaires: /*.....*/.
Exemple tiré d'un projet étudiant qui contrôlait un simulateur de maison. Si on pesait sur le
bouton de la lumière pendant 2 secondes, on tombait dans le mode d'affichage de l'heure sur les
7 segments qui affiche normalement la température. L'heure était affichée durant 3 secondes, les
minutes durant 3 secondes, ensuite on réaffiche la température et le bouton lumière redevient
fonctionnel.
Notez l'absence d'accent: Certains compilateurs sont sensibles aux lettres accentuées. Les problèmes
peuvent être simplement un affichage de drôles de caractères ou pire une
erreur de lecture du compilateur, alors vos programmes ne seront pas
compilés.
2.8. Entêtes:
Les commentaires seront aussi utilisés pour expliquer le fonctionnement d'un programme ou d'une
partie de programme. Pour la première session ce sera la description de vos programmes qui sera
inclus dans l'entête.
///////////////////////////////////////////////////////////////////////////////
//
// Fichier: LAB9.C
//
// Description: - Programme du laboratoire #9 du cours 247-215.
// - Ce programme permet de lire et d'afficher, a l'ecran du PC,
// l'etat du simulateur de maison.
// - On peut aussi controler certains elements tel:
// - L'etat des lumieres.
// - La temperature de consigne de chaque piece.
// - On peut modifier l'heure, les minutes et les secondes.
//
// Programmeur: Daniel Cote
//
// Date: 19/11/00
//
// Compilateur: Borland C 3.1
//
// Modification:
// 17/05/01: Corrige l'erreur pour la modification des minutes.
// 19/05/01: Enleve la boucle qui bloquait le programme lorsque
// le simulateur n'etait pas branche. Remplacer par un
// simple test.
///////////////////////////////////////////////////////////////////////////////
Parfois l'entête occupe plus de place que la section de programme qu'elle décrit. Ceci permet aux
personnes consultant le programme de comprendre le fonctionnement du programme, sans
nécessairement connaitre le langage de programmation.
Voici un exemple tiré du même programme de contrôle du simulateur de maison. C'est l'entête de la
section qui s'occupe de l'affichage sur les 7 segments de chaque pièce.
En langage C nous aurons besoin d'opérateur pour nous permettre d'effectuer nos tests avec des ET et
des OU.
Équivalence:
Algo C
ET && // Le ET logique. Permet
// de joindre deux tests.
SI((Touche == 0x0A) ET (Temp > 28)) if((iTouche == 0x0A) && (iTemp > 28))
OU || // Le OU logique. Permet de
// choisir un test ou l'autre.
Exemples: Trouvez le test pour partir un moteur si la température est supérieure à 40 degrés ou si un
bouton est pesé.
SI((Temp > 40) OU (Bouton == 1)) if((fTemp > 40) || (iBouton == 1))
Trouvez le test pour vérifier si le niveau maximum est atteint et si le moteur de la pompe
est en marche.
SI((Niveau > MAX) ET (Pompe == ON)) if((fNiveau > MAX) && (iPompe == ON))
Nombre binaire:
La plus petite unité d'information dans un ordinateur se nomme le "BIT".
Elle peut prendre deux valeurs, 0 ou 1.
Le BIT n'est pas très pratique si on le prend tout seul (seulement 2 valeurs). On a donc choisit de
prendre des groupes de bits. On va appeler ces groupes des MOTS. Le nombre de bits dans le mot
détermine sa longueur. Exemple un mot de 8 bits, un mot de 12 bits etc…
Nom de mots spéciaux: 8 bits Octet (byte) Le plus connu des mots.
16 bits Mot 16 bits (word)
4 bits quartet (nibble)
Bases de numération (binaire, hexadécimal, décimal):
- Un nombre binaire est représenté par l'état 0 ou 1 de plusieurs bits.
Exemple: 101100
Un nombre binaire est formé d'un polynome: (…. a4*24 + a3*23 + a2*22 + a1*21 + a0*20)
Les coefficients "ax" peuvent prendre la valeur 0 ou 1.
Exemple précédent:
101100 = 1*25 + 0*24 + 1*23 + 1*22 + 0*21 + 0*20
= 32 + 0 + 8 + 4 + 0 + 0
= 44 décimal.
Résultat: 1 0 0 1 0 1
149: ________________________
231: ________________________
2.13. Hexadécimal.
Représentation d'un nombre binaire pris quatre bits à la fois (quartet).
Exemple (1101110110):
1 1 / 0 1 1 1 / 0 1 1 0
3 7 6 Donc: 0x376
Exemple (101101011100):
1 0 1 1 / 0 1 0 1 / 1 1 0 0
B 5 C Donc: 0xB5C
Exemple (0x198):
0x 1 9 8
0001 1001 1000 Binaire
Exemple (0x7EB6):
0x 7 E B 6
0111 1110 1011 0110 Binaire
Faire l'exercice.
• Les opérateurs binaires sont utilisés pour modifier un ou plusieurs bits à la fois.
• On les utilisera aussi pour isoler un groupe de bit.
• Ces opérateurs sont utilisés entre deux opérandes (données).
• Un des opérandes est souvent appelé un masque.
• L'exécution de l'opérateur s'effectue entre chaque bit des deux opérandes.
• L'opérateur ET ( & ) est souvent utilisé pour mettre des bits à 0 ou pour isoler un groupe de bits.
• L'opérateur OU ( | ) est souvent utilisé pour mettre des bits à 1.
• L'opérateur OU-Exclusif ( ^ ) est souvent utilisé pour changer l'état des bits.
ET:
Exercices:
cResultat = 0x0F & 0xF0; // cResultat = _________________________
OU:
Exercices:
cResultat = 0x0F | 0xF0; // cResultat = _________________________
OU Exclusif:
0xF0 → 1111 0000 (Donnée)
^ ^
0x11 → 0001 0001 (Masque, le OU EX change l'état des bits)
------------------- (à l'endroit où le masque a des 1.)
Résultat: 1110 0001
Exercices:
cResultat = 0x0F ^ 0xF0; // cResultat = _________________________
ET: F 0 A C
0xF0AC →1111 0000 1010 1100 (Donnée)
& &
0x93F6 → 1001 0011 1111 0110 (Masque, le ET met les bits à 0)
-------------------
Résultat: 1001 0000 1010 0100
En C: iResultat = 0xF0AC & 0x93F6; // iResultat = 0x90A4
OU: 8 7 9 2
0x8792 → 1000 0111 1001 0010 (Donnée)
| |
0x7349 → 0111 0011 0100 1001 (Masque, le OU met les bits à 1)
-------------------
Résultat: 1111 0111 1101 1011
OU Exclusif: B 4 C E
0xB4CE → 1011 0100 1100 1110 (Donnée)
^ ^
0x01F9 → 0000 0001 1111 1001 (Masque, le OU EX change l'état des bits)
------------------- (à l'endroit où le masque a des 1.)
Résultat: 1011 0101 0011 0111
if( (P1 & 0x38) == 0x38) // Vérifie si les bits 3,4 et 5 du Port1 sont à 1.
if( (P1 & 0x38) != 0x38) // Vérifie si un des bits 3,4 ou 5 est à 0.
if( (P1 & 0x38) == 0x00) // Vérifie si les bits 3,4 et 5 sont à 0.
printf("Etat du bit P3.0: 0x%bX", P3 & 0x01); // Valeurs possibles: 0x0 ou 0x1
printf("Etat du bit P3.6: 0x%bX", P3 & 0x40); // Valeurs possibles: 0x0 ou 0x40
SW3
Le niveau '0' sera amené sur la broche du port par P1.6
Attention: Pour que ce circuit fonctionne, il faut que les bits du port soient en entrées. La plupart des
microprocesseurs placent leurs ports en entrées au démarrage. Pour placer un bit de port en
entrée il s'agit souvent de mettre tout simplement un '1' sur le bit du port.
Quelquefois, il faut écrire dans un registre de direction du microprocesseur pour indiquer que
le bit est en entrée. Voir les conditions de reset du DS89C450 page 34.
Pour la résistance de Pull-Up, certains microprocesseurs en ont une interne. Parfois, elle est toujours
active et pour d'autres processeurs, il faut l'activer. Voir les caractéristiques des ports page 35.
Si on a plusieurs Pull-Up à placer sur un port, il peut être intéressant d'utiliser des résistances montées en
ligne (SIP Single Inline Package).
VCC
1
R4
RESISTOR SIP 8
8
7
6
5
4
3
2
Lire un port: La lecture du port se fait si le nom du port est dans une expression (souvent à droite du =).
Pseudocode: en C:
LIRE Port à P2. Port = P2; // Lecture du port P2.
ECRIRE P2. printf("Port2 = %02bX", P2); // Affiche P2 en hexa.
Bit0Port2 = P2 & 0x01. Bit0Port2 = P2 & 0x01; // Bit0Port2 vaut 0 ou 1.
Bit3Port2 = P2 & 0x08. Bit3Port2 = P2 & 0x08; // Bit3Port2 vaut 0 ou 8.
Bit6Port2 = P2 & 0x40. Bit6Port2 = P2 & 0x40; // Bit6Port2 vaut 0 ou 0x40.
→ En fait, on a qu'à mettre le nom du port dans une expression et le port sera lu.
Par exemple on veut lire les trois interrupteurs de la page précédente (P1.4 à P1.6). R1 R2 R3
2k2 2k2 2k2
uProc
Il s'agit ici de modifier le masque pour englober les trois bits.
SW1
P1.4
Pseudocode: en C:
Sw = P1 & 0x70. Sw = P1 & 0x70; // Lecture Switch sur P1.
Vérifier si un des interrupteurs a été pesé, il y aura alors au moins un 0 dans les trois.
SI((Sw & 0x70) != 0x70) if((Sw & 0x70) != 0x70) // Un interrupteur pesé?.
Écriture sur les ports. L'écriture sur un port se fait quand le nom du port est à gauche du signe égal.
VCC
Exemples (avec le port 2):
P2 = 0xEF; // Met P2.4 a 0 et les autres bits a 1. R5
470
P2 = P2 & 0xEF; // Met P2.4 a 0, les autres sont inchangés.
P2.4
Souvent nous utiliserons une variable pour mémoriser l'état du port, surtout si le port est
modifié à plusieurs endroits dans le programme.
1
1 2 27 37 D0 D0 2 19 A0
ALE ALE/P P0.0/AD0 36 3 D1 Q1 18
R1-2 D1 D1 A1
4K7 P0.1/AD1 35 D2 D2 4 D2 Q2 17 A2
4
4K7 P0.2/AD2 34 D3 D3 5 D3 Q3 16 A3
EA P0.3/AD3 33 D4 D4 6 D4 Q4 15 A4
2
5 6 29 P0.4/AD4 32 D5 D5 7 D5 Q5 14 A5
EA/VP P0.5/AD5 31 D6 D6 8 D6 Q6 13 A6
U1-3B P0.6/AD6 30 D7 D7 9 D7 Q7 12 A7
74HC125 P0.7/AD7 D8 Q8
18 A8 11
P2.0/A8 19 ALE 1 G
A9
P2.1/A9 20 A10 OC
P2.2/A10 21 A11 74HC573
10
P2.3/A11 22 A12
PSEN P2.4/A12 23 A13
9 8 26 P2.5/A13 24 A14
PSEN P2.6/A14 25 A15
U1-3C P2.7/A15
74HC125
A[0..15]
A[0..15]
5
13
1 2 18p P1.2/RXD1 43 8 8
P1.3/TXD1 44 P1.3 P1.7 9 P3.7/*RD 9
Y 1-1 P1.4
2
11.059MHz P1.4/INT2 1 10 10
10u P1.5/INT3 2 P1.5
R1-4 C1-3 P1.6 HEADER 10 HEADER 10
2
1 2 14 P1.6/INT4 3
S1-2 P1.7
1 1K XTAL2 P1.7/INT5
2 18p DS89C450
1
SW SPDT
RUN/PROG
VCC VCC VCC VCC
1
1
R1-5 R1-6 R1-7 R1-8
4K7 4K7 4K7 1K
S1-3 S1-4 S1-5 D1-1
2
2
1 2 1 2 1 2 2 1
P3.2 P3.3 P3.4 P3.5
PTS645SL43 PTS645SL43 PTS645SL43
SML-LX1206SRC-TR
CIRCUIT VCC GND
Conception : Alain Champagne
VCC VCC VCC MT1-1 MT1-2
DS89C450 6,38 16,17,28,39 Title
1
74HC573 20 10 A DallasSMT.DSN A
R≈40Ω
Pin 1.x
Quel serait la tension en sortie si je place une résistance de 1K au Gnd? V1K ?
5𝑉 1K
𝑉1𝐾 = (10𝐾+1𝐾) × 1𝐾 = 0.45 Volts Ce n'est pas un beau niveau 1!
Pin 1.x I?
Quel serait le courant dans la Led avec le branchement suivant?
2V
5𝑉−2𝑉 LED
𝐼=( ) = 0.3 ma La Led ne sera pas trop brillante!
10𝐾
Conclusion: Avec le Dallas, nous ne pouvons pas activer, avec un '1', des éléments qui demandent
beaucoup de courant.
Vout = 21.4 ma * 40Ω = 0.856 Volts C'est trop haut pour un niveau 0!
Conclusion: Pour le Dallas, avec un '0' en sortie nous allons limiter le courant à 8ma.
La documentation de Dallas nous demande de ne pas dépasser 10ma pour les 8 bits d'un
port (ce que nous ferons mais ce n'est pas garantie).
Structure des programmes utilisant une boucle de délai pour ralentir le programme afin de nous
permettre de visualiser des phénomènes externes (exemple: Led qui clignote).
void main(void)
{
unsigned int uiDelai = 0; // Si non modifiee dans le pgm, aucun delai.
unsigned int uiDelaiIn;
unsigned int uiDelaiOut;
while(1)
{
// Lecture des entrees. // On met la valeur des ports dans des variables.
// Exemple: ucPort1 = P1;
// Ecriture des resultats. // On met la valeur des variables dans les ports.
// Exemple: P1 = ucPort1;
// Delai
uiDelaiOut = 0;
while (uiDelaiOut < uiDelai) // Boucle de uiDelai millisecondes.
{
uiDelaiOut++;
uiDelaiIn = 0;
while(uiDelaiIn < 613) // 613: Valeur trouvee de maniere experimentale
{ // pour avoir 1 milliseconde par boucle
uiDelaiIn++; // avec un DS89C4xx a 11.059 MHz.
}
}
} // Fin while(1).
} // Fin main.
À ce jour, nous avons toujours utilisé les types "int" et "float". Pour nos besoins, ces types de données
suffisaient. Le langage C, est un langage près du matériel (électronique). Il est optimisé pour une utilisation
efficace du code. C'est pourquoi il est très utilisé dans des environnements où les ressources matérielles
sont limitées. Par exemple, dans plusieurs microcontrôleurs l'espace mémoire est relativement faible (128
octets de RAM par exemple). Il est donc important d'utiliser le bon type de donnée en fonction des besoins,
afin de ne pas gaspiller des bits qui sont si précieux.
Par exemple, si nous utilisons toujours des variables entières pour mémoriser l'état d'un bit (0 ou 1), on perd
beaucoup d'espace à chaque fois, car un entier (int) est à 16 bits. Il existe en C, des types de donnée moins
gourmands en espace mémoire.
Plusieurs types de donnée sont standard en C et d'autres sont spécifiques au compilateur utilisé.
* Le type "int" peut être à 32 bits dans certains environnements. Pour être sûr d'avoir une
variable à 16 bits, il existe le type "short".
Regardons le type "char". C'est un type à 8 bits donc 28 = 256 possibilités (-128 à +127)
Le huitième bit est à zéro. Si ce bit devient 1, nous aurons un nombre négatif. On dit alors que le bit le plus
significatif est le bit de signe. Les nombres négatifs sont codés en complément à deux. Nous verrons ce
codage dans un cours ultérieur. Sachez pour l'instant que 0000 0000 – 0000 0001 = 1111 1111 = -1.
S'il existe des types de variables avec un signe, il existe aussi des types non signés (toujours positif).
Voici les principaux:
Le type à 8 bits est particulièrement intéressant pour nous. La plupart des registres du processeur sont à 8
bits (exemple les ports). Donc le type "unsigned char" sera très utilisé dans nos programmes.
Le type "unsigned int" sera souvent utilisé comme indice de boucle ou pour faire des calculs d'entier avec
de petites valeurs positives.
Finalement, le type "float" sera utilisé exclusivement pour des calculs nécessitant la partie décimale. Ce
genre de donnée demande beaucoup de ressource du processeur. Les calculs utilisant les points flottants
demandent beaucoup de temps et d'espace mémoire. Dans la mesure du possible évité l'emploi du type
"float" pour de petits processeurs.
À partir de maintenant, nous devrons identifier le type de la variable dans le nom de la variable. Il sera
alors, plus facile de vérifier nos programmes. La manière de procéder est simple. Il s'agit de mettre un
préfixe à nos variables. Ce préfixe identifiera le type de donnée.
Cas particulier (compilateur pour les processeurs de la famille Cx51, comme Keil)
Ces compilateurs ont été optimisés pour tenir compte de l'architecture interne des microcontrôleurs de la
famille 8051. Ces processeurs ont des registres spéciaux nommés les SFR (Special Fonction Registers).
Ces registres sont placés dans le processeur à des adresses spécifiques. Pour y accéder, il faudra utiliser le
type "sfr". C'est un type non standard en C.
Avec ces déclarations, le compilateur sait que les variables P0, P1, P3 et PCON sont situés à l'intérieur
d'une zone spéciale du processeur.
Un autre type qui nous sera très utile est "sbit". Avec ce type on peut accéder à un seul bit à la fois, dans
certaines zones du processeur. Les ports font partie de cette zone. Donc, si on place les déclarations
suivantes au début de notre programme (ça peut être dans un fichier .h) nous pourrons accéder
individuellement à chaque bit du port 1 (exit les masques!).
// P1 a l'adresse 0x90
sbit P1_7 = 0x97;
sbit P1_6 = 0x96;
sbit P1_5 = 0x95;
sbit P1_4 = 0x94;
sbit P1_3 = 0x93;
sbit P1_2 = 0x92;
sbit P1_1 = 0x91;
sbit P1_0 = 0x90;
Exemple d'utilisation en C:
Pour terminer, voici les types disponibles avec Keil. Certains ne sont pas standards en C.
Comme nous l'avons déjà vu, il y a plusieurs types de donnée en C (char, int, float, unsigned char, etc.).
Pour chacun de ces types correspond un ensemble de valeur fixe que l'on appelle constantes.
Constantes entières:
On peut les définir dans plusieurs formats correspondant à différentes bases de codage de nombre.
Base hexadécimal: C'est la base 16 (0 à 9, a,b,c,d,e,f (minuscule ou majuscule)), format qui nous sera
utile lorsque l'on voudra représenter des éléments plus près de la machine. On peut
distinguer un nombre hexadécimal d'un nombre décimal par le fait qu'il est précédé
par 0X ou 0x.
Note: On retrouve également la base octale mais elle est de moins en moins utilisée. Vous pourrez
consulter un ouvrage de référence pour obtenir plus d'information.
Constantes flottantes:
Notation littérale:
Exemple.: 12.3456
Notation scientifique :
Exemple.: 1.23456 e1
Constantes caractères:
Il existe aussi, un ensemble de caractères spéciaux que l'on nomme caractères de contrôle qui évite
d'avoir à indiquer la valeur numérique du code ASCII.
En C, il est possible d'associer un nom à une constante avec la commande au préprocesseur: #define
Exemple:
void main(void)
{
int iBoucle = 0;
Avec l'utilisation de la constante DELAI, il est possible de modifier le délai dans tout le programme en
modifiant seulement la définition de la constante au début du programme.
Dans les faits le compilateur, lorsqu'il rencontre une constante, remplace le nom en majuscule par la
valeur qui a été définie au début du programme.
D.C. 42 Cours 247-136 Programme de TSO
03-09-2020 NotesCours136_2020.docx
Notes de cours Analyser le Fonctionnement de Circuits Numériques 247-136
Jusqu'à maintenant, nous ne nous sommes pas trop souciés de la vitesse d'exécution de nos
programmes (hormis les délais pour les DEL). Lors de la lecture des boutons, nous testons si le bouton
est pesé ou non. Cependant, il arrive fréquemment que nous ne voulons pas agir tant que le bouton est
pesé, mais seulement au moment où le bouton est pesé.
Voici le niveau électrique à l'entrée du port 3, bit P3_4, lorsque le bouton de votre kit est pesé.
5Volts
Ce qui nous intéresse, lors de la détection des changements, ce sont les transitions (descente ou
montée). Elles sont indiquées par des flèches sur le dessin. On va souvent parler de front.
Pour faire réagir notre programme seulement lors des transitions, il faut être en mesure de détecter ces
fronts. Pour y arriver, il faut connaître l'état actuel du bouton et l'état du bouton avant la dernière
lecture. Si les deux valeurs sont identiques, alors il n'y a pas eu de changement. Cependant, si les deux
valeurs diffèrent, nous pourrons conclure à un changement.
Pour mémoriser l'ancienne valeur du bouton, nous aurons donc besoin d'une variable. Cette variable
sera initialisée au début du programme avec la valeur du bouton au début.
Exemple avec un bouton servant à la remise à zéro d'un compteur (branché sur P3_4):
Pour détecter un changement il nous reste à vérifier si ucAncienEtat est différent de la valeur actuel du
bouton.
Exemple:
Nous avons donc détecté un changement. Nous ne savons toutefois pas si c'est une transition montante
(on a relâché le bouton) ou une transition descendante (on vient de peser sur le bouton).
La valeur de ucBoutonMarche nous donne cette information. Si ucBoutonMarche est à 1, alors c'était
un front de montée (on a relâché le bouton) sinon (ucBoutonMarche est à 0) on vient de peser sur le
bouton. Pour vérifier le type de transition, il faut simplement ajouter le code suivant dans le if( ).
Lorsque l'on pèse sur un bouton, il se produit un phénomène mécanique qui se nomme le
rebondissement. Il s'agit d'un mouvement oscillatoire des contacts de l'interrupteur. Il s'en suit une
série de contact/non-contact de l'interrupteur.
Si on regarde au niveau électrique (phénomène amplifié):
5Volts
0Volt
Bouton pesé Bouton relâché
On remarque sur cette forme d'onde que plusieurs transitions se produisent lorsqu'on pèse ou relâche
le bouton. Donc même avec la technique de détection des changements, nous allons voir plusieurs
changements alors qu'il ne doit y en avoir qu'un seul.
Voir page suivante pour Bouton réel.
Il existe plusieurs moyens pour résoudre le problème. Les techniques peuvent être matériel (ajout
d'une bascule, ajout d'un condensateur, utilisation de bouton de meilleure qualité, etc…) ou logiciel.
Pour résoudre le problème de manière logiciel, on a besoin de savoir que ces oscillations durent en
général moins de 10ms. Donc, au moment de la détection du front, on ajoute un délai de 10 ms avant
de continuer le programme. Ensuite si le programme revient voir l'état du bouton, il sera stabilisé.
0.1 ms/div
5V
1 V/div
0V
Donnée
1 2
Commande 1 Commande 2
Rép: À 60Hz on ne voit plus le clignotement des lumières. 60Hz = 1 / T où T est la période.
T = 1/60 = 0.0166 sec ou 16.6 ms
Procédure:
Il faudra aussi trouver la durée nécessaire d'affichage pour que l'œil puisse mémoriser l'information.
Un peu plus difficile à trouver, mais si on se rappelle qu'à 16.6 ms l'œil n'y voit que du feu, il faudra
être plus lent.
Avec au moins 200 ms entre deux informations différentes (on change la Donnée 1 et la Donnée 2)
l'œil commence à percevoir les données.
D.C. 46 Cours 247-136 Programme de TSO
03-09-2020 NotesCours136_2020.docx