‘Programme Horloge – Calendrier commenté '**************************************************************** '* Name : Horloge et calendrier XT OSC 3.BAS * '* Author : Claude Cossette, VE2APS * '* Notice : Copyright (c) 2003 [select VIEW...EDITOR OPTIONS] * '* : All Rights Reserved * '* Date de programmation : 11-01-2004 * '* Version : 1.2 * '* Notes : Oscillateur externe 4.194304 Mhz, division par 256 avec prescaler * '* Notes : et division par 256 avec TIMER0 ; LCD câblé par défaut * '* Notes : et PortB pattes 1 et 2 laissées libres pour usage ultérieur * '* Notes : modifié pour heure avancée et normale selon la Loi sur le temps légal en vigueur au Québec depuis le 2007-01-01 * '****************************************************************************************************************************** ‘ Fuses @ device PIC16F628,XT_OSC,WDT_OFF,MCLR_OFF,PWRT_ON,BOD_ON,LVP_OFF,CPD_OFF,PROTECT_OFF CCP1CON = 0 'Capture Compare OFF CMCON = 7 'Compare module OFF Pause 500 'Pause pour donner le temps à l'affichage LCD de démarrer 'Liste des variables Y var bit 'Variable auxiliaire pour test de l'heure normale ; c'est un drapeau Nodujour var byte 'Variable représentant le numéro du jour de la semaine 1= Dimanche Update var byte 'Variable auxiliaire relative au rafraîchissement du LCD B0 var byte 'Variable B0 pour debouncing des boutons de réglage de l'horloge Sec var byte 'Variable Secondes Minut var byte 'Variable Minutes Hre var byte 'Variable Heures Div_temps Var byte 'Variable Diviseur de temps dans la sous-routine ISR Jour var byte 'Variable Jour Mois var byte 'Variable Mois An var word 'Variable Année (Cette variable a 4 chiffres, il faut donc plus que 8 bits pour représenter sa valeur dans le système binaire ; voir manuel du compilateur PicBasic Pro page 21para.4.3 Variables) Nbjrmois var byte 'Variable Nombre de jours dans le mois W1 var byte 'Variable auxiliaire utilisée dans le test pour l'année bissextile 'Initialisation des variables et des Ports Update = 1 'Force le premier affichage au LCD Sec = 0:Minut = 0:Hre = 0:B0 = 0:Div_temps = 0 ‘Notez l’usage du symbole : pour séparer deux énoncés placés sur une même ligne, ce qui ne change pas la quantité de code généré (voir PBP Compiler manuel page 29 para 4.13. Multistatement lines) Jour = 1:Mois = 1:An = 2003:W1 = 1:Nbjrmois = 31:Nodujour = 1: Y = 0 ‘où y est un drapeau ‘Mise à zéro des ports A et B PortA = 0 'PortA mis à zéro pour fins de stabilisation ; très important avant de faire le TrisA ; à noter que aucun signe devant la valeur signifie une valeur exprimée dans le système décimal, un signe % devant la valeur signifie que celle-ci est exprimée dans le système décimal et un signe $ devant la valeur signifie que celle-ci est exprimée dans le système hexadécimal PortB = 0 'PortB mis à zéro pour fins de stabilisation ; très important avant de faire le TrisB ‘Définition des pattes sur les ports A et B TrisA = %11110000 'Le symbole % signifie que la valeur est exprimée dans le système binaire ; Sur PortA définition des pattes RA0 à RA3 en sortie car raccordées sur affichage LCD et RA4 à RA7 en entrée parce que c’est l’usage physique qu’on en fait (voir le schéma de câblage). Voir également le manuel PicBasic Pro Compiler pages 27 et 28 para 4.11. Pins ; 1 = en entrée et 0 = en sortie car ce faisant on agit sur le «registre Tris» de fonction spéciale du port TrisB = %11111011 'Sur le PortB les pattes RB0, RB1 et RB3 à RB7 sont définies en entrée car elles sont connectées sur les boutons et RB2 est en sortie car c’est l‘usage physique qu’on en fait (voir le schéma de câblage) 'Réglage de l'interrupt du TIMER0 'Réglage du prescaler dans l'Option Register pour diviser la fréquence de l'osc par 256. Il est intéressant de regarder la fig.14 dans le data sheet # DS40400C page 101 du Pic 16F628 où on explique la logique de l’Interrupt dans ce PIC. On y explique également que ce PIC offre 10 sources différentes d’interrupt. OPTION_REG = %10000111 ‘voir Microchip data sheet DS40300C page 20 ; les bits 0, 1 et2 étant réglés à 1 cela permet au TMR0 de diviser la fréquence de l’oscillateur par 256 ; bit 7 réglé à 1 fait que «PortA pull-ups are disabled» 'Initialisation du TIMER0 TMR0 = 0 ’Timer zéro mis à 0 'Réglage de l'interrupt control register pour que Timer0 puisse lever le drapeau au compte de 256 Intcon = %10100000 ‘voir Microchip data sheet DSC40300C page 21 ; bit 5 réglé à 1 c’est le TMR0 overflow enable bit et lorsque réglé à 1 «it enables the TMR0 interrupt» ; bit 7 réglé à 1 «it enables all unmasked interrupts». Pour encore mieux comprendre ça il faut regarder la fig. 14 dans le data sheet du Pic 16F628. ON Interrupt Goto ISR 'Si le drapeau de l'Interrupt control register est levé par l'overflow du TIMER0, branchement à la sous-routine ISR ‘Début de la boucle principale Main: 'Label marquant le début de la boucle principale B0 = 0 ' Variable qui doit être mise à zéro avant le départ de toute instruction «button» 'Vérifier si un des boutons de réglage de l'heure est pressé Button PortB.7,0,100,10,B0,1,Hreset 'Bouton de réglage manuel des heures voir note 1 au bas de la page 8 Button PortB.6,0,100,10,B0,1,Minutset 'Bouton de réglage manuel des minutes et des secondes simultanément 'Vérifier si un des boutons de réglage du calendrier est pressé (voir les explications sur le fonctionnement de l’instruction BUTTON à la page 9 du présent document) Button PortB.0,0,100,10,B0,1,Jourset 'Bouton de réglage manuel du jour Button PortB.5,0,100,10,B0,1,Moisset 'Bouton de réglage manuel du mois Button PortA.5,0,100,10,B0,1,Anset 'Bouton de réglage manuel de l'année 'Vérifier si le bouton de réglage du numéro du jour (lequel représente le nom du jour) est pressé [ici par convention Dimanche est le jour 1. Button PortB.4,0,100,10,B0,1,Nodujourset IF sec >= 60 Then Minut = Minut + 1:Sec = 0 'Si variable Sec >= 60 augmenter variable Minut de 1 et placer variable Sec à 0 ENDIF If Minut >= 60 Then Hre = Hre + 1:Minut = 0 'Si variable Minut >= 60 augmenter variable Hre de 1 et placer variable Minut à 0 ENDIF IF Hre >= 24 Then Hre = 0:Minut = 0:Sec = 0 'Si variable Hre >= 24 placer variables Sec, Minut et Hre à 0 Jour = Jour + 1 Nodujour = Nodujour + 1 ENDIF 'Vérifier si le numéro du jour de la semaine est plus grand que 7 IF Nodujour > 7 THEN Nodujour = 1 ENDIF 'Aller lire dans la mémoire du EEPROM le nombre de jours dans le mois LOOKUP Mois,[0,31,28,31,30,31,30,31,31,30,31,30,31],Nbjrmois 'Si on est dans le mois de février, vérifier si l'année est bissextile IF Mois = 2 THEN Testbissextile 'Vérifier si la variable Jour a dépassé le nombre de jours dans le mois Limitmois: IF Jour > Nbjrmois THEN Jour = 1:Mois = Mois + 1 ENDIF IF Mois > 12 THEN Mois = 1:An = An + 1 ENDIF 'Vérifier si l'année a dépassée l'année 2050 IF An > 2050 THEN Jour = 1:Mois = 1:An = 2003 ENDIF 'Vérifier si on est à l'heure avancé IF (Mois = 3) AND (Nodujour = 1) AND (Jour >= 8) AND (Hre = 2) THEN ‘L’opérateur (>=) signifie [plus grand ou égal à] voit manuel du compilateur Picbasic Pro page 36 para. 4.18 Comparison Operators ; pour les opérateurs logiques comme AND, OR etc., voir le manuel du compilateur PicBasic pro page 36 para. 4.19 Logical Operators Hre = Hre + 1 Y = 0 ‘abaisser le drapeau ENDIF 'Vérifier si on est à l'heure normale IF Y = 0 THEN Testhrenorm 'Début de l'affichage du temps sur le LCD (voir manuel de compilateur PicBasic Pro page 90 para. 5.36 LCDOUT) Affichage: 'Label marquant le début de l'affichage du temps IF Update = 1 THEN 'Variable Update utilisée pour forcer l'affichage des données si = 1 LCDOUT $fe, 1 ' Effacer l'affichage LCD LCDOUT dec2 Hre,":",dec2 Minut,":",dec2 Sec 'Afficher la valeur décimale à 2 chiffres pour chacune des variables Hre, Minut et Sec sous la forme HH:MM:SS LCDOUT $FE,$C0,dec1 Nodujour,":",dec2 Jour,":",dec2 Mois,":",dec4 An ‘ où une variable à chaîne comme les deux points ( :)  doivent être placés entre guillemets voir manuel du compilateur PicBasic Pro page 25 para. 4.8 Numéric Constants ENDIF Update = 0 'Interdit l'affichage des données au moment inopportun Goto Main 'Branchement inconditionnel à la boucle principale appelée «Main» 'Début de la sous-routine suite à un interrupt donné par l'overflow du TIMER0 ; elle permet de compter les levés du drapeau du TMR0 à tous les 1/16 sec dans l'intervalle de temps compris entre chaque seconde DISABLE 'Instruction requise pour éviter des interruptions à un moment inopportun ISR: 'Label ISR (Interrupt sub-routine) Div_temps = Div_temps + 1 'Augmenter d'une unité la variable Div_temps INTCON.2 = 0 'Reset le bit 2 du Interrupt control register qui correspond au TMR0 overflow interrupt flag bit, lequel doit être remis à 0 par software (voir PIC data sheet DS40300C page 21) IF Div_temps >= 16 Then Sec = Sec + 1:Div_temps = 0:Update = 1 'Si Div_temps = 16, augmenter variable Sec d'une unité et placer variable Div_temps à 0 ; rafraîchir l'écran LCD endif Resume 'Sortir de la sous-routine et retourner au programme principal 'Début du réglage manuel des heures Hreset: 'Label marquant le début du réglage manuel des heures Hre = Hre + 1 Pause 300 IF Hre >= 24 THEN Hre = 0 ENDIF Update = 1 'Autoriser l'affichage des données Goto Affichage ‘Début du réglage manuel des minutes Minutset: 'Label marquant le début du réglage manuel des minutes Minut = Minut + 1:sec = 0 Pause 300 'Délai pour nous donner le temps d'ajuster manuellement les minutes sur l'affichage IF Minut >= 60 THEN Minut = 0:sec = 0 ENDIF Update = 1 'Autoriser l'affichage des données Goto Affichage 'Branchement inconditionnel au label «Affichage» ‘Sous-routine pour tester si l’année en cours est bissextile Testbissextile: W1 = An // 4 ‘Les deux barres parallèles (//) signifient que le PIC effectue la division de «An» par 4 et il place le reste de la division dans la variable W1, ce reste est appelé «modulus»; voir manuel du compilateur PicBasic Pro page 32 para. 4.17.2 Division. IF W1 = 0 THEN Nbjrmois = 29 ENDIF GOTO Limitmois 'Début de la sous-routine du réglage manuel du calendrier car tous ces Labels sont associés aux boutons de réglage manuel des divers paramètres de l’horloge Jourset: Jour = Jour + 1 Pause 300 IF Jour > Nbjrmois THEN Jour = 1 ENDIF Update = 1 GOTO Affichage Moisset: Mois = Mois + 1 Pause 300 IF Mois > 12 THEN Mois = 1 ENDIF Update = 1 GOTO Affichage Anset: An = An + 1 Pause 300 IF An > 2050 THEN An = 2003 ENDIF Update = 1 ‘autorise la mise à jour de l’affichage lorsque la variable Update est égale à 1 GOTO Affichage Nodujourset: Nodujour = Nodujour + 1 PAUSE 300 IF Nodujour > 7 THEN Nodujour = 1 ENDIF Update = 1 GOTO Affichage ‘Sous-routine du test pour l’heure normale Testhrenorm: IF (Mois = 11) AND (Jour < 8) AND (Nodujour = 1) AND (Hre = 2) THEN Hre = Hre - 1 Y = 1 ‘Lever le drapeau Update = 1 PAUSE 300 ENDIF GOTO Affichage End 'Indique au compilateur la fin du programme Par Claude Cossette, VE2APS 2008-11-06