Aquest rellotge, a més de permetre ajustar l'hora, fa senyals lluminosos i acústics per indicar cada quart d'hora.
El programa final és:
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
cblock 0x20
AdreI2C ; Adreça del dispositiu I2C
AdreMem ; Adreça de la memoria on volem llegir o escriure
Dades ; Dades que volem llegir o escriure
Port ; Valor a escriure al port C
; RC7 es SDA
; RC6 es SCL
Buffer ; Variable emprada per les funcions de llegir i escriure
Bits ; Compta els bits que es van rebent o enviant
Caracter ; Caracter o codi a enviar a la pantalla
Retard1 ; Variables de retard
Retard2
Retard3
Retard4
Retard5
Polsador ; Variable per comprovar els polsadors
Modif ; Variable que pren per valor 1, 2, ..., 7 que indica que s'està modificant
Desenes ; Variable que guarda les desenes de la funcio Convertir
Unitats ; Variable que guarda les unitats de la funció Convertir
Resul ; Variable que emmagatzema el resultat en decimal
Temp ; Variable de la funcio Convertir
D1 ; Variable que guarda les unitats de la funcio Reconvertir
D2 ; Variable que guarda les desenes de la funcio Reconvertir
ValPR2 ; Aqui hi guardarem el valor de PR2
ValCCPR1L ; Aqui hi guardarem el valor de CCPR1L
ValDC1B ; Aqui hi guardarem el valor de DC1B
ValCCP1CON ; Aqui hi guardarem el valor de CCP1CON
M ; Per comprovar si M esta activada per tocar l'hora en punt
K ; Per comprovar els polsadors amb mes frequencia quan estem modificant l'hora o la data
Kaka ; Per comprovar el polsador 1 dins la funcio Modificar
N ; Per comprovar si N esta activada per tocar el primer quart
O ; Per comprovar si O esta activada per tocar el segon quart
Pe ; Per comprovar si Pe esta activada per tocar el tercer quart
Encen1 ; Per encendre nomes durant una estona els LED pel primer quart
Encen2 ; Per encendre nomes durant una estona els LED pel segon quart
Encen3 ; Per encendre nomes durant una estona els LED pel tercer quart
Encen4 ; Per encendre nomes durant una estona els LED per l'hora en punt
endc
org 0
Inici
bsf STATUS,RP1 ; Tria el banc 2
movlw b'00000101'
movwf ANSEL ; Configura AN0 i AN2 com entrada anal?gica
clrf ANSELH ; Desactiva les altres entrades anal?giques
bcf STATUS,RP1
bsf STATUS,RP0 ; Tria el banc 1
movlw 0xFF ; Posa l'acumulador a FFh (tot uns)
movwf TRISA ; Posa tots els bits del port A com a entrada
clrf TRISB ; Tot el port B ?s de sortida
clrf TRISC ; Tot el port C ?s de sortida
bsf TXSTA,BRGH ; Configuraci? de velocitat
bcf BAUDCTL,BRG16 ; Par?metre de velocitat de 8 bits
movlw .25 ; Velocitat de 9600 baud
movwf SPBRG ; Par?metre de velocitat
bcf TXSTA,SYNC ; Comunicaci? as?ncrona
bcf TXSTA,TX9 ; Comunicaci? de 8 bits
movlw b'00010000' ; Posa el conversor a 1/8 de la freq??ncia
movwf ADCON1 ; Copia W a la configuraci? del conversor A/D
bcf STATUS,RP0 ; Tria el banc 0
bsf RCSTA,SPEN ; Activa comunicaci? s?rie
bsf STATUS,RP0 ; Tria el banc 1
bsf TXSTA,TXEN ; Activa comunicaci?
bcf STATUS,RP0 ; Tria el banc 0
clrf PORTB ; Posa a zero totes les sortides del port B
clrf PORTC ; Posa a zero totes les sortides del port C
clrf Port ; Posa a zero tots els bits de Port
movlw b'01101000' ; Adre?a del m?dul RTC
movwf AdreI2C ; Ho guarda com a adre?a I2C
; Com a mostra, es posen les 23.59.50
; del dijous 31-3-2016
; per poder veure un canvi de dia i de mes
movlw .0 ; Segons
movwf AdreMem
movlw 0x50 ; 50
movwf Dades
call EscriuI2C
movlw .1 ; Minuts
movwf AdreMem
movlw 0x59 ; 59
movwf Dades
call EscriuI2C
movlw .2 ; Hores
movwf AdreMem
movlw 0x23 ; 23
movwf Dades
call EscriuI2C
movlw .3 ; Dia setmana
movwf AdreMem
movlw 0x04 ; Dijous
movwf Dades
call EscriuI2C
movlw .4 ; Dia mes
movwf AdreMem
movlw 0x31 ; 31
movwf Dades
call EscriuI2C
movlw .5 ; Mes
movwf AdreMem
movlw 0x03 ; Mar?
movwf Dades
call EscriuI2C
movlw .6 ; Any
movwf AdreMem
movlw 0x16 ; 2016
movwf Dades
call EscriuI2C
movlw .7 ; Polsos
movwf AdreMem
movlw 0x00 ; Desactivat
movwf Dades
call EscriuI2C
movlw b'00001001' ; activa el conversor A/D connectat a AN2
movwf ADCON0 ; amb el resultat justificat per l'esquerra
clrf Modif ; Posa a 0 variable
movlw b'00000001' ; W = 1
movwf M ; Ho guarda a la variable, M=1
movwf N ; Ho guarda a la variable, N = 1
movwf O ; Ho guarda a la variable, O = 1
movwf Pe ; Ho guarda a la variable, Pe = 1
; INICI BUCLE DEL PROGRAMA
Bucle
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
call Horaenpunt ; Mira si es l'hora en punt per tocar el brunzidor i encendre LED
call PrimerQuart ; Mira si es un quart per tocar el brunzidor i encendre LED
call SegonQuart ; Mira si son dos quarts per tocar el brunzidor i encendre LED
call TercerQuart ; Mira si son tres quarts per tocar el brunzidor i encendre LED
; Comprovar variable modif
movf Modif,f ; Modif = 0 ?
btfss STATUS,Z ; Si Modif es 0, salta
goto nozero ; Si Modif no es 0, va a l'etiqueta nozero
sizero ; Comprova el polsador 1
call Llegir ; Llegeix els polsadors
movf Polsador,w
xorlw b'00000001' ; Mirem si s'ha premut el 1
btfss STATUS,Z ; Si es el 1, salta
goto Bucle ; No es el 1, torna a l'etiqueta Bucle
movlw b'00000001' ; W = 1
movwf Modif ; Ho guarda a la variable, Modif = 1
nozero
call Modificar ; Crida la funcio que permet modificar l'hora i la data, el
; valor que modifiquem fa pampallugues a la pantalla
goto Bucle ; Torna a fer el Bucle de nou
; FUNCIONS
; INICI FUNCIO MODIFICAR
Modificar
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
; bucle de la variable Modif
movlw b'00000001' ; W = 1
xorwf Modif,w ; Preguntem si Modif = 1
btfss STATUS,Z ; Si es igual a 1, salta
goto NoIguals1 ; Si no es igual a 1, va a l'etiqueta NoIguals1
Iguals1 ; El dia fa pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola1
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0 salta
goto Kno0 ; Si K no es 0, va a l'etiqueta Kno0
K0 ; Mostra el dia a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .0 ; Filera 1 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .4 ; Dia
movwf AdreMem
call LlegirI2C ; Llegeix el dia del microcontrolador
call HEXtoBCD ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno0
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno2 ; Si no es igual a 2, va a l'etiqueta Kno2
; espai en blanc
K2 ; Mostra dos espais en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .0 ; Filera 1 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
call EnviaL ; Ho envia
Kno2
movlw b'00000001' ; Retard 0,2
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0 salta
goto NoIguals1 ; Si Kaka no es 0, va a l'etiqueta NoIguals1
Kaka01 ;
decf K,f ; K=K-1
goto Hola1
NoIguals1
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000010' ; W = 2
xorwf Modif,w ; Preguntem si Modif = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto NoIguals2 ; Si no es igual a 2, va a l'etiqueta NoIguals2
Iguals2 ; El mes fa pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola2
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0 salta
goto Kno02 ; Si K no es 0, va a l'etiqueta Kno02
K02 ; Mostra el mes a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .3 ; Filera 1 columna 4
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .5 ; Mes
movwf AdreMem
call LlegirI2C ; Llegeix el mes del microcontrolador
call HEXtoBCD ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno02
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno22 ; Si no es igual a 2, va a l'etiqueta Kno22
; espai en blanc
K22 ; Mostra dos espais en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .3 ; Filera 1 columna 4
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
call EnviaL ; Ho envia
Kno22
movlw b'00000001' ; Retard 0,2
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0 salta
goto NoIguals2 ; Si Kaka no es 0, va a l'etiqueta NoIguals2
Kaka02
decf K,f ; K=K-1
goto Hola2
NoIguals2
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000011' ; W = 3
xorwf Modif,w ; Preguntem si Modif = 3
btfss STATUS,Z ; Si es igual a 3, salta
goto NoIguals3 ; Si no es igual a 3, va a l'etiqueta NoIguals3
Iguals3 ; L'any fa pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola3
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0, salta
goto Kno03 ; Si K no es 0, va a l'etiqueta Kno03
K03 ; Mostra l'any a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .6 ; Filera 1 columna 7
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw '2' ; Any primer digit
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw '0' ; Any segon digit
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .6 ; Any
movwf AdreMem
call LlegirI2C ; Llegeix l'any (ultims dos digits) del microcontrolador
call HEXtoBCD ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno03
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno23 ; Si no es igual a 2, va a l'etiqueta Kno23
; espai en blanc
K23 ; Mostra quatre espais en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .6 ; Filera 1 columna 7
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
call EnviaL ; Ho envia
call EnviaL ; Ho envia
call EnviaL ; Ho envia
Kno23
movlw b'00000001' ; Retard 0,2 segons
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0, salta
goto NoIguals3 ; Si Kaka no es 0, va a l'etiqueta NoIguals3
Kaka03
decf K,f ; K=K-1
goto Hola3
NoIguals3
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000100' ; W = 4
xorwf Modif,w ; Preguntem si Modif = 4
btfss STATUS,Z ; Si es igual a 4, salta
goto NoIguals4 ; Si no es igual a 4, va a l'etiqueta NoIguals4
Iguals4 ; El dia de la setmana fa pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola4
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0, salta
goto Kno04 ; Si K no es 0, va a l'etiqueta Kno04
K04 ; Mostra el dia de la setmana a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .12 ; Filera 1 columna 13
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .3 ; Dia setmana
movwf AdreMem
call LlegirI2C ; Llegeix el dia de la setmana del microcontrolador
call Hex1 ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno04
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno24 ; Si no es igual a 2, va a l'etiqueta Kno24
; espai en blanc
K24 ; Mostra un espai en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .12 ; Filera 1 columna 13
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
Kno24
movlw b'00000001' ; Retard 0,2
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0 salta
goto NoIguals4 ; Si Kaka no es 0, va a l'etiqueta NoIguals4
Kaka04
decf K,f ; K=K-1
goto Hola4
NoIguals4
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000101' ; W = 5
xorwf Modif,w ; Preguntem si Modif = 5
btfss STATUS,Z ; Si es igual a 5, salta
goto NoIguals5 ; Si no es igual a 5, va a l'etiqueta NoIguals5
Iguals5 ; L'hora fa pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola5
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0, salta
goto Kno05 ; Si K no es 0, va a l'etiqueta Kno05
K05 ; Mostra l'hora a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .64 ; Filera 2 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .2 ; Hores
movwf AdreMem
call LlegirI2C ; Llegeix l'hora del microcontrolador
call HEXtoBCD ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno05
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno25 ; Si no es igual a 2, va a l'etiqueta Kno25
; espai en blanc
K25 ; Mostra dos espais en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .64 ; Filera 2 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
call EnviaL ; Ho envia
Kno25
movlw b'00000001' ; Retard 0,2
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0 salta
goto NoIguals5 ; Si Kaka no es 0, va a l'etiqueta NoIguals5
Kaka05
decf K,f ; K=K-1
goto Hola5
NoIguals5
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000110' ; W = 6
xorwf Modif,w ; Preguntem si Modif = 6
btfss STATUS,Z ; Si es igual a 6, salta
goto NoIguals6 ; Si no es igual a 6, va a l'etiqueta NoIguals6
Iguals6 ; Els minuts fan pampallugues
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Hola6
movf K,f ; K = 0 ?
btfss STATUS,Z ; Si K es 0 salta
goto Kno06 ; Si K no es 0, va a l'etiqueta Kno06
K06 ; Mostra els minuts a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .67 ; Filera 2 columna 4
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador
call HEXtoBCD ; Ho mostra a la pantalla
movlw b'00000100' ; W = 4
movwf K ; Ho guarda a la variable, K = 4
Kno06
movlw b'00000010' ; W = 2
xorwf K,w ; Preguntem si K = 2
btfss STATUS,Z ; Si es igual a 2, salta
goto Kno26 ; Si no es igual a 2, va a l'etiqueta Kno26
K26 ; Mostra dos espais en blanc a la pantalla
movlw .254 ; Control de la posicio del cursor
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw .67 ; Filera 2 columna 4
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
movlw ' ' ; Espai en blanc a l'acumulador
movwf Caracter ; Ho guarda a la variable Caracter
call EnviaL ; Ho envia
call EnviaL ; Ho envia
Kno26
movlw b'00000001' ; Retard 0,2
call Rets
clrf Kaka ; Kaka = 0
call Comprova ; Comprovem tots els polsadors
movf Kaka,f ; Kaka = 0 ?
btfss STATUS,Z ; Si Kaka es 0 salta
goto NoIguals6 ; Si Kaka no es 0, va a l'etiqueta NoIguals6
Kaka06
decf K,f ; K=K-1
goto Hola6
NoIguals6
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000111' ; W = 7
xorwf Modif,w ; Preguntem si Modif = 7
btfss STATUS,Z ; Si es igual a 7, salta
goto NoIguals7 ; Si no es igual a 7, va a l'etiqueta NoIguals7
Iguals7 ; Reinicialitzem els segons a 0 i Modif = 0
movlw .0 ; Segons
movwf AdreMem
movlw 0x00 ; W = 00
movwf Dades ; Ho guarda a la variable, Dades = 00
call EscriuI2C ; Escriu al microcontrolador el que hi ha a la variable Dades
clrf Modif ; Modif = 0
return
NoIguals7
goto Modificar
; FI DE LA FUNCIO MODIFICAR
; INICI FUNCIO CONVERTIR
Convertir ; Converteix el que hi ha a la variable Dades a decimal
swapf Dades,w ; Gira el valor del que hi ha a Dades
andlw 0x0F
movwf Desenes ; Ho guarda a la variable Desenes
movf Dades,w ; Guarda Dades a l'acumulador
andlw 0x0F
movwf Unitats ; Ho guarda a la variable Unitats
rlf Desenes,w ; Multiplica les desenes per 2 i guarda resultat acumulador
movwf Resul ; Copia el valor de l'acumulador a la variable Resul
movwf Temp ; Copia el valor de l'acumulador a la variable Temp
rlf Temp,f ; Multiplica Temp per dos i guarda el resultat a la variable Temp
rlf Temp,w ; Multiplica Temp per dos i guarda el resultat a l'acumulador
addwf Resul,f ; Ara suma Resul+Acumulador(el que hi havia a la variable Temp)
movf Unitats,w ; Copia valor unitats a l'acumulador
addwf Resul,f ; Resul (valor decimal) = Unitats + Resul
return
; FI FUNCIO CONVERTIR
; INICI FUNCIO RECONVERTIR
Reconvertir
clrf D2 ; Posa D2 (desenes) a zero
movwf D1 ; Guarda W (valor a convertir) a D1
; D1 son les unitats
Desen ; Anem a trobar les desenes
movlw .10 ; Carrega 10 decimal a W
subwf D1,w ; Li resta W a D1
btfss STATUS,C ; Mira C i si es 1 no fa la seguent
; Si es 1 vol dir resultat positiu
goto Final ; Si el resultat es negatiu les desenes ja estan
; el valor de W es perd i anem a ASCII
movwf D1 ; Guarda el resultat (W) a D1
incf D2,f ; La desena restada a D1 l'afegeix a D2
goto Desen ; Tornem-ho a fer
Final
swapf D2,w ; Gira el que hi ha a la variable D2 i ho guarda a l'acumulador
movwf Dades ; Ho guarda a la variable Dades
movf D1,w ; Posa el que hi ha a D1 a l'acumulador
iorwf Dades,f ; Dades = W + Dades
movf Dades,w ; Posa Dades a l'acumulador
return
; FI FUNCIO RECONVERTIR
; INICI FUNCIO INCREMENTAR (POLSADOR 2)
Inc
call LlegirI2C ; Llegeix el que hi ha al microcontrolador
call Convertir ; Converteix el que hi ha a Dades a decimal
incf Resul,f ; Incrementa en 1 Resul i guarda resultat a la variable Resul
movf Resul,w ; Copia el valor de Resul a l'acumulador
call Reconvertir ; Reconverteix el valor de Resul per poder-lo escriure a la pantalla
call EscriuI2C ; Escriu el que hi ha a Dades al microcontrolador
return
; FI FUNCIO INCREMENTAR
; INICI FUNCIO DECREMENTAR (POLSADOR 3)
Dec
call LlegirI2C ; Llegeix el que hi ha al microcontrolador
call Convertir ; Converteix el que hi ha a Dades a decimal
decf Resul,f ; Incrementa en 1 Resul i guarda resultat a la variable Resul
movf Resul,w ; Copia el valor de Resul a l'acumulador
call Reconvertir ; Reconverteix el valor de Resul per poder-lo escriure a la pantalla
call EscriuI2C ; Escriu el que hi ha a Dades al microcontrolador
return
; FI FUNCIO DECREMENTAR
; INICI FUNCIÓ COMPROVA
Comprova ; Mirem si estan premuts els polsadors
; Mirem el polsador 1
call Llegir ; Llegeix els polsadors
movf Polsador,w
xorlw b'00000001' ; Mirem si s'ha premut el 1
btfss STATUS,Z ; Si es el 1, salta
goto Polsador2 ; No es el 1, va a l'etiqueta Polsador2
incf Modif,f ; Modif = Modif + 1
movlw b'00000001' ; W = 1
movwf Kaka ; Ho guarda a la variable, Kaka = 1
Polsador2 ; Es comprova el polsador 2
movf Polsador,w
xorlw b'00000010' ; Mirem si s'ha premut el 2
btfss STATUS,Z ; Si es el 2, salta
goto Polsador3 ; No es el 2, va a l'etiqueta Polsador3
call Inc ; Crida la funcio Inc que incrementa en un el que s'esta modificant
Polsador3 ; Es comprova el polsador 3
movf Polsador,w
xorlw b'00000100' ; Mirem si s'ha premut el 3
btfss STATUS,Z ; Si es el 3, salta
return ; No es el 3, retorna
call Dec ; Crida la funcio Dec que decrementa en un el que s'esta modificant
return
; FI FUNCIO COMPROVA
; En les seguents funcions comprovem si és hora en punt o qualsevol
; dels quarts per tocar el brunzidor i encendre els LED
; INICI FUNCIO HORAENPUNT
Horaenpunt
movlw b'00000001' ; W=1
xorwf M,w ; Preguntem si M = 1
btfss STATUS,Z ; Si M=1, salta
goto NoZero2 ; Si M no es 1, va a l'etiqueta NoZero2
Migual1 ; M = 1
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegim els minuts (en aquest cas) del microcontrolador i ho guarda a Dades
movlw 0x00 ; W = 00
xorwf Dades,w ; Preguntem si Dades = 00
btfss STATUS,Z ; Si es igual a 00, salta
goto NoZero2 ; Si no es igual a 00, va a l'etiqueta NoZero2
Zero2 ; Toquen 3 notes a traves del brunzidor i s'encenen 4 LED
call Brunzidor ; Crida la funcio Brunzidor
call Led4 ; Crida la funcio Led4
clrf M ; M = 0
NoZero2
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador
movlw 0x59 ; W = 59
xorwf Dades,w ; Preguntem si Dades = 59
btfss STATUS,Z ; Si Dades es 59, salta
goto No59 ; Si Dades no es 59, va a l'etiqueta No59
Si59 ; S'activa la variable M
movlw b'00000001' ; W = 1
movwf M ; Ho guarda a la variable, M = 1
No59
return
; FI FUNCIO HORAENPUNT
; INICI FUNCIO PRIMERQUART: Quan son un quart,
; sona el brunzidor i s'encen un LED
PrimerQuart
movlw b'00000001' ; W = 1
xorwf N,w ; Preguntem si N = 1
btfss STATUS,Z ; Si N=1, salta
goto NoZeroN ; Si N no es 1, va a l'etiqueta NoZeroN
Nigual1 ; N = 1
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x15 ; W = 15
xorwf Dades,w ; Preguntem si Dades = 15
btfss STATUS,Z ; Si Dades es 15, salta
goto NoZeroN ; Si Dades no es 15, va a l'etiqueta NoZeroN
ZeroN ; El brunzidor toca i s'encen un LED
call Brunzidor2 ; Crida la funcio Brunzidor2
call Led1 ; Crida la funcio Led1
clrf N ; N = 0
NoZeroN
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x14 ; W = 14
xorwf Dades,w ; Preguntem si Dades = 14
btfss STATUS,Z ; Si Dades es 14, salta
goto No15 ; Si Dades no es 14, va a l'etiqueta No15
Si15 ; Activa la variable N
movlw b'00000001' ; W = 1
movwf N ; Ho guarda a la variable, N = 1
No15
return
; FI FUNCIO PRIMERQUART
; INICI FUNCIO SEGONQUART: Quan son dos quarts,
; sona el brunzidor i s'encenen dos LED
SegonQuart
movlw b'00000001' ; W = 1
xorwf O,w ; Preguntem si O = 1
btfss STATUS,Z ; Si O=1, salta
goto NoZeroO ; Si O no es 1, va a l'etiqueta NoZeroO
Oigual1 ; O = 1
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x30 ; W = 30
xorwf Dades,w ; Preguntem si Dades = 30
btfss STATUS,Z ; Si Dades es 30, salta
goto NoZeroO ; Si Dades no es 30, va a l'etiqueta NoZeroO
ZeroO ; El brunzidor toca i s'encenen dos LED
call Brunzidor2 ; Crida la funcio Brunzidor2
call Led2 ; Crida la funcio Led2
clrf O ; O = 0
NoZeroO
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x29 ; W = 29
xorwf Dades,w ; Preguntem si Dades = 29
btfss STATUS,Z ; Si Dades es 29, salta
goto No30 ; Si Dades no es 29, va a l'etiqueta No30
Si30 ; Activa la variable O
movlw b'00000001' ; W = 1
movwf O ; Ho guarda a la variable, O = 1
No30
return
; FI FUNCIO SEGONQUART
; INICI FUNCIO TERCERQUART: Quan son tres quarts,
; sona el brunzidor i s'encenen tres LED
TercerQuart
movlw b'00000001' ; W = 1
xorwf Pe,w ; Preguntem si Pe = 1
btfss STATUS,Z ; Si Pe=1, salta
goto NoZeroP ; Si Pe no es 1, va a l'etiqueta NoZeroP
Pigual1 ; Pe = 1
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x45 ; W = 45
xorwf Dades,w ; Preguntem si Dades = 45
btfss STATUS,Z ; Si Dades es 45, salta
goto NoZeroP ; Si Dades no es 45, va a l'etiqueta NoZeroP
ZeroP ; El brunzidor toca i s'encenen tres LED
call Brunzidor2 ; Crida la funcio Brunzidor2
call Led3 ; Crida la funcio Led3
clrf Pe ; Pe = 0
NoZeroP
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C ; Llegeix els minuts del microcontrolador i ho guarda a Dades
movlw 0x44 ; W = 44
xorwf Dades,w ; Preguntem si Dades = 44
btfss STATUS,Z ; Si Dades es 44, salta
goto No45 ; Si Dades no es 44, va a l'etiqueta No45
Si45
movlw b'00000001' ; W = 1
movwf Pe ; Ho guarda a la variable, Pe = 1
No45
return
; FI FUNCIO TERCERQUART
; INICI FUNCIO BRUNZIDOR
Brunzidor
bsf STATUS,RP0 ; Tria el banc 1
movlw b'00100000' ; Definim com volem les E/S del port C
movwf TRISC ; RC5 (sortida del PWM) com a entrada
bcf STATUS,RP0 ; Tria el banc 0
clrf PORTC ; Desactiva les sortides del port C
movlw b'00001100' ; Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
; DC1B = 00 (bits 5-4) els dos bits de menys pes s?n 0
; CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
movwf ValCCP1CON ; Ho guarda per fer-ho servir m?s tard
movwf CCP1CON ; Ho posa com a configuraci? del PWM
movlw b'00000011' ; Configura el Timer 2
; bits T2KCPS (bits 1- 0) a 11 prescalat de 16
; bit 2 (TMR2ON) a 0, Timer aturat
; Postscaler TOUTPS (bits 6-3) no afecten al PWM
movwf T2CON ; Ho posa com a configuraci? del Timer 2
movlw .238 ; Valor que correspon aproximadament a do3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw .119 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw .2 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota ; Toca la nota configurada
movlw .212 ; Valor que correspon aproximadament a re3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw .106 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw .2 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota ; Toca la nota configurada
movlw .189 ; Valor que correspon aproximadament a mi3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw .95 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw .0 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota ; Toca la nota configurada
call RetM ; Espera 0,2 s
return
TocaNota
movf ValPR2,w ; Valor de PR2 per a la nota desitjada
bsf STATUS,RP0 ; Tria el banc 1
bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada
movwf PR2 ; Ho posem com a comparaci? al Timer 2
bcf STATUS,RP0 ; Tria el banc 0
movf ValCCP1CON,w ; Agafa la configuraci? de CCP1CON
andlw b'11001111' ; Posa els bits que corresponen a DC1B a zero per precauci?
movwf ValCCP1CON ; I ho torna a guardar
swapf ValDC1B,w ; Agafa el valor que ha d'anar a DC1B
; I el guarda, permutat, a W
; Els dos bits han de quedar a les posicions 4-5
andlw b'00110000' ; Posa els altres sis bits a zero per precauci?
iorwf ValCCP1CON,w ; I ho afegeix a CCP1CON
movwf CCP1CON ; Ho posa com a configuraci? del PWM
movf ValCCPR1L,w ; Valor de CCPR1L
movwf CCPR1L ; Registre que ens d?na l'amplada de tON
bcf PIR1,TMR2IF ; Desactiva el bit d'interrupci? del Timer 2
bsf T2CON,TMR2ON ; Activa el Timer 2
; No conv? engegar el PWM fins que el Timer 2 no ha fet un cicle
btfss PIR1,TMR2IF ; Espera l'activaci? del bit d'interrupci? del Timer 2
goto $-1
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,5 ; Posem RC5 (sortida del PWM) com a sortida
bcf STATUS,RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
bsf STATUS,RP0 ; Tria el banc 1
bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada
; Fem silenci
bcf STATUS,RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
return
; FI FUNCIO BRUNZIDOR
; INICI FUNCIO BRUNZIDOR2 (pels quarts)
Brunzidor2
bsf STATUS,RP0 ; Tria el banc 1
movlw b'00100000' ; Definim com volem les E/S del port C
movwf TRISC ; RC5 (sortida del PWM) com a entrada
bcf STATUS,RP0 ; Tria el banc 0
clrf PORTC ; Desactiva les sortides del port C
movlw b'00001100' ; Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
; DC1B = 00 (bits 5-4) els dos bits de menys pes s?n 0
; CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
movwf ValCCP1CON ; Ho guarda per fer-ho servir m?s tard
movwf CCP1CON ; Ho posa com a configuraci? del PWM
movlw b'00000011' ; Configura el Timer 2
; bits T2KCPS (bits 1-0) a 11 prescalat de 16
; bit 2 (TMR2ON) a 0, Timer aturat
; Postscaler TOUTPS (bits 6-3) no afecten al PWM
movlw .212 ; Valor que correspon aproximadament a re3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw .106 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw .2 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota2 ; Toca la nota configurada
movlw .189 ; Valor que correspon aproximadament a mi3
movwf ValPR2 ; Ho posem com a valor de PR2
movlw .95 ; Valor que correspon a un cicle del 50 %
movwf ValCCPR1L ; Valor de CCPR1L
movlw .0 ; Valor dels bits de menys pes del CCP
movwf ValDC1B ; Valor de DC1B
call TocaNota2 ; Toca la nota configurada
call RetM ; Espera 0,2 s
return
TocaNota2
movf ValPR2,w ; Valor de PR2 per a la nota desitjada
bsf STATUS,RP0 ; Tria el banc 1
bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada
movwf PR2 ; Ho posem com a comparaci? al Timer 2
bcf STATUS,RP0 ; Tria el banc 0
movf ValCCP1CON,w ; Agafa la configuraci? de CCP1CON
andlw b'11001111' ; Posa els bits que corresponen a DC1B a zero per precauci?
movwf ValCCP1CON ; I ho torna a guardar
swapf ValDC1B,w ; Agafa el valor que ha d'anar a DC1B
; I el guarda, permutat, a W
; Els dos bits han de quedar a les posicions 4-5
andlw b'00110000' ; Posa els altres sis bits a zero per precauci?
iorwf ValCCP1CON,w ; I ho afegeix a CCP1CON
movwf CCP1CON ; Ho posa com a configuraci? del PWM
movf ValCCPR1L,w ; Valor de CCPR1L
movwf CCPR1L ; Registre que ens d?na l'amplada de tON
bcf PIR1,TMR2IF ; Desactiva el bit d'interrupci? del Timer 2
bsf T2CON,TMR2ON ; Activa el Timer 2
; No conv? engegar el PWM fins que el Timer 2 no ha fet un cicle
btfss PIR1,TMR2IF ; Espera l'activaci? del bit d'interrupci? del Timer 2
goto $-1
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,5 ; Posem RC5 (sortida del PWM) com a sortida
bcf STATUS,RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
bsf STATUS,RP0 ; Tria el banc 1
bsf TRISC,5 ; Posem RC5 (sortida del PWM) com a entrada
; Fem silenci
bcf STATUS,RP0 ; Tria el banc 0
call RetM ; Espera 0,2 s
return
; FI FUNCIO BRUNZIDOR2
; INICI FUNCIONS DE LEDS
; INICI FUNCIO LED1
Led1
movlw 0x10 ; W = 10
movwf Encen1 ; Ho guarda a la variable, Encen1 = 50
Adeu1
movf Encen1,f ; Encen1 = 0 ?
btfss STATUS,Z ; Si Encen1 es 0, salta
goto Encen1no0 ; Si Encen1 no es 0, va a l'etiqueta Encen1no0
Encen10 ; Si Encen1 està desactivada, surt de la funcio Led1
return
Encen1no0 ; S'encen un LED
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,3 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,3 ; Activa el bit 0 del port C
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000001' ; Retard 0,2
call Rets
decf Encen1,f ; Encen1 = Encen1 - 1
goto Adeu1
; FI FUNCIO LED1
; INICI FUNCIO LED2
Led2
movlw 0x10 ; W = 10
movwf Encen2 ; Ho guarda a la variable, Encen2 = 10
Adeu2
movf Encen2,f ; Encen2 = 0 ?
btfss STATUS,Z ; Si Encen2 es 0, salta
goto Encen2no0 ; Si Encen2 no es 0, va a l'etiqueta Encen2no0
Encen20 ; Si Encen2 està desactivada, surt de la funcio Led2
return
Encen2no0 ; S'encenen dos LED
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,2 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,2 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,3 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,3 ; Activa el bit 0 del port C
call MostrarHora
movlw b'00000001' ; Retard 0,2
call Rets
decf Encen2,f ; Encen1 = Encen1 - 1
goto Adeu2
; FI FUNCIO LED2
; INICI FUNCIO LED3
Led3
movlw 0x10 ; W = 10
movwf Encen3 ; Ho guarda a la variable, Encen3 = 10
Adeu3
movf Encen3,f ; Encen3 = 0 ?
btfss STATUS,Z ; Si Encen3 es 0, salta
goto Encen3no0 ; Si Encen3 no es 0, va a l'etiqueta Encen3no0
Encen30 ; Si Encen3 està desactivada, surt de la funcio Led3
return
Encen3no0 ; S'encenen tres LED
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,1 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,1 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,1 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,1 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,2 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,2 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,3 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,3 ; Activa el bit 0 del port C
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000001' ; Retard 0,2
call Rets
decf Encen3,f ; Encen3 = Encen3 - 1
goto Adeu3
; FI FUNCIO LED3
; INICI FUNCIO LED4
Led4
movlw 0x10 ; W = 10
movwf Encen4 ; Ho guarda a la variable, Encen4 = 10
Adeu4
movf Encen4,f ; Encen4 = 0 ?
btfss STATUS,Z ; Si Encen4 es 0, salta
goto Encen4no0 ; Si Encen4 no es 0, va a l'etiqueta Encen4no0
Encen40
return
Encen4no0 ; S'encenen quatre LED
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,0 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,0 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,1 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,1 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,2 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,2 ; Activa el bit 0 del port C
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,3 ; Posa el bit 0 del port C com a sortida
bcf STATUS,RP0 ; Tria el banc 0
bsf PORTC,3 ; Activa el bit 0 del port C
call MostrarHora ; Mostra l'hora i la data del microcontrolador a la pantalla
movlw b'00000001' ; Retard 0,2
call Rets
decf Encen4,f ; Encen4 = Encen4 - 1
goto Adeu4
; FI FUNCIO LED4
; FI FUNCIONS DE LEDS
; A PARTIR D'AQUI SON FUNCIONS DEL PROGRAMA BASE
;
; Llegeix un byte I2C
; En el dispositiu indicat a AdreI2C
; A l'adreça de memòria guardada a AdreMem
; Deixa el valor llegit a Dades
;
LlegirI2C
call SDAsortida ; Posa SDA com a sortida
call StartI2C ; Envia el bit d'inici I2C
; En la primera fase enviem l'adreça del dispositiu
movf AdreI2C,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
; Només hem d'enviar set bits
bcf STATUS,C ; i després un zero per indicar escriptura
rlf Buffer,f ; Eliminem el bit de més pes
; i afegim el zero al final
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
; A la segona fase enviem l'adreça de memòria
call SDAsortida ; Posa SDA com a sortida
movf AdreMem,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
call SDAsortida ; Posa SDA com a sortida
call RestartI2C ; Envia el bit de reinici I2C
; En la tercera fase enviem l'adreça del dispositiu
movf AdreI2C,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
; Només hem d'enviar set bits
bsf STATUS,C ; i després un 1 per indicar lectura
rlf Buffer,f ; Eliminem el bit de més pes
; i afegim l'1 al final
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
; A la quarta fase enviem el valor
call RebByteI2C ; Rep el byte
movf Buffer,w ; Agafa el valor rebut
movwf Dades ; I el guarda a dades
call SDAsortida ; Posa SDA com a sortida
call NACK_M ; Envia un NACK a l'esclau
call StopI2C ; Envia el bit d'aturada I2C
return
;
; Escriu un byte I2C
; Amb el valor indicat a Dades
; En el dispositiu indicat a AdreI2C
; A l'adreça de memòria guardada a AdreMem
;
EscriuI2C
call SDAsortida ; Posa SDA com a sortida
call StartI2C ; Envia el bit d'inici I2C
; En la primera fase enviem l'adreça del dispositiu
movf AdreI2C,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
; Només hem d'enviar set bits
bcf STATUS,C ; i després un zero per indicar escriptura
rlf Buffer,f ; Eliminem el bit de més pes
; i afegim el zero al final
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
; A la segona fase enviem l'adreça de memòria
call SDAsortida ; Posa SDA com a sortida
movf AdreMem,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
; A la tercera fase enviem el valor
call SDAsortida ; Posa SDA com a sortida
movf Dades,w ; Adreça a enviar
movwf Buffer ; Preparada per enviar
call EnvByteI2C ; Envia el byte
call SDAentrada ; Posa SDA com a entrada
call ACK_S ; Reb un ACK des de l'esclau
call SDAsortida ; Posa SDA com a sortida
call StopI2C ; Envia el bit d'aturada I2C
return
;
; Posa SDA com a entrada
;
SDAentrada
bsf STATUS,RP0 ; Tria el banc 1
bsf TRISC,7 ; Posem SDA com a entrada
bcf STATUS,RP0 ; Tria el banc 0
return
;
; Posa SDA com a sortida
;
SDAsortida
bsf STATUS,RP0 ; Tria el banc 1
bcf TRISC,7 ; Posem SDA com a sortida
bcf STATUS,RP0 ; Tria el banc 0
return
;
; Envia el bit d'inici I2C
;
StartI2C
RestartI2C
bsf Port,7 ; Abans de començar, SDA ha d'estar activat
bsf Port,6 ; i SCL també
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
nop ; Allarguem el pols
nop
bcf Port,7 ; Bit d'inici, posem SDA a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
nop ; Allarguem el pols
nop
bcf Port,6 ; Fi del bit d'inici, posem SCL a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
return
;
; Envia el bit d'aturada I2C
;
StopI2C
bcf Port,7 ; Desactivem SDA
bsf Port,6 ; i activem SCL
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf Port,7 ; Posem SDA a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
return
;
; Reb un ACK des de l'esclau
;
ACK_S
bsf Port,6 ; Posem SCL a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
nop ; Esperem
nop
bcf Port,6 ; Posem SCL a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf Port,7 ; Posem SDA a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
return
;
; Envia un NACK a l'esclau
;
NACK_M
bsf Port,7 ; Posem SDA a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf Port,6 ; Posem SCL a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
nop ; Esperem
nop
bcf Port,6 ; Posem SCL a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
return
;
; Funció interna que envia un byte a I2C
; El byte a enviar ha d'estar a Buffer
;
EnvByteI2C
movlw .8 ; Hem d'enviar 8 bits
movwf Bits ; Ho posem al comptador
BucEnv
bcf Port,6 ; Posem SCL a zero per modificar SDA
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf Port,7 ; Suposem que hem agafat un 1
rlf Buffer,f ; Agafem el bit que hem d'enviar
btfss STATUS,C ; Mirem si realment era un 1
bcf Port,7 ; Si era un zero, corregim
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf Port,6 ; Activem SCL perquè el receptor llegeixi el bit
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
decfsz Bits,f ; Ja hem enviat un altre bit
goto BucEnv ; Si no era l'últim, repetim
bcf Port,6 ; Posem SCL a zero per modificar SDA
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
return
;
; Funció interna que rep un byte a I2C
; El byte rebut estarà a Buffer
;
RebByteI2C
bcf Port,6 ; Posem SCL a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
movlw .8 ; Hem de rebre 8 bits
movwf Bits ; Ho posem al comptador
BucReb
bsf Port,6 ; Posem SCL a 1
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
bsf STATUS,C ; Suposem que llegirem un 1
btfss PORTC,7 ; Mirem si realment era un 1
bcf STATUS,C ; Si era un zero, corregim
rlf Buffer,f ; Agafem el bit que acabem de rebre
bcf Port,6 ; Posem SCL a zero
movf Port,w ; Agafem els valors
movwf PORTC ; I els copiem al port C
decfsz Bits,f ; Ja hem enviat un altre bit
goto BucReb ; Si no era l'últim, repetim
return
;
; Enviem caràcters a visualitzar
;
EnviaL
movf Caracter,w ; Agafa el caràcter
movwf TXREG ; L'envia
nop
nop ; Espera 2 us
btfss PIR1,TXIF ; El registre TXREG ha quedat lliure?
goto $-1 ; No, doncs esperem
return ; Tornem al lloc des d'on hem vingut
;
; Mostrem a la pantalla un valor BCD
; a partir de dues xifres hexadecimals
;
HEXtoBCD
swapf Dades,w
andlw 0x0F
movwf Caracter ; Ho guarda a la variable
movlw '0' ; Carrega el codi ASCII del número 0
; Sumant-li la xifra tindrem el codi ASCII
addwf Caracter,f ; Ara Caracter conté el caràcter ASCII
call EnviaL ; Ho envia
Hex1 ; Si només té una xifra, entrem per aquí
movf Dades,w
andlw 0x0F
movwf Caracter ; Ho guarda a la variable
movlw '0' ; Carrega el codi ASCII del número 0
; Sumant-li la xifra tindrem el codi ASCII
addwf Caracter,f ; Ara Caracter conté el caràcter ASCII
call EnviaL ; Ho envia
return
;
; Funció de retard de 0,2 W s
;
Rets
movwf Retard3
Bucles
decfsz Retard1,f
goto Bucles
decfsz Retard2,f
goto Bucles
decfsz Retard3,f
goto Bucles
return
;
; Funció per llegir els polsadors
;
Llegir
clrf Polsador ; Si aquest valor no es canvia és que no hi ha cap polsador premut
nop ; espera un microsegon
nop ; espera un microsegon
nop ; espera un microsegon
nop ; espera un microsegon
nop ; espera un microsegon, en total 5
bsf ADCON0,GO ; Inicia la conversió
btfsc ADCON0,GO ; Quan el bit sigui 0 la conversió haurà acabat
goto $-1 ; repetim la línia fins que deixi de ser 0
; Comparació P1
movlw .220 ; Límit superior de P1
subwf ADRESH,w ; W = ADRESH - W
btfsc STATUS,C ; C = 1 si ADRESH >= W
goto NoP1 ; ADRESH >= W
movlw .200 ; Límit inferior de P1
subwf ADRESH,w ; W = ADRESH - W
btfss STATUS,C ; C = 1 si ADRESH >= W
goto NoP1 ; ADRESH < W
movlw b'00000001' ; Polsador P1
movwf Polsador ; Ho copia a Polsador
goto NoP5
NoP1 ; Comparació P2
movlw .194 ; Límit superior de P2
subwf ADRESH,w ; W = ADRESH - W
btfsc STATUS,C ; C = 1 si ADRESH >= W
goto NoP2 ; ADRESH >= W
movlw .174 ; Límit inferior de P2
subwf ADRESH,w ; W = ADRESH - W
btfss STATUS,C ; C = 1 si ADRESH >= W
goto NoP2 ; ADRESH < W
movlw b'00000010' ; Polsador P2
movwf Polsador ; Ho copia a Polsador
goto NoP5
NoP2 ; Comparació P3
movlw .163 ; Límit superior de P3
subwf ADRESH,w ; W = ADRESH - W
btfsc STATUS,C ; C = 1 si ADRESH >= W
goto NoP3 ; ADRESH >= W
movlw .143 ; Límit inferior de P3
subwf ADRESH,w ; W = ADRESH - W
btfss STATUS,C ; C = 1 si ADRESH >= W
goto NoP3 ; ADRESH < W
movlw b'00000100' ; Polsador P3
movwf Polsador ; Ho copia a Polsador
goto NoP5
NoP3 ; Comparació P4
movlw .90 ; Límit superior de P4
subwf ADRESH,w ; W = ADRESH - W
btfsc STATUS,C ; C = 1 si ADRESH >= W
goto NoP4 ; ADRESH >= W
movlw .70 ; Límit inferior de P4
subwf ADRESH,w ; W = ADRESH - W
btfss STATUS,C ; C = 1 si ADRESH >= W
goto NoP4 ; ADRESH < W
movlw b'00001000' ; Polsador P4
movwf Polsador ; Ho copia a Polsador
goto NoP5
NoP4 ; Comparació P5
movlw .55 ; Límit superior de P5
subwf ADRESH,w ; W = ADRESH - W
btfsc STATUS,C ; C = 1 si ADRESH >= W
goto NoP5 ; ADRESH >= W
movlw .35 ; Límit inferior de P5
subwf ADRESH,w ; W = ADRESH - W
btfss STATUS,C ; C = 1 si ADRESH >= W
goto NoP5 ; ADRESH < W
movlw b'00010000' ; Polsador P5
movwf Polsador ; Ho copia a Polsador
NoP5
return
;
; Funci? de retard de 0,2 s
;
RetM
decfsz Retard4,f
goto RetM
decfsz Retard5,f
goto RetM
return
MostrarHora
movlw .5 ; Retard d'1 s
call Rets
movlw .254 ; Control de la posici? del cursor
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .64 ; Filera 2 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .2 ; Hores
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw '.' ; Separador
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .1 ; Minuts
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw '.' ; Separador
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .0 ; Segons
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw .254 ; Control de la posici? del cursor
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .0 ; Filera 1 columna 1
iorlw b'10000000' ; Posa el bit de posicionat a 1
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .4 ; Dia
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw '-' ; Separador
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .5 ; Mes
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw '-' ; Separador
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw '2' ; Any primer d?git
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw '0' ; Any segon d?git
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .6 ; Any
movwf AdreMem
call LlegirI2C
call HEXtoBCD ; Ho mostra a la pantalla
movlw ' ' ; Espai
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw ' ' ; Espai
movwf Caracter ; Ho guarda a la variable
call EnviaL ; Ho envia
movlw .3 ; Dia setmana
movwf AdreMem
call LlegirI2C
call Hex1 ; Ho mostra a la pantalla
return
end

Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.