' nom : minuteur / thermometre / jeu / message défilant ' date : 12/09 ' auteur : vede ' cible : 16F877A ' program minuteur_v2 ' ' assigne des noms aux ports ' symbol BP_PLUS10 = PORTA.1 symbol BP_PLUS = PORTA.2 symbol BP_MOINS = PORTA.3 symbol BP_START = PORTA.4 ' symbol CATHODE_1 = PORTD.7 symbol CATHODE_2 = PORTD.5 symbol CATHODE_3 = PORTC.7 symbol CATHODE_4 = PORTC.5 symbol RELAIS = PORTE.0 symbol BUZZ_PORT = PORTE symbol BUZZ_PIN = 1 symbol OW_PORT = PORTE symbol OW_PIN = 2 ' symbol TEMPO = Delay_ms(1) ' ' déclare les variables utilisées ' const LETTRE as byte[4] = (%11101110, %11111110, %01110010, %01111110)' A,8,C,0 const FREQUENCE as word[4] = (220, 493, 1174, 1318) ' LA, SI, RE, MI ' dim tmp, temps as word ' vars "globales" dim adc2pwm, i as byte ' dim minutes, ' vars du minuteur secondes, sec_diz, sec_uni, demi_sec as byte ' dim flag_temperature, ' vars du thermometre degres, deg_cen, deg_diz, deg_uni, deg_dec as byte ' dim tableau as byte[51] ' vars du jeu et du message défilant dim freq as word dim vitesse, n, m, niveau, bouton as byte ' ' declare les procédures utilisées ' sub procedure alarme ' CATHODE_1 = 0 ' éteint les afficheurs CATHODE_2 = 0 CATHODE_3 = 0 CATHODE_4 = 0 while BP_START = 0 ' et fait "BIP BIP BIP BIP BIP BIP... " i=255 ' en attendant un appui sur SW4 (START) while (i) BUZZ_PORT.BUZZ_PIN=1 Delay_us(119) BUZZ_PORT.BUZZ_PIN=0 Delay_us(119) dec(i) wend Delay_ms(255) wend Delay_ms(255) end sub ' sub procedure affiche(dim n as byte) select case n case 0 PORTB = %01111110 case 1 PORTB = %00001100 case 2 PORTB = %10110110 case 3 PORTB = %10011110 case 4 PORTB = %11001100 case 5 PORTB = %11011010 case 6 PORTB = %11111010 case 7 PORTB = %00001110 case 8 PORTB = %11111110 case 9 PORTB = %11011110 case 10 PORTB = %10000000 ' signe moins (-) end select end sub ' sub procedure interrupt nop ' on laisse un peu de temps (environ 1µs à 4Mhz) nop ' au pic pour s'assurer qu'il ait le temps de ' dresser le drapeau (flag) de l'interruption... ' if testbit(PIR1,TMR1IF) = 1 then ' si interruption sur TMR1 dec(temps) ' décrémente temps if temps > 0 then TMR1L = 220 ' reactive interrupt TMR1 TMR1H = 11 PIR1.TMR1IF = 0 else RELAIS = 0 ' désactive relais T1CON = %000000 ' desactive interrupt TMR1 PIE1 = %00000000 PIR1 = %00000000 alarme() ' lance l'alarme ;O] INTCON = %10010000 ' et reactive interrupt RB0 end if end if ' if testbit(INTCON,INTF) = 1 then ' si interruption sur RB0 if BP_START = 1 then ' démarre le minuteur si BP START appuyé TMR1L = 220 ' réglage du TMR1 pour générer TMR1H = 11 ' une temporisation de 500ms... T1CON = %110001 ' activation du TMR1, avec PreScaler=8 INTCON = %11000000 ' activation interruptions peripheriques PIE1 = %00000001 ' activation interruption du TMR1 RELAIS = 1 ' active le relais if temps = 0 then temps = 1199 end if ' 9'59'5 (10MN) if temps > 1199 then temps = 1199 end if else if BP_PLUS = 1 then inc(temps) ' incrémente le temps ( 1/2 seconde ) end if if BP_MOINS = 1 then if temps > 0 then dec(temps) ' décrémente le temps ( 1/2 seconde ) end if end if if BP_PLUS10 = 1 then temps = temps + 20 ' incrémente le temps ( 10 secondes ) end if INTCON.INTF = 0 ' reactive interrupt RB0 end if Delay_ms(10) ' anti-rebonds logiciel end if ' if temps > 1199 then temps = 1199 end if demi_sec = 0 ' decodage du temps pour son bon affichage tmp = temps if tmp MOD 2 = 1 then demi_sec = 5 dec(tmp) end if tmp = tmp DIV 2 minutes = tmp DIV 60 secondes = tmp MOD 60 sec_diz = secondes DIV 10 sec_uni = secondes MOD 10 end sub ' ' début du programme : initialise et configure les ports ' main: TrisA = %00011111 ' met RA0-RA4 en entrées, les autres en sorties TrisB = %00000001 ' met RB0 en entrée, les autres en sorties TrisC = %00000000 ' met tous les ports C en sorties TrisD = %00000000 ' met tous les ports D en sorties TrisE = %00000000 ' met tous les ports E en sorties PortA = %00000000 ' met tous les ports A à 0 PortB = %00000000 ' met tous les ports B à 0 PortC = %00000000 ' met tous les ports C à 0 PortD = %00000000 ' met tous les ports D à 0 PortE = %00000000 ' met tous les ports E à 0 ' ADCON0 = %00000001 ' initialisation du convertisseur analogique et sa ADCON1 = %00001110 ' configuration pour l'utilisation de PortA.0 en ADC ' PR2 = 127 ' configuration PWM : config. TMR2 T2CON = %00000100 ' configuration PWM : start TMR2 CCP1CON = %001100 ' configuration PWM : start PWM ' ADCON0.GO = 1 ' lance conversion ADC TEMPO ' on récupére la valeur du potard pour la pwm... CCPR1L = ADRESH DIV 2 ' module le signal PWM avec ADC ' STATUS = %00000000 ' soft reset ' if BP_START = 1 then goto temperature ' no comment ;O] end if if BP_PLUS10 = 1 then goto lejeu ' no comment ;O] end if ' ' initialise le minuteur ' tmp = 0 temps = 0 minutes = 0 secondes = 0 sec_diz = 0 sec_uni = 0 demi_sec = 0 INTCON = %10010000 ' active interruption sur RB0 ' ' programme principal "minuteur", qui affiche ' le temps, dans une boucle infinie... ' while true affiche(minutes) CATHODE_4 = 0 CATHODE_1 = 1 ADCON0.GO = 1 ' lance conversion ADC TEMPO affiche(sec_diz) CATHODE_1 = 0 CATHODE_2 = 1 adc2pwm = ADRESH ' récupére résultat conversion ADC TEMPO affiche(sec_uni) CATHODE_2 = 0 CATHODE_3 = 1 adc2pwm = adc2pwm DIV 2 ' "traite" résultat ADC TEMPO affiche(demi_sec) CATHODE_3 = 0 CATHODE_4 = 1 CCPR1L = adc2pwm ' module le signal PWM avec ADC TEMPO wend ' return ' ' initialise le thermométre ' temperature: degres = 0 deg_cen = 0 deg_diz = 0 deg_uni = 0 deg_dec = 0 flag_temperature = 0 ' init. flag ow_reset(OW_PORT, OW_PIN) ' onewire reset ow_write(OW_PORT, OW_PIN, $CC) ' command to DS18B20 ow_write(OW_PORT, OW_PIN, $4E) ' demande envoi 3 bits de config. ow_write(OW_PORT, OW_PIN, $65) ' envoi TH : alarme Température Haute ow_write(OW_PORT, OW_PIN, $81) ' envoi TL : alarme Température Basse ow_write(OW_PORT, OW_PIN, $0) ' envoi demande résolution sur 9 bits ow_reset(OW_PORT, OW_PIN) ' onewire reset ow_write(OW_PORT, OW_PIN, $CC) ' command to DS18B20 ow_write(OW_PORT, OW_PIN, $48) ' copy scratchpad ow_reset(OW_PORT, OW_PIN) ' onewire reset ow_write(OW_PORT, OW_PIN, $CC) ' command to DS18B20 ow_write(OW_PORT, OW_PIN, $44) ' demande conversion température ' ' programme principal "thermometre", qui affiche ' la température, dans une boucle infinie... ' while true affiche(deg_cen) CATHODE_4 = 0 CATHODE_1 = 1 ' ADCON0.GO = 1 ' lance conversion ADC if flag_temperature = 0 then ' conversion température ow_reset(OW_PORT, OW_PIN) ' onewire reset ow_write(OW_PORT, OW_PIN, $CC) ' command to DS18B20 ow_write(OW_PORT, OW_PIN, $44) ' demande conversion température flag_temperature = 1 i = 50 end if TEMPO ' affiche(deg_diz) CATHODE_1 = 0 CATHODE_2 = 1 ' adc2pwm = ADRESH ' récupére résultat conversion ADC if flag_temperature = 1 then dec(i) if i = 0 then ' "attente" i cycles fin conversion temperature flag_temperature = 2 end if end if TEMPO ' affiche(deg_uni) CATHODE_2 = 0 CATHODE_3 = 1 ' adc2pwm = adc2pwm DIV 2 ' "traite" résultat conversion ADC if flag_temperature = 2 then ' lis la température ow_reset(OW_PORT, OW_PIN) ' onewire reset ow_write(OW_PORT, OW_PIN, $CC) ' command to DS18B20 ow_write(OW_PORT, OW_PIN, $BE) ' lecture température deg_diz = ow_read(OW_PORT, OW_PIN) ' lit 1 er octet du scratchpad deg_uni = ow_read(OW_PORT, OW_PIN) ' lit 2 éme octet du scratchpad flag_temperature = 3 end if TEMPO ' affiche(deg_dec) CATHODE_3 = 0 CATHODE_4 = 1 ' CCPR1L = adc2pwm ' module le signal PWM avec ADC if flag_temperature = 3 then ' décodage de la temperature pour son deg_cen = 0 ' bon affichage sur les afficheurs... deg_dec = 0 if deg_uni.7 = 1 then ' teste si négative deg_diz = not deg_diz inc(deg_diz) deg_uni = not deg_uni deg_cen = 10 ' signe moins (-) end if if deg_diz.3 = 1 then ' teste si décimale deg_dec = 5 end if deg_diz = deg_diz >> 4 deg_uni = deg_uni << 4 degres = deg_diz + deg_uni if degres > 99 then deg_cen = 1 degres = degres - 100 end if deg_diz = degres DIV 10 deg_uni = degres MOD 10 flag_temperature = 0 end if TEMPO ' wend ' ' initialise le jeu ' lejeu: vitesse=33 delay_ms(300) if BP_PLUS10 = 1 then delay_ms(500) if BP_PLUS10 = 1 then delay_ms(900) if BP_PLUS10 = 1 then goto gagne ' mode "message defilant" end if end if end if ' gosub debut Sound_Init(BUZZ_PORT, BUZZ_PIN) ' Initialize sound at RD2 jeu: PORTD = %00000000 PORTC = %00000000 tableau[0] = 0 i = i + PCL tableau[1] = i MOD 4 tmp = 510 niveau = 1 n = 0 ' ' pogramme principal du jeu ' joue: m = tableau[n] freq = FREQUENCE[m] PORTB = LETTRE[m] select case m case 0 CATHODE_1 = 1 case 1 CATHODE_2 = 1 case 2 CATHODE_3 = 1 case 3 CATHODE_4 = 1 end select Sound_Play(freq, tmp) ' Play the sound temps = tmp DIV 2 PORTD = %00000000 PORTC = %00000000 Vdelay_ms(temps) inc(n) if n < niveau then goto joue end if n = 0 joueur: while PortB.0 = 0 inc(i) wend m = PortA if m.1=1 then bouton=0 end if if m.2=1 then bouton=1 end if if m.3=1 then bouton=2 end if if m.4=1 then bouton=3 end if freq = FREQUENCE[bouton] PORTB = LETTRE[bouton] select case bouton case 0 CATHODE_1 = 1 case 1 CATHODE_2 = 1 case 2 CATHODE_3 = 1 case 3 CATHODE_4 = 1 end select Sound_Play(freq, tmp) ' Play the sound PORTD = %00000000 PORTC = %00000000 while PortB.0 = 1 wend ' if bouton <> tableau[n] then gosub perdu goto jeu end if ' inc(n) if n < niveau then goto joueur end if ' inc(niveau) if niveau = 50 then goto gagne end if ' i = i + PCL tableau[niveau] = i MOD 4 ' pseudo random tmp = tmp - 10 delay_ms(500) n = 0 goto joue ' debut: PORTB = %10000000 ' affiche "----" en attendant un appui sur start pour jouer while BP_START=0 CATHODE_4 = 0 CATHODE_1 = 1 ADCON0.GO = 1 ' lance conversion ADC TEMPO CATHODE_1 = 0 CATHODE_2 = 1 adc2pwm = ADRESH ' récupére résultat conversion ADC TEMPO CATHODE_2 = 0 CATHODE_3 = 1 adc2pwm = adc2pwm DIV 2 ' "traite" résultat ADC TEMPO CATHODE_3 = 0 CATHODE_4 = 1 CCPR1L = adc2pwm ' module le signal PWM avec ADC TEMPO inc(i) wend return ' perdu: ' affiche "NULL" en attendant appui sur start pour rejouer while BP_START=0 PORTB = %01101110 'N CATHODE_4 = 0 CATHODE_1 = 1 ADCON0.GO = 1 ' lance conversion ADC TEMPO PORTB = %01111100 'U CATHODE_1 = 0 CATHODE_2 = 1 adc2pwm = ADRESH ' récupére résultat conversion ADC TEMPO PORTB = %01110000 'L CATHODE_2 = 0 CATHODE_3 = 1 adc2pwm = adc2pwm DIV 2 ' "traite" résultat ADC TEMPO PORTB = %01110000 'L CATHODE_3 = 0 CATHODE_4 = 1 CCPR1L = adc2pwm ' module le signal PWM avec ADC TEMPO wend return ' ' initialise le message défilant ' gagne: tableau[0] = %00011100 'J tableau[1] = %01111110 'O tableau[2] = %11011100 'Y tableau[3] = %11110010 'E tableau[4] = %01111100 'U tableau[5] = %00000000 ' tableau[6] = %01101110 'N tableau[7] = %01111110 'O tableau[8] = %11110010 'E tableau[9] = %01110000 'L tableau[10] = %00000000 ' tableau[11] = %10110110 '2 tableau[12] = %01111110 'O tableau[13] = %01111110 '0 tableau[14] = %11011110 '9 tableau[15] = %00000000 ' tableau[16] = %10000000 '- tableau[17] = %00000000 ' tableau[18] = %01101110 'N tableau[19] = %01111110 'O tableau[20] = %11011100 'Y tableau[21] = %11110010 'E tableau[22] = %01111100 'U tableau[23] = %00000000 ' tableau[24] = %00011100 'J tableau[25] = %01111110 'O tableau[26] = %11110010 'E tableau[27] = %01110000 'L tableau[28] = %00000000 ' tableau[29] = %10110110 '2 tableau[30] = %01111110 'O tableau[31] = %01111110 '0 tableau[32] = %11011110 '9 tableau[33] = %00000000 ' tableau[34] = %10000000 '- tableau[35] = %00000000 ' tableau[36] = %00011100 'J tableau[37] = %01111110 'O tableau[38] = %11011100 'Y ' ' programme principal message défilant ' defile: i = vitesse while i PORTB = tableau[niveau] CATHODE_4 = 0 CATHODE_1 = 1 TEMPO ADCON0.GO = 1 ' lance conversion ADC PORTB = tableau[niveau+1] CATHODE_1 = 0 CATHODE_2 = 1 TEMPO vitesse = ADRESH ' récupére résultat conversion ADC PORTB = tableau[niveau+2] CATHODE_2 = 0 CATHODE_3 = 1 TEMPO if vitesse<3 then vitesse=2 end if 'change la vitesse PORTB = tableau[niveau+3] CATHODE_3 = 0 CATHODE_4 = 1 TEMPO dec(i) wend inc(niveau) if niveau = 36 then niveau = 0 end if goto defile ' end.