; ;******************************************************************** LIST P = 16C84 LIST F = INHX8M ; ; Clock à PIC ;********************************************************************* ; ; PRÉSENTATION DU PROGRAMME ; ; Ce programme tourne sur un PIC16C84. ; ; Description de la carte ; ; Affichage ; L'affichage se fait sur 4 afficheurs LED 7 segments sous la forme : ; ; ( 88:88 ) ; ; Les mêmes segments des 4 afficheurs sont tous reliés entre eux et sont ; connectés au port B (a=RB1 ; b=RB2 ; c=RB3 ; d=RB4 ; e=RB5 ; f=RB6 ; g=RB7); ; ; Les ":" sont réalisés par les virgules des 2 afficheurs du milieu (celui de ; droite est retourné) qui sont connectées au bit 0 du port B. ; ; Les afficheurs sont de type anode commune (HPDSP7511) et leurs anode est ; connectée au port A (digit0=RA3 ; digit1=RA2 ; digit2=RA1 ; digit3=RA0). ; ; ; INTERRUPTEURS ; Les 12 lignes d'entrée/sortie étant utilisées, il faut effectuer un ; multiplexage pour pouvoir insérer les interrupteurs ; cela est réalisé ; sur le port B (SW1=RB1 ; SW2 = RB2 ; SW3 =RB3); il faut donc que le ; programme commute ces lignes en entrée pour pouvoir analyser l'état des ; interrupteurs. ; SW1 : affichage des secondes ; SW2 : règlage des minutes ; SW2 : règlage des heures ; ; L'oscillateur à quartz utilisé génère une fréquence de 1,8432 MHz, cela ; donne une fréquence interne de 460,8 kHz; la rotation du timer (256 états) ; prédivisé dans un rapport 8 se fait alors à une fréquence de 225 Hz. ; ; Programme : clkapic.ASM ; Date de Révision : Février 95 ; ;************************** Déclarations ************************* ; ; ; ;PORT_A equ H'05' ; anodes communes des afficheurs 7 segments ;PORT_B equ H'06' ; segments et virgules des afficheurs et interrupteurs ; ZEROT equ H'81' UN equ H'F3' DEUX equ H'49' TROIS equ H'61' QUATRE equ H'33' CINQ equ H'25' SIX equ H'05' ; Table des segments (PORT_B) SEPT equ H'F1' HUIT equ H'01' NEUF equ H'31' BLANC equ H'FF' ; variables pour le comptage MAXFRAC equ D'31' ; Timer : 256-31=225, ce qui donne 1 s MAXSECS equ D'196' ; Secondes : 256-196=60 MAXMINS equ D'196' ; Minutes : 256-196=60 MAXHRS equ D'244' ; Heures : 256-244=12 MINHRS equ D'243' ADJMIN equ D'9' ; nombre à soustraire chaque minute ADJHR equ D'34' ; nombre à soustraire chaque heure ADJDAY equ D'3' ; nombre à soustraire chaque 1/2 journée ; AFF0 equ B'00000001' AFF1 equ B'00000010' ; Table de selection des afficheurs (PORT_A) AFF2 equ B'00000100' AFF3 equ B'00001000' AFF_OFF equ B'00000000' SWITCH equ B'00001110' ; Sélection des interrupteurs ; ; Désignation des bits d'état SEC equ 0 ; bit d'état des secondes MIN equ 1 ; bit d'état des minutes HRS equ 2 ; bit d'état des heures CHG equ 3 ; changement d'état d'un interrupteur SW1 equ 4 ; attribution des interrupteurs (0 si actif) : SW2 equ 5 ; SW1 : Secondes-minutes, SW2 : heures, SW3 : mode SW3 equ 6 SW_ON equ 7 ; un interrupteur a été appuyé ; ; VARIABLES clefs equ H'18' ; quel boutons a été appuyé ? flags equ H'19' ; bits d'états : 0-SEC, 1-MIN, 2-HRS, ; 3-CHG, 4-SW1, 5-SW2, 6-SW3 ; equ H'1A' ; pas utilisé affiche equ H'1B' ; quel afficheur raffraîchir ? digit0 equ H'1C' ; Digit des minutes (à droite) digit1 equ H'1D' ; Digit des dizaines de minutes digit2 equ H'1E' ; Digit des heures digit3 equ H'1F' ; Digit des dizaines de heures ; ; Les variables de comptage sont initialisées pour correspondre ; au comptage de l'heure ainsi, seconds démarre à 195D et passe ; à 0 au bout de 61 coups. ; sec_nth equ H'20' ; fractions de seconde seconds equ H'21' ; secondes minutes equ H'22' ; minutes heures equ H'23' ; heures var equ H'24' ; variable temporaire count equ H'25' ; Variable de comptage count2 equ H'26' ; 2ème variable de comptage ; ;******************************************************************************** ; ; Initialisation des ports et effacement de l'affichage ; INCLUDE "PIC84JW.H" ORG PIC84 GOTO START ; ; START movlw 2 ; initialisation du registre option BSF STATUS,RP0 ; Passage au banc mémoire 1 movwf OPT ; Règlage du timer RTCC (1:16) sur horloge interne ; movlw 0 movwf TRISA ; Tous les bits du port A en sortie movwf TRISB ; Tous les bits du port B en sortie BCF STATUS,RP0 ; Retour au banc mémoire 0 movlw BLANC movwf PORT_B ; On n'affiche rien ; ; initialize variables movlw 1 movwf RTCC ; Initialisation de RTCC à 1 movlw AFF0 movwf affiche ; Initialisation des variables d'affichage. movlw BLANC ; Effacement de tous les segments (pas d'affichage). movwf digit0 movwf digit1 movwf digit2 movwf digit3 movlw MAXFRAC ; Initialisation des variables du timer movwf sec_nth movlw MAXSECS movwf seconds movlw MAXMINS movwf minutes movlw 0FFH ; Les heures démarrent à 12 (FFH) movwf heures movlw 0 movwf flags ; Initialisation du mot d'état à 0 clrwdt ; effacement du chien de garde (< 18 ms) ; ; MAIN ; ; Attente de la fin de comptage du timer COMPTEUR movf RTCC,0 ; RTCC --> w btfss STATUS,Z_BIT ; RTCC n'est pas perturbé dans son comptage goto COMPTEUR ; incfsz sec_nth,1 ; Incrémentation des fractions de secondes goto TEMPS_OK ; Incrémentation de l'horloge si 0 clrwdt movlw MAXFRAC movwf sec_nth ; Rechargement des fractions de secondes ; VERIF_SW btfss flags,SW_ON ; A-t'on pressé sur un interrupteur ? goto MISE_A_LHEURE ; non alors on affiche l'heure btfsc flags,SW1 ; Est-ce SW1 (affichage des secondes) goto MISE_A_LHEURE ; Oui, alors on ne change pas l'heure movlw MAXSECS ; non, alors on passe en mode règlage de l'horloge movwf seconds ; on remet les secondes à 0 à la mise à l'heure movlw H'7F' ; Accélération du timer (1/2 seconde) movwf sec_nth btfss flags,SW2 ; Est-ce SW2 (règlage des minutes) goto REGLAGE ; non, alors les minutes ne changent pas, on vérifie l'heure movlw H'AF' ; oui, on accélère le timer pour le règlage des minutes (1/2 s) movwf sec_nth incfsz minutes,1 ; incrémentation des minutes goto REGLAGE ; si pas de débordement, on règle l'heure movlw MAXMINS ; réinitialisation des minutes movwf minutes ; REGLAGE btfsc flags,SW2 ; Est-ce SW2 (règlage des heures) goto VERIF_TEMPS ; non, on continue incfsz heures,1 ; incrémentation des heures goto VERIF_TEMPS ; si pas de débordement, on vérifie l'horloge movlw MAXHRS ; réinitialisation des heures movwf heures goto VERIF_TEMPS ; affichage des données ; MISE_A_LHEURE bsf flags,SEC ; Les secondes, si elles sont affichées doivent être actualisées bsf flags,CHG ; il y a eu des changements incfsz seconds,1 ; incrémentation des secondes goto TEMPS_OK ; il n'y a pas eu de débordement, on saute movlw MAXSECS ; Débordement => réinitialisation des secondes movwf seconds ; bsf flags,MIN ; Les minutes doivent être réactualisées (si besoin) bsf flags,CHG ; il y a eu des changements ; movlw ADJMIN ; subwf sec_nth,1 ; Ajustement à chaque minute incfsz minutes,1 ; Incrémentation des minutes goto TEMPS_OK ; C'est OK jusqu'à FFH (fin de comptage) movlw MAXMINS ; Réinitialisation des minutes movwf minutes ; bsf flags,HRS ; les heures ont changé (bit d'état mis à 1) bsf flags,CHG ; il y a eu des changements ; movlw ADJHR ; addwf sec_nth,1 ; Ajustement à chaque heure incfsz heures,1 ; Incrémentation des heures goto TEMPS_OK ; C'est OK jusqu'à FFH (fin de comptage) movlw MAXHRS ; Réinitialisation des heures movwf heures ; movlw ADJDAY ; subwf sec_nth,1 ; Ajustement à chaque 1/2 journée (12h00) ; TEMPS_OK btfss flags,CHG ; Y a-t'il eu changement ? (digits ou interrupteurs) goto CYCLE ; non, alors on saute ; ; VERIF_SECONDES ; A-t'on appuyé sur les secondes ? (SW1) btfss flags,SW1 goto VERIF_TEMPS movlw 0 movwf digit1 ; le 3ème digit sert à stocker temporairement la valeur hexa des heures movwf digit2 movwf digit3 movlw MAXSECS subwf seconds,0 movwf digit0 ; le premier digit sert à stocker temporairement la valeur hexa des secondes goto SPLIT_HEX ; VERIF_TEMPS movlw 0 movwf digit3 ; On place un 0 dans les dizaines s'il n'y a pas d'incrémentation movwf digit1 movlw MINHRS subwf heures,0 ; le 3ème digit sert à stocker temporairement movwf digit2 ; la valeur hexa des heures movlw MAXMINS subwf minutes,0 ; le premier digit sert à stocker temporairement movwf digit0 ; la valeur hexa des minutes ; ; ; SPLIT_HEX ; séparation des variables d'affichage en 2 mots hexa movlw 2 movwf count ; boucle pour convertir chaque nombre en secondes, minutes et heures ; ; 1er passage : FSR = digit0, 2ème passage : FSR = digit2 ; movlw digit0 ; adresse du digit0 dans File Select Register movwf FSR ; et validation de POINTER goto BOUCLE ; Déplacement des minutes/secondes ; BOUCLE2 movlw digit2 movwf FSR ; Déplacement des heures ; BOUCLE movlw D'10' subwf POINTER,1 ; Comptage du nombre de dizaines btfsc STATUS,CARRY ; Il y a-t'il débordement (borrow) goto INCREMENT_10S ; si non, on ajoute 1 à la position des dizaines addwf POINTER,1 ; si oui, on ajoute 10 pour obtenir 1 seconde goto NEXT_DIGIT ; INCREMENT_10S incf FSR,1 ; bump address pointed to from 1s positoion to 10s incf POINTER,1 ; add 1 to 10s position as determined by previous subtract decf FSR,1 ; put POINTER value back to 1s place for next subtraction goto BOUCLE ; go back and keep subtracting until finished ; NEXT_DIGIT decfsz count,1 goto BOUCLE2 ; CONVERT_HEX_TO_DISPLAY ; conversion hexa -> décimal movlw digit0 movwf FSR ; Adresse du 1er digit dans FSR pour valider POINTER movlw H'4' movwf count ; Il y 4 afficheurs à gérer NEXT_HEX movf POINTER,0 ; Récupération de la valeur du digit (Hexa) call RENVOI_CODE ; Recherche du code dans la table des segments movwf POINTER ; Ecriture dans la variable digit incf FSR,1 ; Pointage vers le digit suivant decfsz count,1 ; A-t'on fait les 4 digits goto NEXT_HEX ; FIX_DISPLAY movlw ZEROT subwf digit3,0 btfss STATUS,Z_BIT ; les 4ème digit est-il nul ? goto FIX_SEC ; non, alors on l'affiche movlw BLANC ; oui, alors on le masque movwf digit3 FIX_SEC btfss flags,SW1 ; Est-on en mode d'affichage des secondes ? goto CLEAR_FLAGS ; non, on saute movwf digit2 ; oui, alors on n'affiche pas le 3ème digit ; CLEAR_FLAGS movlw H'F0' andwf flags,1 ; Effacement des 4 bits d'état de poids faible ; CYCLE movlw AFF_OFF movwf PORT_A ; Extinction des afficheurs movlw SWITCH BSF STATUS,RP0 ; Passage au banc mémoire 1 movwf TRISB ; Bits du port B en entrée (interrupteurs) BCF STATUS,RP0 ; Retour au banc mémoire 0 movlw H'0F' nop nop nop nop nop andwf flags,1 ; Réinitialisation du mot d'état movf PORT_B,0 xorlw H'FF' ; Complémentation des données movwf var btfss var,1 goto SWITCH2 bsf flags,CHG bsf flags,SW1 bsf flags,SW_ON SWITCH2 btfss var,2 goto SWITCH3 bsf flags,CHG bsf flags,SW2 bsf flags,SW_ON SWITCH3 btfss var,3 goto SETPORT bsf flags,CHG bsf flags,SW3 bsf flags,SW_ON ; SETPORT movlw 0 BSF STATUS,RP0 ; Passage au banc mémoire 1 movwf TRISB BCF STATUS,RP0 ; Retour au banc mémoire 0 movlw BLANC movwf PORT_B ; ; détermination de l'afficheur à réactualiser ; btfsc affiche,0 ; Est-ce le premier digit ? movf digit3,0 ; si oui, on le place dans w btfsc affiche,1 ; Est-ce le deuxième digit ? movf digit2,0 ; si oui, on le place dans w btfsc affiche,2 ; Est-ce le troisième digit ? movf digit1,0 ; si oui, on le place dans w btfsc affiche,3 ; Est-ce le quatrième digit ? movf digit0,0 ; si oui, on le place dans w movwf PORT_B ; on envoie w vers les afficheurs (Port B) btfsc sec_nth,7 bcf PORT_B,0 ; Clignotement des ":" (50 % du temps) movf affiche,0 ; Cycle d'affichage du digit concerné movwf PORT_A ; Validation de l'affichage rlf affiche,1 ; Rotation de l'affichage bcf affiche,0 ; on place un 0 dans le LSB btfsc affiche,4 ; A-t'on réactualisé les 4 digits bsf affiche,0 ; Si oui on réinitialise la variable affiche clrwdt ; goto MAIN ; RENVOI_CODE addwf PC,1 retlw ZEROT retlw UN retlw DEUX retlw TROIS retlw QUATRE retlw CINQ retlw SIX retlw SEPT retlw HUIT retlw NEUF END