Le type de gestion d'entrées/sorties le plus simple à gérer pour un
microcontrôleur consiste à utiliser directement des niveaux logiques
'0' ou '1'. En effet, l'exploitation des niveaux
logiques ne nécessite aucune transformation du signal.
Dans cet exemple, on utilise la carte MSC1210 EValuation Module. On utilise un bouton poussoir et deux diodes électroluminescentes (LED) dont le câblage est fixé comme suit :
Tableau 10. Entrées/Sorties un bit MSC1210EVM
| Type | Désignation | Broche microcontrôleur |
|---|---|---|
| Entrée | Bouton poussoir SW2 | P3.2 |
| Sortie | LED rouge | P3.4 |
| Sortie | LED jaune | P3.5 |
Exemple 15. Programme d'illustration des entrées/sorties logiques sur un bit
Voici un programme «minimaliste» d'illustration du fonctionnement des entrées/sorties sur un bit : sdcc_ttl_1bit.c. À chaque appui sur le bouton poussoir, on allume la LED rouge. Tous les quatre appuis sur le même bouton poussoir, on allume la LED jaune.
01: #include <stdio.h>
02: #include <msc1210.h>
03: #include "ser_msc1210.h"
04:
05: __sbit __at (0xb2) IN_SW2; // p3.2
06: __sbit __at (0xb4) OUT_RED; // p3.4
07: __sbit __at (0xb5) OUT_YELLOW; // p3.5
08:
09: void putchar(char c) {
10: ser_putc(c);
11: }
12:
13: bit antirebond() {
14: unsigned char i = 0;
15: unsigned int j = 0;
16: bit sw_now = 1, sw_previous = 1;
17:
18: while (i < 5) {
19: sw_previous = IN_SW2;
20: // Boucle de temporisation
21: for(j = 0; j < 8000; j++)
22: ;
23: sw_now = IN_SW2;
24: if (sw_now == sw_previous)
25: i++;
26: }
27:
28: return sw_now;
29: }
30:
31: void main(void) {
32:
33: unsigned char c, i = 0;
34: bit sw;
35:
36: /* Appuyer sur Entrée pour ajuster automatiquement
37: * le débit sur la liaison série */
38: autobaud();
39: EA=1;
40:
41: puts("Lecture SW2/Ecriture LED");
42: putcr();
43: while (1) {
44: if (sw = antirebond())
45: OUT_RED = 1;
46: else {
47: OUT_RED = 0;
48: if (++i % 4)
49: OUT_YELLOW = 1;
50: else
51: OUT_YELLOW = 0;
52: }
53: c = sw + 0x30;
54: putchar(c);
55: putchar('\r');
56: }
57: }
En fonction du tableau donné ci-dessus
on affecte les noms d'entrées/sorties à l'aide des directives du
compilateur. Ici, la directive __sbit __at (0xb2) IN_SW2;
affecte le nom IN_SW2 au bit accessible à l'adresse
0xb2. Cette adresse correspondant au troisième bit du port
numéro 3 du microcontrôleur : P3.2.
Une fois ces affectations en place, on utilise les noms d'entrées/sorties de la même façon que des variables.
Comme avec n'importe quel type de variable, il faut respecter les
espaces de représentation mémoire des entrées/sorties. Dans l'exemple, on a
désigné des entrées/sorties de type bit. Il n'est donc pas
question de placer le contenu d'une variable qui occupe plus d'un bit sur
une sortie de type bit. À l'inverse, le transtypage
automatique offert par le langage C permet très bien de stocker un bit dans
une variable dont l'occupation mémoire est plus grande. À la ligne
ligne 53, on place le bit sw dans
c qui est une variable de type
character dont l'espace de représentation est l'octet.
Voir la Section 7.3, « Types de représentation des données ».
Comme l'exemple d'illustration propose de compter les appuis sur le bouton poussoir, il est nécessaire de se préoccuper des «rebonds». Lors d'un appui manuel sur le contact électrique du bouton poussoir, une suite d'impulsions transitoires est transmise. Ces impulsions parasites sont communément appelées rebonds.
La fonction présentée ici utilise une boucle de temporisation (lignes
20 à 22). L'emploi de ce type de boucle doit être évité au maximum mais le
bouton poussoir de la carte MSC1210 EValuation Module
a été câblé directement sur la broche P3.2 du
microcontrôleur sans cellule RC de filtrage des rebonds.
Le compteur i sert à contrôler que l'on a lu 5
fois le même état entre chaque temporisation.
La condition d'appel au corps de la boucle tant que
while (1) est toujours vraie. Il s'agit donc d'une boucle
infinie. Seule la ré-initialisation du microcontrôleur peut interrompre le
programme.
Sans appui sur le bouton poussoir, la fonction
antirebond() renvoie un bit à 1. On éteint alors la
LED rouge en envoyant un niveau 1 sur la broche P3.4 du
microcontrôleur : OUT_RED = 1;.
Lors d'un appui sur le bouton poussoir, la fonction
antirebond() renvoie un bit à 0. On allume alors la
LED rouge en envoyant un niveau 0 :
OUT_RED = 0;.
C'est aussi lors d'un appui sur le bouton poussoir que l'on
incrémente le compteur i. On teste ensuite si le reste
de la division entière de i par 4 est nul. Si la
condition est vérifiée, on allume la LED jaune. Ce
codage permet d'allumer la LED jaune tous les quatre
appuis sur le bouton poussoir.
L'évaluation des conditions des lignes 44 et 48 utilise directement
les résultats numériques des expressions codées avec l'instruction
if-else. Si l'expression renvoie la valeur 0, c'est que le
test est faux. Voir Une condition fausse vaut toujours 0.
Pour afficher l'état de l'appui sur le bouton poussoir sur la console
du système de développement via la liaison série, il est nécessaire de
transformer le bit lu en un code ASCII. Sachant que le
code ASCII du chiffre 0 est
0x30, il suffit d'ajouter la valeur du bit à ce code pour
afficher les caractères '0' ou '1'
sur la console.
Comme la scrutation de l'état du bouton poussoir est continue, on
envoie le code ASCII de retour en début de ligne
'\r' après chaque affichage de la valeur du bit d'état.
De cette façon, on évite de remplir l'écran de la console et l'affichage
est donc plus lisible.
Dans cet exemple, on utilise la carte du département Génie Électrique de l'IUT 'A' Paul Sabatier. Relativement à la carte MSC1210 EValuation Module, cette carte offre une extension sur les entrées/sorties logiques.
L'utilisation du port P0 a été «étendue» en utilisant deux sorties du port P3 comme signaux de contrôles. Ces bits de contrôle servent à sélectionner un composant chacun : un pour les entrées et un pour les sorties. De plus, deux bits supplémentaires des ports P3 et P1 ont été alloués comme entrées et sorties. Le schéma ci-dessous montre que l'on dispose de 10 entrées et 10 sorties logiques.
Exemple 16. Programme d'illustration des entrées/sorties logiques sur plusieurs bits
Voici un programme d'illustration du fonctionnement des entrées/sorties sur plusieurs bits : sdcc_ttl_io_iut.c. Il propose un menu qui permet de lire ou écrire 10 bits simultanément ainsi que la lecture ou l'écriture d'un bit individuel parmi 10.
01: #include <stdio.h>
02: #include <stdlib.h>
03: #include <msc1210.h>
04: #include "ser_msc1210.h"
05: #include "iut_msc1210.h"
06:
07: #define EOF 0x04
08: #define MAXCHAR 4
09:
10: char getchar(void) {
11: return ser_getc();
12: }
13:
14: void putchar(char c) {
15: ser_putc(c);
16: }
17:
18: unsigned char menu(void) {
19:
20: putcr();
21: putcr();
22: puts("------- Menu -------");
23: putcr();
24: puts("(a) : lecture des 10 entrees");
25: putcr();
26: puts("(b) : ecriture des 10 sorties");
27: putcr();
28: puts("(c) : saisie de la valeur a ecrire (< 1024)");
29: putcr();
30: puts("(d) : lecture bit individuel (0 <= b <= 9)");
31: putcr();
32: puts("(e) : ecriture bit individuel (0 <= b <= 9)");
33: putcr();
34: puts("(EOF) : taper CTRL D pour sortir");
35: putcr();
36: puts("--------------------");
37: putcr();
38:
39: return getchar();
40: }
41:
42: void main(void) {
43:
44: unsigned int val = 0;
45: unsigned char c, chaine[MAXCHAR], num;
46:
47: /* Appuyer sur Entrée pour ajuster automatiquement
48: * le débit sur la liaison série */
49: autobaud();
50: EA=1;
51:
52: while ((c = menu()) != EOF) {
53: switch (c) {
54: case 'a':
55: val = lecture_10bits();
56: break;
57: case 'b':
58: ecriture_10bits(val);
59: break;
60: case 'c':
61: puts("Valeur :");
62: putcr();
63: ser_gets_echo(chaine, MAXCHAR);
64: val = atoi(chaine);
65: putcr();
66: break;
67: case 'd':
68: do {
69: puts("Numero du bit :");
70: putcr();
71: ser_gets_echo(chaine, MAXCHAR);
72: num = atoi(chaine);
73: putcr();
74: } while (num > 9);
75: val = lecture_1bit(num);
76: break;
77: case 'e':
78: do {
79: puts("Numero du bit :");
80: putcr();
81: ser_gets_echo(chaine, MAXCHAR);
82: num = atoi(chaine);
83: putcr();
84: } while (num > 9);
85: do {
86: puts("Valeur du bit :");
87: putcr();
88: ser_gets_echo(chaine, MAXCHAR);
89: val = atoi(chaine);
90: putcr();
91: } while (val > 1);
92: ecriture_1bit(num, val);
93: break;
94: default:
95: puts("Option non reconnue");
96: putcr();
97: }
98: printf ("/%03x/\n\r", val);
99: putcr();
100: }
101: // Fin du programme
102: puts("The End!");
103: putcr();
104:
105: while(1);
106:}
Vous êtes ici :