← Retour← Back
CV

Micro-informatique : PIC16F84a et horloge à quartz sur PIC16F877aMicrocontrollers: PIC16F84a and a quartz clock on the PIC16F877a

PIC16F84aPIC16F877aAssembleur / AssemblyCMPLAB X
QuoiWhat
Une horloge temps réel sur PIC16F877a (PICDEM2+) avec LCD, réglage par boutons ou potentiomètre et température en I²C, précédée de TPs sur PIC16F84a.A real-time clock on the PIC16F877a (PICDEM2+) with LCD, setting by buttons or potentiometer and I²C temperature, preceded by labs on the PIC16F84a.
PourquoiWhy
Maîtriser timers, interruptions, CAN et I²C sur un vrai microcontrôleur, et structurer un code C en modules.To get comfortable with timers, interrupts, ADC and I²C on a real microcontroller, and to structure C code in modules.
CommentHow
Quartz 32,768 kHz sur TIMER1 + CCP1, librairie LCD écrite from scratch, six modules C. En binôme avec Aamir Asmal.32.768 kHz quartz on TIMER1 + CCP1, LCD library written from scratch, six C modules. With Aamir Asmal.
RésultatsResults
Base de temps à 1 Hz sans jamais remettre TMR1 à zéro, testée sous PICSimLab puis sur la vraie carte.1 Hz time base without ever resetting TMR1, tested on PICSimLab then on the real board.

Module EEL6-NUMU2 en deux temps : des TPs sur PIC16F84a pour comprendre l'architecture et le jeu d'instructions, puis un projet de synthèse sur PIC16F877a (carte PICDEM2+) : une horloge à quartz avec LCD, réglage par boutons ou potentiomètre, et température via un capteur TC74 en I²C. Projet fait avec Aamir Asmal.

TPs sur PIC16F84a

  • TP1 : MPLAB X, assembleur, une LED puis un chenillard avec temporisation par boucle (chaque instruction = 1 cycle, sauf les sauts).
  • TP2 : chenillard en C (XC8), puis TIMER0 avec prédiviseur et valeur de rechargement.
  • TP3 : passage du polling aux interruptions, chien de garde (WDT) comme temporisation, message défilant sur le 7 segments.

Projet : horloge sur PICDEM2+

main.cboucle 10 Hz + ITmain.c10 Hz loop + ISRtimerTIMER1 + CCP1lib_LCDLCD 2×16, 4 bitslib_LCD2×16 LCD, 4-bitboutonS2 (RA4), S3 (RB0)boutonS2 (RA4), S3 (RB0)potCAN 10 bits, AN0pot10-bit ADC, AN0tc74I²C, MSSP maîtretc74I²C, MSSP masterIT 1 Hz1 Hz ISRaffichagedisplaypoussoirsbuttonsconversionconversionlecture 5 Hz5 Hz read
Découpage modulaire du projet horloge : un module par périphérique, le tout orchestré par main.c.Modular split of the clock project: one module per peripheral, orchestrated by main.c.
  • Base de temps : quartz 32,768 kHz sur TIMER1, qui déborde toutes les 2 s. Le comparateur CCP1 à 0x8000 ajoute une IT à mi-parcours, donc 1 Hz sans jamais remettre TMR1 à zéro (sinon on perd la précision du quartz). Une LED sur RB1 clignote à 0,5 Hz pour dire « l'IT tourne ».
  • Interruptions : il faut les trois verrous en même temps (masque PIE1, PEIE, GIE), sinon rien ne se passe.
  • Librairie LCD : écrite from scratch, en mode 4 bits sur le PORTD. L'init suit la datasheet Sunplus (4 cycles avec leurs temporisations). Un front parasite sur E décale tout d'un demi-mot, et toucher RD7 coupe l'alim de l'afficheur : on s'en est rendu compte.
  • Réglage : appui long sur S2 (≥ 2 s) pour entrer en réglage, S3 incrémente (appui maintenu = défilement). Le potentiomètre (CAN 10 bits sur RA0) peut aussi régler : il ne prend la main que s'il bouge de plus de 10 LSB, pour ne pas dépendre du bruit.
  • Température : TC74 sur bus I²C (MSSP en maître à 100 kHz, adresse 0x4D), lu toutes les 200 ms avec une trame start / écriture du pointeur / restart / lecture.
  • Code : six modules en C (timer, lib_LCD, bouton, pot, tc74, main) et une boucle principale à 10 Hz. Les variables partagées avec l'IT sont volatile.
Le piège dont on se souvient : RA0 (potentiomètre) et RA4 (S2) sont sur le même port A, et un seul registre (ADCON1) décide analogique ou numérique. Il faut initialiser les boutons avant le potentiomètre, sinon on écrase la config du CAN et les lectures deviennent incohérentes.

Test d'abord sous PICSimLab (le quartz 32 kHz n'y existe pas, donc horloge principale avec prédiviseur 8), puis sur la vraie carte. Les potentiomètres des cartes étaient un peu usés, donc le réglage analogique est moins précis qu'espéré.

EEL6-NUMU2 module in two parts: lab sessions on the PIC16F84a to learn the architecture and instruction set, then a final project on the PIC16F877a (PICDEM2+ board): a quartz clock with an LCD, set with buttons or a potentiometer, plus temperature from a TC74 sensor over I²C. Done with Aamir Asmal.

PIC16F84a labs

  • Lab 1: MPLAB X, assembly, one LED then a chaser with a loop-based delay (each instruction = 1 cycle, except jumps).
  • Lab 2: chaser in C (XC8), then TIMER0 with prescaler and reload value.
  • Lab 3: from polling to interrupts, watchdog (WDT) as a delay source, scrolling message on the 7-segment display.

Project: clock on the PICDEM2+

main.cboucle 10 Hz + ITmain.c10 Hz loop + ISRtimerTIMER1 + CCP1lib_LCDLCD 2×16, 4 bitslib_LCD2×16 LCD, 4-bitboutonS2 (RA4), S3 (RB0)boutonS2 (RA4), S3 (RB0)potCAN 10 bits, AN0pot10-bit ADC, AN0tc74I²C, MSSP maîtretc74I²C, MSSP masterIT 1 Hz1 Hz ISRaffichagedisplaypoussoirsbuttonsconversionconversionlecture 5 Hz5 Hz read
Découpage modulaire du projet horloge : un module par périphérique, le tout orchestré par main.c.Modular split of the clock project: one module per peripheral, orchestrated by main.c.
  • Time base: 32.768 kHz quartz on TIMER1, which overflows every 2 s. The CCP1 compare at 0x8000 adds an interrupt halfway, so 1 Hz without ever resetting TMR1 (otherwise we lose the quartz precision). An LED on RB1 blinks at 0.5 Hz to say "the ISR is alive".
  • Interrupts: all three locks must be set (PIE1 mask, PEIE, GIE), or nothing happens.
  • LCD library: written from scratch, 4-bit mode on PORTD. The init follows the Sunplus datasheet (4 cycles with their delays). A stray edge on E shifts everything by half a word, and touching RD7 cuts the display's power: we found that out.
  • Setting the time: long press on S2 (≥ 2 s) to enter set mode, S3 increments (held = scrolls). The potentiometer (10-bit ADC on RA0) can set it too: it only takes over if it moves by more than 10 LSB, so noise doesn't trigger it.
  • Temperature: TC74 on the I²C bus (MSSP master at 100 kHz, address 0x4D), read every 200 ms with a start / pointer write / restart / read frame.
  • Code: six C modules (timer, lib_LCD, bouton, pot, tc74, main) and a 10 Hz main loop. Variables shared with the ISR are volatile.
The trap we remember: RA0 (pot) and RA4 (S2) are on the same port A, and a single register (ADCON1) sets analog or digital. Buttons must be initialized before the pot, otherwise the ADC config gets overwritten and readings become inconsistent.

Tested first on PICSimLab (the 32 kHz quartz doesn't exist there, so main clock with a prescaler of 8), then on the real board. The pots on our boards were a bit worn, so the analog setting is less precise than hoped.