Programació en mpasm del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Rellotge digital

Programa del grup 1

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

 

 

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