Aller au contenu

Un mot pour Fahmio

Tu écris. Tu continues.

Un problème, une idée — assez pour qu’on comprenne, puis tu retournes à ta copie.

On lit. Tu n’as rien d’autre à faire.

Où veux-tu aller ?

↑ ↓ pour parcourir · Entrée pour ouvrir · Échap pour fermer

Fahmio
Fahmio
Bac Tunisie
PIC-DAutomatisme — PIC et mikroPascal

Programme de comptage d'impulsions : interruption RB0/INT ou TMR0 sur RA4, consigne BCD, afficheurs 7 segments et commande des contacteurs

Idée directrice

Des impulsions (une par allée, par pas, par pièce) doivent être comptées sans en perdre une seule, pendant que le programme fait autre chose. Le PIC les confie soit à l'interruption externe RB0/INT (la procédure interrupt() met le compte à jour), soit au timer TMR0 en mode compteur sur RA4/T0CKI. La boucle principale lit la consigne en BCD, affiche le compte et décide des contacteurs en comparant compte et consigne. C'est la moitié programmée des exercices « solution câblée puis solution programmée » des sessions 2024–2025.

Ce qui aide à reconnaître la démarche

« Pourquoi a-t-on relié le capteur S2 à l'entrée RA4 du PIC 16F876A ? » ; « //Procédure interruption » ; « //lecture position choisie No » ; « //Mise en service par appuie sur le bouton START » ; « //Déclaration d'une fonction interruption »

Besoin d’un point de départ ? Voir la méthode
  • Entrée d'impulsions : RB0/INT → interruption externe (INTCON = 0x90 : GIE + INTE) ; RB4 à RB7 → interruption sur changement d'état (0x88 : GIE + RBIE) ; RA4/T0CKI → TMR0 compteur (T0CS = 1 dans OPTION_REG).
  • La procédure interrupt() ne fait que mettre le compte à jour, puis efface son indicateur (INTF_bit = 0, ou réécriture d'INTCON = 0x90).
  • Consigne sur roues codeuses : Bcd2Dec(PORT) ou 10 × (PORT/16) + PORT%16 ; affichage par 7447 : Dec2Bcd(N) ou 16 × (N/10) + N%10.
  • Contacteurs : comparer compte et consigne (<, ==, >) dans la boucle ; bouton marche/arrêt : basculer au relâchement (Button + drapeau).
  • TRIS : 1 entrée, 0 sortie, en appliquant le N.B. aux broches non connectées.
Les pièges à vérifier dans ta démarche

Lire la consigne comme un binaire naturel (0x27 vaut 39, pas 27) ; oublier de remettre INTF à 0 ; compter les impulsions dans la boucle au lieu de l'interruption (impulsions perdues) ; basculer Dv tant que le bouton est enfoncé au lieu d'une seule fois ; mettre RB5, RB6 en entrées alors que le N.B. veut les broches non connectées en sorties ; confondre avance et recul selon le signe de No − Np.

Sujet principal

Exercice — positionnement d'un chariot de transfert, programme MikroC avec interruption, dans l'esprit des sessions 2018–2025

1 questionFigure fournieCorrigé masqué

Dans un entrepôt, un chariot de transfert roule le long de 60 allées numérotées de 00 à 59 ; il est à l'allée 00 à la mise sous tension. Un capteur inductif délivre une impulsion H à chaque allée franchie. L'opérateur choisit l'allée de destination No sur deux roues codeuses BCD, puis appuie sur START : le chariot avance (KM1) ou recule (KM2) jusqu'à ce que sa position Np soit égale à No. Un nouvel appui sur START met la carte hors service ; la position Np reste alors mémorisée.

Carte à PIC 16F877A : H sur RB0/INT ; RB1 et RB2 commandent, par les transistors T1 et T2, les relais KM1 (avance) et KM2 (recul) ; voyant rouge Dr (chariot en mouvement) sur RB3 ; voyant vert Dv (carte en service) sur RB4 ; RB5 et RB6 non connectées ; START sur RB7 (1 quand on appuie) ; port C vers deux décodeurs 7447 (dizaines sur RC7…RC4, unités sur RC3…RC0) ; roues codeuses sur le port D (SW2 dizaines sur RD7…RD4, SW1 unités sur RD3…RD0). Registre INTCON : bit 7 GIE (validation générale), bit 4 INTE (validation de RB0/INT), bit 1 INTF (indicateur de RB0/INT).

N.B : les broches non connectées sont considérées comme des sorties.

Programme en MikroC à compléter :

// Déclaration des variables
unsigned short Np, No, st;
sbit KM1 at RB1_bit;
sbit KM2 at ………… ;
sbit Dr  at ………… ;
sbit Dv  at ………… ;

// Procédure d'interruption : une impulsion H
void interrupt() {
  if (KM1) Np = Np + 1;             // le chariot avance
  if (KM2) ……………… ;                // le chariot recule
  INTF_bit = 0;
}

void main() {
  // Configuration des registres
  TRISB = 0x…… ;  TRISC = 0x…… ;  TRISD = 0x…… ;
  PORTB = 0;  PORTC = 0;
  INTCON = 0x…… ;                   // GIE et INTE
  Np = 0;  st = 0;
  while (1) {
    // Lecture de l'allée choisie
    No = ……………… ;
    // Mise en service / hors service par START
    if (Button(&PORTB, 7, 1, 1)) st = 1;
    if (st && Button(&PORTB, 7, 1, 0)) {
      Dv = ……… ;  st = 0; }
    // Affichage de la position
    PORTC = ……………… ;
    // Commande des contacteurs
    if (Dv && (Np < No))      { KM1 = 1;  KM2 = 0; }
    else if (Dv && (Np > No)) { KM1 = ……; KM2 = ……; }
    else                      { KM1 = ……; KM2 = ……; }
    // Voyant rouge : chariot en mouvement
    Dr = ……………… ;
  }
}

1. Pourquoi a-t-on relié le capteur H à l'entrée RB0/INT plutôt qu'à une entrée lue dans la boucle ? Quelle autre broche du PIC permettrait de compter ces impulsions sans procédure d'interruption, et avec quel module ?

2. Compléter les déclarations sbit et la configuration des registres TRISB, TRISC, TRISD et INTCON.

3. Compléter la procédure d'interruption, qui met à jour le compteur de position Np. Pourquoi le sens du comptage est-il pris sur KM1 et KM2 ? Quel est le rôle de l'instruction INTF_bit = 0 ?

4. Compléter la lecture de la consigne et l'affichage de Np (fonctions Bcd2Dec et Dec2Bcd).

5. Compléter l'instruction qui bascule Dv. Expliquer le rôle des deux lignes qui utilisent Button et la variable st : à quel moment Dv change-t-il d'état ?

6. Compléter la commande des contacteurs et du voyant Dr.

7. Le chariot est à l'allée 18 ; les roues codeuses affichent 4 (dizaines) et 5 (unités). Donner PORTD en binaire et en décimal, la consigne No, le contacteur excité, le nombre d'impulsions H reçues avant l'arrêt, puis la valeur de PORTC au départ et à l'arrivée. Que se passerait-il si l'on avait écrit No = PORTD ?

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : une impulsion peut arriver pendant que la boucle est occupée ailleurs (Button attend 1 ms, les contacteurs sont en cours de mise à jour…). Sur RB0/INT, chaque front de H déclenche aussitôt interrupt() : aucune impulsion n'est perdue, quel que soit l'endroit où se trouve la boucle. L'autre solution est l'entrée RA4/T0CKI : le timer TMR0, en mode compteur (OPTION_REG, T0CS = 1), compte seul les fronts.

2. Idée : RB0 (H) et RB7 (START) sont les seules entrées du port B ; RB5 et RB6, non connectées, sont des sorties d'après le N.B.

sbit KM2 at RB2_bit;
sbit Dr  at RB3_bit;
sbit Dv  at RB4_bit;
TRISB = 0x81;  TRISC = 0x00;  TRISD = 0xFF;
INTCON = 0x90;

TRISB =1000 0001=1000\,0001 ; décodeurs en sortie (0x00) ; roues codeuses en entrée (0xFF) ; INTCON =1001 0000=1001\,0000 : GIE = 1, INTE = 1.

3. Np = Np - 1; Chaque impulsion vient d'un déplacement réel, dont le sens est fixé par le contacteur excité : KM1 = 1, le chariot avance et Np augmente ; KM2 = 1, il recule et Np diminue. Le front sur RB0 met INTF à 1 ; s'il n'est pas remis à 0, la procédure se relance sans fin dès sa sortie. INTF_bit = 0 réarme l'interruption pour l'impulsion suivante.

4. No = Bcd2Dec(PORTD); et PORTC = Dec2Bcd(Np); Les roues codeuses délivrent un chiffre BCD par quartet : 0100 0101 signifie 45, pas 69. Inversement, chaque 7447 attend un chiffre BCD.

5. La première ligne mémorise l'appui (st = 1 quand RB7 est resté à 1 pendant 1 ms, ce qui élimine les rebonds). La seconde attend le relâchement (RB7 = 0) : Dv = ~Dv; bascule alors une seule fois et st revient à 0. Dv change donc d'état au relâchement, une fois par appui, même si START est maintenu longtemps ; il sert de mémoire « en service » et allume le voyant vert.

6. Idée : hors service (Dv = 0) ou à l'arrivée (Np = No), les deux contacteurs sont au repos ; Dr s'allume dès que l'un d'eux est excité.

else if (Dv && (Np > No)) { KM1 = 0; KM2 = 1; }
else                      { KM1 = 0; KM2 = 0; }
Dr = KM1 || KM2;

7. PORTD =0100 0101=69=0100\,0101=69 ; No=N_o= Bcd2Dec(69) =45=\boxed{45}. Np=18<45N_p=18<45 : KM1 (avance) et Dr = 1. Le chariot reçoit 45−18=2745-18=\boxed{27} impulsions. Au départ, PORTC = Dec2Bcd(18) =0001 1000=0001\,1000 (0x18 = 24) ; à l'arrivée, PORTC =0100 0101=0100\,0101 : les afficheurs montrent 45, KM1 = 0 et Dr = 0. Avec No = PORTD, la consigne vaudrait 69 : le chariot avancerait au-delà de la dernière allée (59) sans jamais trouver Np = No.

Changer d’énoncé, garder le raisonnement

Choisis un seul transfert après le sujet principal. Qu’est-ce qui change ? Quel résultat ou quelle méthode peux-tu réutiliser ? Les autres exercices restent disponibles pour une prochaine séance.

Variantes rencontrées : interruption RB0/INT, consigne BCD2DEC(portC), affichage DEC2BCD(Np) sur deux 7447, marche/arrêt par START et Dv = ~Dv (contrôle 2025) ; deux compteurs Nx et Nz dans une même interruption sur changement d'état de RB4 à RB7, consignes sur les deux quartets du port D (contrôle 2024) ; capteur sur RA4 et TMR0 en compteur (OPTION_REG = 1110 1000), lot de 100 fûts affiché sur LCD (principale 2019) ; TMR0 affiché sur deux ports par une table de codes (principale 2018) ; TMR0 compté puis décompté 12 − TMR0 avec Dec2Bcd (principale 2020) ; compteurs incrémentés par un bouton avec anti-rebond (contrôle 2020, contrôle 2021).

Exercices d'entraînement — une nuance à la fois

1 Drill PIC-D.1 — mikroPascal : TMR0 compteur sur RA4, choix du front dans OPTION_REG, lot de sacs
Entraînement 01 / 05

Drill PIC-D.1 — mikroPascal : TMR0 compteur sur RA4, choix du front dans OPTION_REG, lot de sacs

1 questionCorrigé masqué

Au poste de chargement d'une cimenterie, un capteur S délivre une impulsion à chaque sac posé sur le convoyeur ; son signal passe de 1 à 0 à l'arrivée du sac. S est relié à RA4/T0CKI d'un PIC 16F876A. Un camion reçoit un lot de 50 sacs. Après une coupure, l'opérateur introduit le nombre de sacs déjà chargés sur deux roues codeuses BCD reliées au port B (unités sur RB3…RB0, dizaines sur RB7…RB4). Un LCD (port C) affiche le total chargé, et « LOT COMPLET » quand ce total atteint 50.

Registre OPTION_REG, du bit 7 au bit 0 : RBPU, INTEDG, T0CS (1 : TMR0 compte les fronts de RA4), T0SE (0 : front montant ; 1 : front descendant), PSA (1 : prédiviseur affecté au chien de garde, TMR0 compte chaque front), PS2, PS1, PS0 (rapport du prédiviseur). On garde RBPU = 1, INTEDG = 1 et PS2…PS0 = 000.

1. Pourquoi relie-t-on S à RA4 ? Déterminer la valeur d'OPTION_REG en binaire et en hexadécimal.

2. Compléter le programme.

program Sacs;                          // nom du programme
var U, D, NDC, NT : byte;              // unités, dizaines, déjà chargés, total
    txt : string[3];                   // chaîne de 3 caractères
// Connexion de l'afficheur LCD (à ne pas traiter)
begin
  OPTION_REG := %………………;             // TMR0 compteur, front descendant
  ADCON1 := $06;                       // port A numérique
  TRISA := $FF;
  TRISB := $……;                        // roues codeuses
  LCD_Init();
  LCD_Cmd(_LCD_CURSOR_OFF);
  U := PORTB and $0F;                  // unités des sacs déjà chargés
  D := ………………;                        // dizaines
  NDC := ………………;                      // nombre déjà chargé
  TMR0 := 0;                           // initialiser le compteur
  while TRUE do
  begin
    NT := ………………;                     // total chargé
    ByteToStr(NT, txt);
    LCD_Out(1, 1, 'Total =');
    LCD_Out(1, 9, txt);
    if NT >= 50 then LCD_Out(2, 1, 'LOT COMPLET');
  end;
end.

3. Les roues codeuses affichent 1 et 8 ; TMR0 vaut 27. Calculer PORTB, NDC et NT. Combien de sacs faut-il compter depuis la reprise pour compléter le lot ?

4. Par erreur, on écrit PSA = 0 (prédiviseur 1:2 affecté à TMR0). Que vaudrait TMR0 après les 27 sacs ?

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : RA4/T0CKI est l'entrée d'horloge externe du timer TMR0. En mode compteur, TMR0 compte les fronts de S par le matériel, sans instruction du programme : aucun sac n'est oublié. Front descendant : T0SE = 1, d'où OPTION_REG =1111 1000=\boxed{1111\,1000}, soit F8 en hexadécimal.

2.

OPTION_REG := %11111000;             // T0CS = 1, T0SE = 1, PSA = 1
TRISB := $FF;
U := PORTB and $0F;
D := PORTB div 16;
NDC := U + 10 * D;
NT := NDC + TMR0;

3. PORTB =0001 1000=24=0001\,1000=24 ; U =24=24 and 15 =8=8 ; D =24=24 div 16 =1=1 ; NDC =8+10×1=18=8+10\times1=\boxed{18} ; NT =18+27=45=18+27=\boxed{45}. Depuis la reprise, le lot demande 50−18=3250-18=\boxed{32} sacs (encore 5 après les 27 comptés).

4. Avec le prédiviseur 1:2, TMR0 n'avance qu'un front sur deux : 27 div 2 =13=13, et le LCD afficherait un total faux de 31.

2 Drill PIC-D.2 — deux compteurs dans une interruption sur changement d'état de RB4 à RB7, consignes sur les quartets du port D
Entraînement 02 / 05

Drill PIC-D.2 — deux compteurs dans une interruption sur changement d'état de RB4 à RB7, consignes sur les quartets du port D

1 questionCorrigé masqué

Un portique de rangement, commandé par un PIC 16F877A, dépose des bacs dans un casier. Son chariot se déplace d'abord en X (moteur commandé par KMX sur RA0), puis la pince descend en Z (KMZ sur RA1). Deux codeurs délivrent Cx (RB6) : 6 impulsions par case en X, et Cz (RB7) : 4 impulsions par niveau en Z. Les consignes sont données par deux roues codeuses sur le port D : SWX (case) sur RD3…RD0, SWZ (niveau) sur RD7…RD4. L'interrupteur DEP (RB0) lance le déplacement ; les compteurs Nx et Nz sont mis à jour dans la procédure d'interruption sur changement d'état de RB4 à RB7. Les broches non utilisées sont des entrées.

sbit DEP at RB0_bit;
sbit Cx at RB6_bit;   sbit Cz at RB7_bit;
sbit KMX at RA0_bit;  sbit KMZ at RA1_bit;
unsigned short Nx, Nz, Chx, Chz;
void interrupt() {                 // impulsions des codeurs
  if (Cx && KMX) Nx = …………;
  if (Cz && KMZ) Nz = …………;
  INTCON = 0x88;
}
void main() {
  ADCON1 = 0x06;                   // port A numérique
  TRISA = 0x……;                    // RA0, RA1 en sortie
  TRISB = 0xFF;
  TRISD = 0x……;                    // roues codeuses
  KMX = 0;  KMZ = 0;
  Nx = 0;  Nz = 0;
  INTCON = 0x……;
  while (1) {
    Chz = PORTD / 16;              // niveau choisi
    Chx = ……………;                   // case choisie
    KMX = DEP && (Nx < 6 * Chx);
    KMZ = DEP && (Nx == 6 * Chx) && (Nz < ……… * Chz);
  }
}

1. Justifier INTCON = 0x88 (bit 7 : GIE ; bit 3 : RBIE). Compléter la procédure d'interruption.

2. L'interruption se déclenche à chaque changement d'état (front montant et front descendant) de RB4 à RB7. Pourquoi faut-il tester Cx et KMX avant d'incrémenter Nx ? Qu'arriverait-il en X si l'on comptait à chaque entrée dans la procédure ?

3. Compléter la configuration, le calcul de Chx et la condition de KMZ.

4. SWX = 3 et SWZ = 2. Donner PORTD, Chx, Chz et le nombre d'impulsions reçues en X, puis en Z.

Voir la correction commentéeAprès avoir posé votre démarche

1. 0x88=1000 10000\text{x}88=1000\,1000 : GIE = 1 et RBIE = 1 (interruption sur changement d'état de RB4 à RB7, où sont Cx et Cz). Nx = Nx + 1; et Nz = Nz + 1;

2. Idée : une impulsion provoque deux entrées dans la procédure, et l'autre codeur en provoque aussi. Tester Cx = 1 ne compte que le front montant, une fois par impulsion ; tester KMX évite de compter en X quand c'est Cz qui change pendant que Cx reste à 1. En comptant à chaque entrée, Nx avancerait de 2 par impulsion (front montant puis front descendant) : le chariot s'arrêterait à mi-chemin, après 3 impulsions par case au lieu de 6.

3.

if (Cx && KMX) Nx = Nx + 1;
if (Cz && KMZ) Nz = Nz + 1;
TRISA = 0xFC;
TRISD = 0xFF;
INTCON = 0x88;
Chx = PORTD - 16 * Chz;       // ou PORTD % 16
KMZ = DEP && (Nx == 6 * Chx) && (Nz < 4 * Chz);

4. PORTD =0010 0011=35=0010\,0011=35 ; Chz =35/16=2=35/16=2 ; Chx =35−32=3=35-32=3. En X : 6×3=186\times3=\boxed{18} impulsions ; puis en Z : 4×2=84\times2=\boxed{8} impulsions.

3 Drill PIC-D.3 — TMR0 compté puis décompté : bobinage aller-retour affiché par Dec2Bcd
Entraînement 03 / 05

Drill PIC-D.3 — TMR0 compté puis décompté : bobinage aller-retour affiché par Dec2Bcd

1 questionCorrigé masqué

Une bobineuse enroule un fil : 15 tours dans le sens 1 (KM1 sur RC0), puis 15 tours dans le sens 2 (KM2 sur RC1). Un capteur délivre une impulsion par tour sur RA4/T0CKI, comptée par TMR0. Deux afficheurs, commandés par deux 7447 reliés au port B (dizaines sur RB7…RB4, unités sur RB3…RB0), montrent le nombre de tours enroulés : de 0 à 15 pendant l'aller, puis de 15 à 0 pendant le retour. Le bouton Dep (RA0) lance le cycle. Les broches non utilisées sont des entrées.

unsigned short i, j;
sbit Dep at RA0_bit;
sbit KM1 at RC0_bit;
sbit KM2 at RC1_bit;
void main() {
  ADCON1 = 0x06;                 // port A numérique
  TRISA = 0xFF;
  TRISB = 0x……;                  // afficheurs
  TRISC = 0x……;                  // RC0, RC1 en sortie
  OPTION_REG = 0x28;             // TMR0 compteur sur RA4
  PORTB = 0;  PORTC = 0;
  while (1) {
    if (Dep == 1) {
      TMR0 = 0;
      while (TMR0 <= ……) {       // aller : 15 tours
        i = TMR0;  PORTB = Dec2Bcd(i);  KM1 = 1; }
      KM1 = 0;  PORTB = Dec2Bcd(15);
      TMR0 = 0;
      while (TMR0 <= ……) {       // retour : 15 tours
        j = ……………;  PORTB = Dec2Bcd(j);  KM2 = 1; }
      KM2 = 0;  PORTB = 0;
    }
  }
}

1. Interpréter OPTION_REG = 0x28 (bits RBPU, INTEDG, T0CS, T0SE, PSA, PS2…PS0) : quels bits règlent TMR0 ?

2. Compléter le programme (configuration, bornes des boucles, calcul de j).

3. Pendant le retour, TMR0 vaut 9 : que vaut j, et qu'écrit-on dans PORTB ?

4. Pourquoi écrire PORTB = Dec2Bcd(i) et non PORTB = i ? Illustrer avec 13.

Voir la correction commentéeAprès avoir posé votre démarche

1. 0x28=0010 10000\text{x}28=0010\,1000 : RBPU = 0 et INTEDG = 0 ne concernent pas TMR0 ; T0CS = 1 (compteur sur RA4), T0SE = 0 (front montant), PSA = 1 (prédiviseur au chien de garde : +1 par tour) ; PS2…PS0 sont alors sans effet sur TMR0.

2. Idée : while (TMR0 <= 14) tourne pour TMR0 = 0 à 14 et s'arrête à 15 tours.

TRISB = 0x00;
TRISC = 0xFC;
while (TMR0 <= 14) { … }       // aller
while (TMR0 <= 14) {           // retour
  j = 15 - TMR0;  PORTB = Dec2Bcd(j);  KM2 = 1; }

Pendant l'aller, l'affichage va de 0 à 14, puis Dec2Bcd(15) affiche 15 à la sortie de la boucle ; pendant le retour, j va de 15 à 1, puis PORTB = 0.

3. j=15−9=6j=15-9=\boxed{6} : PORTB = Dec2Bcd(6) =0000 0110=0000\,0110, les afficheurs montrent 06.

4. Chaque 7447 attend un chiffre BCD par quartet : Dec2Bcd(13) =0001 0011=0001\,0011 affiche 1 et 3. PORTB = 13 écrirait 0000 11010000\,1101 : dizaine 0, et le décodeur des unités recevrait 1101, qui n'est pas un code BCD.

4 Drill PIC-D.4 — compter les appuis sur un bouton : anti-rebond, détection du relâchement, bornes
Entraînement 04 / 05

Drill PIC-D.4 — compter les appuis sur un bouton : anti-rebond, détection du relâchement, bornes

1 questionCorrigé masqué

Sur un empileur de palettes, l'opérateur règle le nombre de couches C1 (de 1 à 20) avec deux boutons, Plus (RB1) et Moins (RB2), qui délivrent 1 quand on appuie. C1 est affiché sur un LCD (port C, ligne 2, colonne 6). Hors temporisation, un tour de boucle dure moins de 1 ms.

1. Une première version compte ainsi : if (Plus == 1) { C1 = C1 + 1; Delay_ms(50); }. L'opérateur maintient Plus enfoncé 0,3 s pour un seul appui. De combien C1 augmente-t-il ? Quel défaut du bouton Delay_ms(50) traite-t-il, et lequel ne traite-t-il pas ?

2. Compléter la version corrigée, qui compte un appui au relâchement du bouton.

unsigned short C1, st1, st2;
char txt[4];
// Connexion de l'afficheur LCD (à ne pas traiter)
void main() {
  ADCON1 = 0x06;
  TRISB = 0xFF;
  C1 = 5;  st1 = 0;  st2 = 0;
  Lcd_Init();  Lcd_Cmd(_LCD_CURSOR_OFF);
  Lcd_Out(1, 1, "Couches :");
  while (1) {
    if (Button(&PORTB, 1, 1, 1)) st1 = 1;        // Plus enfoncé
    if (st1 && Button(&PORTB, 1, 1, 0)) {        // Plus relâché
      if (C1 < ……) C1 = C1 + 1;
      st1 = 0; }
    if (Button(&PORTB, 2, 1, 1)) st2 = 1;        // Moins enfoncé
    if (…… && Button(&PORTB, 2, 1, 0)) {         // Moins relâché
      if (C1 > ……) C1 = ……………;
      st2 = 0; }
    ByteToStr(C1, txt);
    Lcd_Out(……, ……, txt);
  }
}

3. C1 vaut 5. L'opérateur appuie 3 fois sur Plus, puis une fois sur Moins. Quelle valeur est affichée ? Pourquoi txt est-il déclaré sur 4 caractères ?

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : ce test lit un niveau, pas un appui. Chaque tour où Plus vaut 1 ajoute 1 puis attend 50 ms : pendant 0,3 s, 300/50=6300/50=6 tours, C1 augmente d'environ 6 au lieu de 1. La temporisation élimine les rebonds (quelques ms) mais pas la durée de l'appui.

2.

if (C1 < 20) C1 = C1 + 1;
if (st2 && Button(&PORTB, 2, 1, 0)) {
  if (C1 > 1) C1 = C1 - 1;
  st2 = 0; }
Lcd_Out(2, 6, txt);

Button(&PORTB, 1, 1, 1) répond vrai si RB1 est resté à 1 pendant 1 ms (anti-rebond) : l'appui est mémorisé dans st1, et C1 n'est modifié qu'au relâchement, une fois par appui quelle que soit sa durée ; les tests C1 < 20 et C1 > 1 bornent le réglage.

3. 5→6→7→8→75\to6\to7\to8\to7 : le LCD affiche 7\boxed{7}. ByteToStr écrit 3 caractères suivis du caractère de fin de chaîne : il faut 4 cases.

5 Drill PIC-D.5 — afficher TMR0 sur deux ports par une table de codes : décodeurs 7447 ou afficheurs commandés en direct
Entraînement 05 / 05

Drill PIC-D.5 — afficher TMR0 sur deux ports par une table de codes : décodeurs 7447 ou afficheurs commandés en direct

1 questionCorrigé masqué

Dans un tunnel de lavage de voitures, le convoyeur avance pas à pas ; un capteur délivre une impulsion par pas sur RA4/T0CKI, comptée par TMR0 (OPTION_REG = 0xE8). Le nombre de pas est affiché sur deux afficheurs 7 segments : unités par un 7447 relié à RC3…RC0, dizaines par un 7447 relié à RB3…RB0. Au 24e pas, la sortie FIN (RA5) passe à 1 ; le bouton RAZ (RA1) remet TMR0 et FIN à 0. Les broches non utilisées sont des entrées.

1. Compléter le programme.

const unsigned short code7seg[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
unsigned short unite, dizaine;
sbit RAZ at RA1_bit;
sbit FIN at RA5_bit;
void affichage() {
  unite = TMR0 % 10;
  dizaine = ……………;
  PORTC = code7seg[unite];         // port des unités
  PORTB = ……………;                   // port des dizaines
}
void main() {
  ADCON1 = 0x06;                   // port A numérique
  TRISA = 0x……;                    // RA5 en sortie
  TRISB = 0x……;  TRISC = 0x……;      // RB0-RB3, RC0-RC3 en sortie
  OPTION_REG = 0xE8;               // TMR0 compteur sur RA4
  TMR0 = 0;  FIN = 0;
  while (1) {
    affichage();
    if (TMR0 == ……) FIN = 1;        // fin du cycle
    if (RAZ == 1) { TMR0 = 0;  FIN = ……; }
  }
}

2. TMR0 = 47 : que valent unite, dizaine, PORTC et PORTB ? Pourquoi la table code7seg contient-elle simplement 0, 1, …, 9 ?

3. On supprime les 7447 : chaque afficheur à cathode commune est commandé directement, segment a sur le bit 0 … segment g sur le bit 6 (1 = segment allumé ; disposition usuelle : a en haut, b et c à droite, d en bas, e et f à gauche, g au milieu). Donner les nouvelles valeurs de code7seg[2], code7seg[4] et code7seg[7], puis PORTC et PORTB pour TMR0 = 47.

Voir la correction commentéeAprès avoir posé votre démarche
1.

dizaine = TMR0 / 10;
PORTB = code7seg[dizaine];
TRISA = 0xDF;                      // 1101 1111
TRISB = 0xF0;  TRISC = 0xF0;
if (TMR0 == 24) FIN = 1;
if (RAZ == 1) { TMR0 = 0;  FIN = 0; }

2. unite =47 % 10=7=47\,\%\,10=7 ; dizaine =47/10=4=47/10=4 ; PORTC =0000 0111=0000\,0111 et PORTB =0000 0100=0000\,0100 : les afficheurs montrent 47. Le 7447 décode lui-même le BCD : le code à envoyer est le chiffre lui-même, d'où une table 0, 1, …, 9.

3. Idée : allumer les segments qui dessinent le chiffre, bit par bit (g … a). 2 : a, b, d, e, g → 0101 10110101\,1011 = 0x5B ; 4 : b, c, f, g → 0110 01100110\,0110 = 0x66 ; 7 : a, b, c → 0000 01110000\,0111 = 0x07. Pour 47 : PORTC = 0x07 et PORTB = 0x66 ; RB0…RB6 et RC0…RC6 doivent alors être en sortie (TRISB = TRISC = 0x80).

Relier ce raisonnement au bac

Choisis une filière pour voir les sujets qui étayent ce scénario.