Subrutinas pic

34
Subrutinas para Pic 2º DPEE Grado Superior Diciembre 2005

Transcript of Subrutinas pic

Page 1: Subrutinas pic

Subrutinas para Pic

2º DPEE Grado Superior Diciembre 2005

Page 2: Subrutinas pic

aschex

;********************************************************************; "aschex";Esta subrutina convierte el código ASCII existente en W en código;hexadecimal. El resultado de la conversión se obtiene en W.;El tiempo total de subrutina es de 10 us, incluido el call.;********************************************************************

CBLOCK 0x72TASCHENDC

aschex movwf TASCH ;Guarda el número original.sublw 0x39 ;¿Es cifra? (resultado positivo)btfss STATUS,C ; "goto Ajlet ;No: salta a ajuste de letra.movlw 0x30 ;Sí: carga valor para resta ysubwf TASCH,W ;obtención del hexadecimal.return

Ajlet: movlw .55 ;Carga el decimal 55 para ajustesubwf TASCH,W ;de cifra.return

Página 1

Page 3: Subrutinas pic

ascii

;********************************************************************; "ASCII";Esta subrutina convierte en código ASCII el byte existente en W.;La conversión del cuarteto mayor se deposita en el registro RASCH;y la del menor en RASCL.;El tiempo máximo de subrutina es de 32 us, incluido el call.;********************************************************************

CBLOCK 0x7ATASC1, TASC2, RASCH, RASCLENDC

ASCII: movwf TASC1 ;Guarda el número original.call AJASC ;Ajusta cuarteto menor. Valor en W.movwf RASCL ;Guarda ajuste de cuarteto menor.swapf TASC1,W ;Permuta cuartetos para ajuste del mayor.call AJASC ;Ajusta cuarteto mayor.movwf RASCH ;Guarda conversión de cuarteto mayor.return

AJASC: andlw B'00001111' ;Borra cuarteto mayor.movwf TASC2 ;Salva valor.sublw 9 ;Compara el número con 9.btfss STATUS,C ;¿Número > 9? ¿Cifra o letra?goto AJLET ;Si número > 9 (letra) salta a ajustarla.movf TASC2,W ;Si W < ó = 9 (cifra) recupera valor.addlw 0x30 ;Suma 30 para ajustar la cifra.retur

AJLET: movf TASC2,W ;Recupera valor.addlw 0x37 ;Suma para ajuste en ASCII de letra.return

Página 1

Page 4: Subrutinas pic

bbcd16

;********************************************************************; "bbcd16";Subrutina para convertir en BCD el número binario de 16 bits contenido;en los registros HBYTE y LBYTE (mayor y menor byte respectivamente).;El resultado queda en RBCDH, RBCDM y RBCDL, nombrados de mayor a menor;dígito, respectivamente.;El tiempo total de subrutina es de 887 us, incluido el call.;********************************************************************

CBLOCK 0x73HBYTE, LBYTE, RBCDL, RBCDM, RBCDH, Conbit, TBCD16ENDC

bbcd16: bcf STATUS,C ;Borra el acarreo.movlw .16 ;Carga contador de bits.movwf Conbit ; "clrf RBCDL ;Borra registros de resultado.clrf RBCDM ; "clrf RBCDH ; "

L16: rlf LBYTE,F ;Rota a izquierda los dos bytesrlf HBYTE,F ;del número.rlf RBCDL,F ;Rota a izquierda los tres registrosrlf RBCDM,F ;del resultado.rlf RBCDH,F ; "decfsz Conbit,F ;Decrementa contador de bits.goto Ajdec ;Si no se ha finalizado, salto a Ajdec.retlw 0 ;Si se ha finalizado, retorno con 0 en W.

Ajdec: movlw RBCDL ;Se carga dígito menor de resultadomovwf FSR ;para ser utilizado como dirección.call Ajbcd ;Ajuste en BCD.movlw RBCDM ;Se carga dígito medio de resultadomovwf FSR ;para ser utilizado como dirección.call Ajbcd ;Ajuste en BCD.movlw RBCDH ;Se carga dígito mayor de resultadomovwf FSR ;para ser utilizado como dirección.call Ajbcd ;Ajuste en BCD.goto L16 ;Repite 16 veces lo anterior.

Ajbcd: movlw 3 ;Carga 3 en W.addwf INDF,W ;Suma 3 al contenido direccionado por FSR.movwf TBCD16 ;Descarga en TBCD16 el resultado anterior.btfsc TBCD16,3 ;Chequea bit 3 del resultado anterior.movwf INDF ;Si bit 3 = 1, carga W en la dirección de FSR.movlw 0x30 ;Si bit 3 = 0, W se carga con 30h.addwf INDF,W ;Suma W con lo direccionado por FSR. movwf TBCD16 ;Carga W en TBCD16.btfsc TBCD16,7 ;Chequea bit 7 de TBCD16.movwf INDF ;Si bit 7 = 1, carga W en la dirección de FSR.retlw 0 ;Si bit 7 = 0 se retorna con 0 en W.

Página 1

Page 5: Subrutinas pic

contlcd

;********************************************************************************;CONJUNTO DE SUBRUTINAS QUE PUEDEN INCLUIRSE EN OTROS PROGRAMAS CON LA ORDEN; include "contlcd.inc";********************************************************************************

;Estas rutinas permitirán realizar el control de la pantalla visualizadora (LCD).

#define ACTIVEN bsf PORTA,2 ;Activa señal E.#define BORRAEN bcf PORTA,2 ;Desactiva señal E.#define LEELCD bsf PORTA,1 ;Lee el módulo.#define ESCRLCD bcf PORTA,1 ;Escribe en el módulo.#define ORDEN bcf PORTA,0 ;Prepara al módulo para recibir una orden.#define DATO bsf PORTA,0 ;Prepara al módulo para recibir un dato

CBLOCK 0x7ETLCD1, TLCD2ENDC

;********************************************************************; "PROGLCD";Realiza la programación de puerto A y puerto B de la manera que ;necesita el módulo LCD: PORTB como salida y las tres líneas de menos;peso del PORTA como salidas digitales.;********************************************************************

PROGLCD: bsf STATUS,RP0 ;Selecciona banco 1.movlw 06 ;Configura las patillas del puerto Amovwf ADCON1 ;como señales digitales.movf TRISA,W ;Lee la programación de TRISA paraandlw b'11111000' ;dejar como salidas las tres líneasmovwf TRISA ;de menor peso y no tocar las demás.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0.ORDEN ;RS=0.BORRAEN ;E=0.return

;********************************************************************; "INILCD";Realiza la inicialización del LCD con interface de 8 bits, 2 líneas ;de pantalla y caracteres de 5 x 7. La subrutina provocará un retardo;de 45,2 ms y un borrado de pantalla.;********************************************************************

INILCD call R20MS ;Retardo mayor de 30 ms necesario paracall R20MS ;que estabilice la tensión de

alimentación.call PROGLCD ;Programación de las líneas de puertos.movlw b'00111100' ;Programación de interface de 8 bits ycall ENVC ;pantalla de 2 líneas.call R100MI ;Retardo mayor de 39 microsegundos.movlw b'00001110' ;Programación de pantalla activa,

cursorcall ENVC ;visible y sin intermitencia.call R100MI ;Retardo aconsejado mayor de 39

microseg.movlw 01 ;Programación de borrado de pantalla.call ENVC ; "

call R5MS ;Retardo aconsejado mayor de 1,53 ms.movlw 06 ;Programación de cursor incremental.call ENVC ; "return

;********************************************************************; "ESPVI";Rutina de espera para que el visualizador quede libre.;********************************************************************

ESPVI LEELCD ;Pone al módulo LCD en modo lectura.bsf STATUS,RP0 ;Selecciona banco 1.movlw 0xFF ;Programa PORTB como entrada.movwf TRISB ; "bcf STATUS,RP0 ;Selecciona banco 0.ACTIVEN ;E=1: activa Enable.nop

ESPVI1: btfsc PORTB,7 ;Chequea bit "BUSY".goto ESPVI1 ;Si está OCUPADO repite el chequeo.BORRAEN ;E=0: desactiva Enable.bsf STATUS,RP0 ;Selecciona el banco 1.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0ESCRLCD ;Deja al módulo en escritura.return

;********************************************************************; "DurEN";Duración de ENABLE. En algunos LCD esta señal debe estar a "0" unos;40uS antes de volver a ponerse a "1".;********************************************************************

DurEN: ACTIVEN ;Activa ENABLE

Página 1

Page 6: Subrutinas pic

contlcdnop ;Retardo de seguridad.BORRAEN ;Desactiva ENABLEmovlw .14 ;Bucle de retardo 40 us.movwf TLCD1 ;Salva valor en temporal.

DurEN1: decfsz TLCD1,F ;Pierde unos 40 uS necesarios para losgoto DurEN1 ;módulos LCD de winteck.return

;********************************************************************; "ENVD";Rutina para enviar al visualizador el dato contenido en W.;********************************************************************

ENVD ORDEN ;RS=0.movwf PORTB ;Saca dato por el puerto B.call ESPVI ;Espera hasta visualizador

LIBRE.DATO ;RS=1: visualizador en modo

dato.goto DurEN ;Aplica pulso de ENABLE.

;********************************************************************; "ENVC";Rutina para enviar al visualizador una orden.;********************************************************************

ENVC ORDEN ;RS=0.movwf PORTB ;Saca en puerto B el valor de

W.call ESPVI ;Espera hasta visualizador

LIBRE.goto DurEN ;Finaliza.

;********************************************************************; "LEED";Rutina para leer el dato ubicado en la posición del cursor del LCD.;El dato leído estará disponible en W.;********************************************************************

LEED bsf STATUS,RP0 ;Selecciona banco 1.movlw 0xFF ;Programa PORTB como entrada.movwf TRISB ; "bcf STATUS,RP0 ;Selecciona banco 0.LEELCD ;R/-W= 1: visualizador en modo lectura.DATO ;RS=1: visualizador en modo dato.ACTIVEN ;E=1: activa Enable.movf PORTB,W ;Lee el dato en posición de cursor.BORRAEN ;E=0: desactiva Enable.movwf TLCD2 ;Salva dato en registro temporal.call ESPVI ;Espera a visualizador libre.bsf STATUS,RP0 ;Selecciona el banco 1.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0.movlw .14 ;Bucle de retardo 40 us.movwf TLCD1 ;Salva valor en temporal.

LEED1: decfsz TLCD1,F ;Pierde unos 40 uS necesarios para losgoto LEED1 ;módulos LCD de winteck.movf TLCD2,W ;Recupera valor leído.return

;********************************************************************;La señal RS está conectada a RA0 (PORTA0).;La señal R/-W está conectada a RA1 (PORTA1).;La señal E está conectada a RA2 (PORTA2).;RS = 0 para orden de control de pantalla.;RS = 1 para dato de o hacia pantalla.;R/-W = 0 para realizar una escritura en pantalla (envío).;R/-W = 1 para leer de pantalla (obtener una información).;E = 0 para inhibición de la pantalla.;E = 1 para habilitar los circuitos del visualizador.;********************************************************************

;********************************************************************;SUBRUTINAS PARA EMPLEAR LA RAM DE REGISTROS COMO PANTALLA LCD;Se emplean las direcciones 30h a 3Fh y 40h a 4Fh para visualizar;las dos líneas de pantalla.;El cursor siempre trabaja en modo incremental, tanto al escribir como;al leer datos.;Antes de escribir o leer, como es lógico, hay que situar el cursor.;********************************************************************INILCDM movlw 30

movwf FSRmovlw .16movwf TLCD1

INILCDM1: clrf INDFincf FSR,Fdecfsz TLCD1,Fgoto INILCDM1return

Página 2

Page 7: Subrutinas pic

contlcdENVDM movwf INDF

incf FSR,Freturn

ENVCM movwf TLCD1movlw 50subwf TLCD1,Wmovwf FSRreturn

LEEDM movf INDF,Wincf FSR,Freturn

Página 3

Page 8: Subrutinas pic

contlcd

;********************************************************************************;CONJUNTO DE SUBRUTINAS QUE PUEDEN INCLUIRSE EN OTROS PROGRAMAS CON LA ORDEN; include "contlcd.inc";********************************************************************************

;Estas rutinas permitirán realizar el control de la pantalla visualizadora (LCD).

#define ACTIVEN bsf PORTA,2 ;Activa señal E.#define BORRAEN bcf PORTA,2 ;Desactiva señal E.#define LEELCD bsf PORTA,1 ;Lee el módulo.#define ESCRLCD bcf PORTA,1 ;Escribe en el módulo.#define ORDEN bcf PORTA,0 ;Prepara al módulo para recibir una orden.#define DATO bsf PORTA,0 ;Prepara al módulo para recibir un dato

CBLOCK 0x7ETLCD1, TLCD2ENDC

;********************************************************************; "PROGLCD";Realiza la programación de puerto A y puerto B de la manera que ;necesita el módulo LCD: PORTB como salida y las tres líneas de menos;peso del PORTA como salidas digitales.;********************************************************************

PROGLCD: bsf STATUS,RP0 ;Selecciona banco 1.movlw 06 ;Configura las patillas del puerto Amovwf ADCON1 ;como señales digitales.movf TRISA,W ;Lee la programación de TRISA paraandlw b'11111000' ;dejar como salidas las tres líneasmovwf TRISA ;de menor peso y no tocar las demás.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0.ORDEN ;RS=0.BORRAEN ;E=0.return

;********************************************************************; "INILCD";Realiza la inicialización del LCD con interface de 8 bits, 2 líneas ;de pantalla y caracteres de 5 x 7. La subrutina provocará un retardo;de 15 ms y un borrado de pantalla.;********************************************************************

INILCD call PROGLCD ;Programación de las líneas de puertos.movlw b'00111100' ;Programación de interface de 8 bits ycall ENVC ;pantalla de 2 líneas.movlw b'00001110' ;Programación de pantalla activa,

cursorcall ENVC ;visible y sin intermitencia.movlw 01 ;Programación de borrado de pantalla.call ENVC ; "

movlw 06 ;Programación de cursor incremental.call ENVC ; "return

;********************************************************************; "ENVD";Rutina para enviar al visualizador el dato contenido en W.;********************************************************************

ENVD DATO ;RS=1: visualizador en modo dato.

ESCRLCD ;R/-W = 0movwf PORTB ;Saca dato por el puerto B.ACTIVENBORRAENcall R1MSreturn

;********************************************************************; "ENVC";Rutina para enviar al visualizador una orden.;********************************************************************

ENVC ORDEN ;RS=0.ESCRLCD ;R/-W = 0movwf PORTB ;Saca en puerto B el valor de

W.ACTIVENBORRAENcall R1MSreturn

;********************************************************************; "LEED";Rutina para leer el dato ubicado en la posición del cursor del LCD.;El dato leído estará disponible en W.;********************************************************************

LEED bsf STATUS,RP0 ;Selecciona banco 1.movlw 0xFF ;Programa PORTB como entrada.

Página 1

Page 9: Subrutinas pic

contlcdmovwf TRISB ; "bcf STATUS,RP0 ;Selecciona banco 0.LEELCD ;R/-W= 1: visualizador en modo lectura.DATO ;RS=1: visualizador en modo dato.ACTIVEN ;E=1: activa Enable.movf PORTB,W ;Lee el dato en posición de cursor.BORRAEN ;E=0: desactiva Enable.movwf TLCD2 ;Salva dato en registro temporal.bsf STATUS,RP0 ;Selecciona el banco 1.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0.movf TLCD2,W ;Recupera valor leído.call R1MSreturn

;*****************************************************************; "LEES";Rutina para leer la palabra de Estado del LCD.;El dato leído estará disponible en W.;********************************************************************

LEES bsf STATUS,RP0 ;Selecciona banco 1.movlw 0xFF ;Programa PORTB como entrada.movwf TRISB ; "bcf STATUS,RP0 ;Selecciona banco 0.LEELCD ;R/-W= 1: visualizador en modo lectura.ORDEN ;RS=1: visualizador en modo dato.ACTIVEN ;E=1: activa Enable.movf PORTB,W ;Lee el dato en posición de cursor.BORRAEN ;E=0: desactiva Enable.movwf TLCD2 ;Salva dato en registro temporal.bsf STATUS,RP0 ;Selecciona el banco 1.clrf TRISB ;Programa PORTB como salida.bcf STATUS,RP0 ;Selecciona banco 0.movf TLCD2,W ;Recupera valor leído.call R1MSreturn

Página 2

Page 10: Subrutinas pic

eeprom;********************************************************************; "EEPROM";Estas subrutinas permiten la lectura y escritura de la EEPROM de;datos. Manejan los registros EEdir y EEdat, para dirección y dato;respectivamente.;********************************************************************

CBLOCK 0x67EEdir, EEdatENDC

;********************************************************************; "LeeEE";Lee un byte de la dirección EEdir de la EEPROM de datos y lo carga;en el registro EEdat.;********************************************************************

LeeEE movf EEdir,W ;Copia en W la dirección de la EEPROM.bsf STATUS,RP1 ;Selecciona banco 2.movwf EEADR ;Escribe la dirección actual.bsf STATUS,RP0 ;Selecciona banco 3.bcf EECON1,EEPGD ;Selecciona memoria EEPROM de datos.bsf EECON1,RD ;Activa modo lectura.bcf STATUS,RP0 ;Selecciona banco 2.movf EEDATA,W ;Lee el byte.bcf STATUS,RP1 ;Selecciona banco 0.movwf EEdat ;Salva en registro el dato leído.return

;********************************************************************; "GrabEE";Graba un byte en la dirección contenida en EEdir. El byte a grabar;estará ubicado en la variable EEdat.;********************************************************************

GrabEE bcf PIR2,EEIF ;Borra el flag de la EEPROM.movf EEdat,W ;Copia en W el dato.bsf STATUS,RP1 ;Selecciona el banco 2.movwf EEDATA ;Copia en registro el dato a grabar.bcf STATUS,RP1 ;Selecciona el banco 0.movf EEdir,W ;Copia en W la dirección de EEPROM.bsf STATUS,RP1 ;Selecciona el banco 2.movwf EEADR ;Copia en registro la dirección actual.

bsf STATUS,RP0 ;Selecciona el banco 3.bcf EECON1,EEPGD ;Selecciona EEPROM de datos.bsf EECON1,WREN ;Habilita la escritura en EEPROM.movlw 0x55 ;Secuencia de escritura en EEPROM,movwf EECON2 ;descrita por Microchip.movlw 0xAA ; "movwf EECON2 ; "bsf EECON1,WR ;Comienza la escritura en EEPROM.bcf STATUS,RP0 ;Selecciona banco 0.bcf STATUS,RP1 ; "

Fingra: btfss PIR2,EEIF ;¿Fin del ciclo de escritura?goto Fingra ;No: continúa chequeo.bcf PIR2,EEIF ;Borra indicador de interrupción.return

Página 1

Page 11: Subrutinas pic

mul16x16

;********************************************************************; "mul16x16";Se realiza el producto de dos números de dos bytes cada uno, con un;resultado de cuatro bytes.;El multiplicando se encuentra en los registros MCDOH y MCDOL (bytes;alto y bajo respectivamente) y el multiplicador en MDORH y MDORL.;El resultado se encontrará disponible en los registros RESHH, RESHM,;RESLM y RESLL, ordenados de mayor a menor según pesos.;********************************************************************

CBLOCK 0x69MCDOH, MCDOL, MDORH, MDORL, RESHHRESHM, RESLM, RESLL, CONROTENDC

mul16x16: movlw .16movwf CONROTmovf MDORH,Wmovwf RESHHmovf MDORL,Wmovwf RESHMclrf MDORHclrf MDORLmovlw 0

reprot: rrf RESHH,F ;Rota byte cuarto de resultado.rrf RESHM,F ;Rota byte tercero de resultado.btfsc STATUS,C ;¿Hay que sumar?call ajsuma ;Sí: suma bytes menores.rrf MDORH,F ;Rota bytes de resultados.rrf MDORL,F ; "rrf RESLM,F ; "rrf RESLL,F ; "decfsz CONROT,F ;¿Se han efectuado 8 bucles?goto reprot ;No: repite proceso.movf MDORH,W ;Sí: ordena resultados en registros.movwf RESHH ; "movf MDORL,W ; "movwf RESHM ; "retlw 0

ajsuma:movf MCDOL,W ;Suma bytes bajos.addwf MDORL,F ; "btfsc STATUS,C ;¿Hay acarreo?incf MDORH,F ;Sí: incrementa byte mayor de MDOR.movf MCDOH,W ;No: suma bytes mayores.addwf MDORH,F ; "retlw 0

Página 1

Page 12: Subrutinas pic

paridad

; - PROGRAMA Nº -;********************************************************************; "Paridad";Calcula la paridad del byte dado W y deja el resultado en el bit de;acarreo, de la siguiente manera:; Paridad PAR en W ==> C=0; Paridad IMPAR en W ==> C=1.;********************************************************************

CBLOCK 0x49PAR1ENDC

Par: movwf PAR1 ;Carga el dato en registro Temp.swapf PAR1,W ;Conmuta cuartetos y lo deja en W.xorwf PAR1,F ;Función OREX entre B7-B3, B6-B2, B5-B1

y

B4-B0.rlf PAR1,W ;Rota a izquierda para posicionar bits.xorwf PAR1,W ;OREX entre (B7-B3)-(B6-B2),

5-B1)-(B4-B0).movwf PAR1rlf PAR1,Frlf PAR1,Fxorwf PAR1,Frlf PAR1,Freturn

Página 1

Page 13: Subrutinas pic

retardos

;********************************************************************;CONJUNTO DE SUBRUTINAS QUE PUEDEN INCLUIRSE EN OTROS PROGRAMAS CON;LA ORDEN include "retardos.inc";Se dispone de retardos de 100 microseg., 1 ms, 5 ms, 10 ms, 20 ms,;100 ms y 1 s, y las más largas tratan el WDT.;********************************************************************

CBLOCK 0x64RET1, RET2, RET3ENDC

;************************************************************************; Cálculo del tiempo;Para una Fclock = 4 MHz, Tclock = 0,25 microsegundos.;Un ciclo de instrucción se ejecuta en 4 Tclock = 1 microsegundo (us).;;tsubrutina R100MI = (3.RET1 + 7) micseg.;tsubrutina R1MS = (4.RET1 + 8) micseg.;tsubrutina R5MS = (4.RET1.RET2 + 4.RET2 + 8) micseg.;tsubrutina R10MS = (4.RET1.RET2 + 4.RET2 + 5) micseg.;tsubrutina R20MS = (4.RET1.RET2 + 4.RET2 + 5) micseg.;tsubrutina R100MS = (4.RET1.RET2 + 4.RET2 + 5) micseg.;tsubrutina R1S = (4.RET1.RET2.RET3 + 4.RET2.RET3 + 4.RET3 + 5) micseg.;************************************************************************

;********************************************************************; "R100MI";Rutina de temporización 100 microsegundos.;********************************************************************

R100MI: movlw .31 ;Carga RET1.movwf RET1 ; "

R100MI1: decfsz RET1,F ;Decrementa RET1 hasta su valor 00h.goto R100MI1 ;Si RET1 no es cero repite decremento.nop ;Si RET1=0 ajusta tiempo y retorna.nop ; "return

;********************************************************************; "R1MS";Rutina de temporización 1 milisegundo.;********************************************************************

R1MS movlw .248 ;Carga RET1.movwf RET1 ; "

R1MS1: clrwdt ;Borra WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R1MS1 ;Si RET1 no es cero repite decrementonop ;Si RET1=0 ajusta tiempo y retorna.nop ; "nop ; "return

;********************************************************************; "R5MS";Rutina de temporización 5 milisegundos.;********************************************************************

R5MS movlw .24 ;Carga RET2.movwf RET2 ; "

R5MS1: movlw .51 ;Carga RET1.movwf RET1 ; "

R5MS2: clrwdt ;Inicializa WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R5MS2 ;Si RET1 no es cero repite decremento.decfsz RET2,F ;Si RET1=0 decrementa RET2.goto R5MS1 ;Si RET2 no es 0 repite el bucle.nop ;Si RET2=0 ajusta tiempo y retorna.nop ; "nop ; "return

;********************************************************************; "R10MS";Rutina de temporización 10 milisegundos.;********************************************************************

R10MS movlw .25 ;Carga RET2.movwf RET2 ; "

R10MS1: movlw .99 ;Carga RET1.movwf RET1 ; "

R10MS2: clrwdt ;Inicializa WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R10MS2 ;Si RET1 no es cero repite decremento.decfsz RET2,F ;Si RET1=0 decrementa RET2.goto R10MS1 ;Si RET2 no es 0 repite el bucle.return ;Si RET=0 retorna.

Página 1

Page 14: Subrutinas pic

retardos

;********************************************************************; "R20MS";Rutina de temporización 20 milisegundos.;********************************************************************

R20MS movlw .25 ;Carga RET2.movwf RET2 ; "

R20MS1: movlw .199 ;Carga RET1.movwf RET1 ; "

R20MS2: clrwdt ;Inicializa WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R20MS2 ;Si RET1 no es cero repite decremento.decfsz RET2,F ;Si RET1=0 decrementa RET2.goto R20MS1 ;Si RET2 no es 0 repite el bucle.return

;********************************************************************; "R100MS";Rutina de temporización 100 milisegundos.;********************************************************************

R100MS movlw .100 ;Carga RET2.movwf RET2 ; "

R100MS1: movlw .249 ;Carga RET1.movwf RET1 ; "

R100MS2: clrwdt ;Inicializa WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R100MS2 ;Si RET1 no es cero repite decremento.decfsz RET2,F ;Si RET1=0 decrementa RET2.goto R100MS1 ;Si RET2 no es 0 repite el bucle.return

;********************************************************************; "R1S";Rutina de temporización 1 segundo.;********************************************************************

R1S movlw .250 ;Carga RET3.movwf RET3 ; "

R1S1: movlw .100 ;Carga RET2.movwf RET2 ; "

R1S2: movlw 9 ;Carga RET1.movwf RET1 ; "

R1S3: clrwdt ;Inicializa WDT.decfsz RET1,F ;Decrementa RET1 hasta cero.goto R1S3 ;Si RET1 no es cero repite decremento.decfsz RET2,F ;Si RET1=0 decrementa RET2.goto R1S2 ;Si RET2 no es 0 repite el bucle 2.decfsz RET3,F ;Si RET2=0 decrementa RET3.goto R1S1 ;Si RET3 no es 0 repite el bucle 3.return

;********************************************************************; CBLOCK dirección o etiqueta; variables; ENDC;Ejemplo:; CBLOCK 0x40; RET1, RET2, RET3; ENDC;Se asignará la dirección 40h a RET1, la 41h a RET2 y la 43h a RET3.;Se conseguirá lo mismo así:; CBLOCK variables; RET1, RET2, RET3; ENDC; Y en el programa principal asignamos:; variables equ 40;********************************************************************

Página 2

Page 15: Subrutinas pic

rs232

; "rs232.inc";********************************************************************;Conjunto de rutinas de control de transmisión vía RS232.;El programa principal que usa estas rutinas tiene que cargar las;siguientes variables:

;CLKIN: Frecuencia del oscilador en ciclos/segundo.;BAUDIOS: Frecuencia de comunicación.;TRMODO: Modo de transmisión: "1" transmite primero bit LSB.;REMODO: Modo de recepción: "1" recibe primero bit LSB.;TRANBIT: Número de bits a transmitir: 7 u 8.;RECNBIT: Número de bits a recibir: 7 u 8.;STOPNBIT: Número de bits de stop: 1 o 2.;CONT: Contador de bits.

CLKOUT equ CLKIN >> 2 ;Calcula duración del ciclo máquina (CLKOUT=CLKIN/4).DURBIT equ ((CLKOUT/BAUDIOS)/3)-.5 ;Calcula la duración del bit.DURBITL equ low DURBIT ;Calcula la parte baja de RET.DURBITH equ high DURBIT+1 ;Calcula la parte alta de RET.DURST equ (DURBIT/2)+DURBIT ;Calcula duración del bit de inicio (START).DURSTL equ low DURST ;Calcula parte baja de START.DURSTH equ high DURST+1 ;Calcula parte alta de START.

CBLOCK 0x5E ;Inicio de las variables para RS232. REGREC ;Registro de recepción.REGTRAN ;Registro de transmisión.CONTRAN ;Contador de bits transmitidos.CONDURL ;Contador de delay parte baja.CONDURH ;Contador de delay parte alta.CONT ;Contador de bits.ENDC

#define PATTRAN PORTB,4 ;Línea de transmisión#define PATREC PORTB,5 ;Línea de recepción

;********************************************************************; "RECEP";Rutina de recepción. Después de la detección del bit de inicio;espera la recepción de una palabra de 7 u 8 bits, según se programe;la variable "RECNBIT". Además, según el valor de "REMODO", se podrá;recibir primero el bit de mayor o menor peso ("REMODO"=1 primero el LSB).;********************************************************************

RECEP clrf REGREC ;Borrar registro receptor.

RECEP1: clrwdt ;Refresco del WDT.btfsc PATRECgoto RECEP1 ;Espera el bit de inicio (0).call TBSTREC ;Tiempo de retraso del bit de inicio

;(1.5 de la célula de bit).

IF RECNBIT == 8

movlw 8 ;8 bits de datos.

ELSE

movlw 7 ;7 bits de datos.

ENDIF

movwf CONT

RECSIG: bcf STATUS,C

IF REMODO == 1

rrf REGREC,F ;Recibir primero el LSB.

ELSE

rlf REGREC,F ;Recibir primero el MSB.

ENDIF

btfsc PATREC ;Chequea bit de entrada.

IF REMODO == 1IF RECNBIT == 8

bsf REGREC,7 ;Activa bit 7 de REGREC si nºbits=8;y 1º bit LSB.

ELSE

bsf REGREC,6 ;Activa bit 6 de Rxdreg si nºbits=7;y 1º bit LSB.

ENDIFELSE

bsf REGREC,0 ;Activa bit 0 de Rxdreg si 1º el bit

Página 1

Page 16: Subrutinas pic

rs232MSB.

ENDIF

call RETBIT ;Espera entre bits.decfsz CONT,F ;Decrementa contador de nº de bits.goto RECSIGcall RETBIT

IF STOPNBIT == 2

call RETBIT

ENDIF ;Espera 1 o 2 bits de stop.

retlw 0

;********************************************************************; "TRANSM";Rutina de transmisión. Tras el bit de inicio se transmite la palabra;contenida en el registro transmisor REGTRAN, seguido de uno o dos;bits de stop, según se programe la variable STOPNBIT.;********************************************************************

TRANSMIF TRANBIT == 8

movlw 8 ;Transmisión de palabras de 8 bits.

ELSE

movlw 7 ;Transmisión de palabras de 7 bits.

ENDIF

movwf CONT

IF TRMODO == 1 ;Si se transmite 1º el LSB y la palabraELSE ;es de 7 bits, el registro transmisor

IF TRANBIT == 8 ;se desplaza una posición a la izquierda

ELSE ;para descartar el 8º bit.

rlf REGTRAN,F

ENDIFENDIF

bcf PATTRAN ;Transmite el bit de inicio.call RETBIT

TRANSIG: bcf STATUS,C

IF TRMODO == 1

rrf REGTRAN,F ;Desplaza a dcha. si 1º es el LSB.

ELSE

rlf REGTRAN,F ;Desplaza a izda. si 1º es el MSB.

ENDIF

btfsc STATUS,C ;Si el carry es uno, se transmite 1bsf PATTRAN ; "btfss STATUS,C ;Si el carry es cero se transmite 0.bcf PATTRAN ; "call RETBIT ;decfsz CONT,F ;Decrementa contador de bits.goto TRANSIG ;Si no es cero repite ciclo.bsf PATTRAN ;Si es cero transmite un bit de stop.call RETBIT ;

IF STOPNBIT == 2

bsf PATTRAN ;Transmite segundo bit de stop.call RETBIT ;

ENDIF

retlw 0

;********************************************************************; "RETBIT";Rutina de temporización para los intervalos entre bit y bit.;********************************************************************

RETBIT: clrwdtmovlw DURBITHmovwf CONDURH

RETBIT1: movlw CONDURLmovwf CONDURL

Página 2

Page 17: Subrutinas pic

rs232RETBIT2: decfsz CONDURL,F

goto RETBIT2decfsz CONDURH,Fgoto RETBIT1retlw 0

;********************************************************************; "TBITST";Rutina de temporización para el bit de inicio en modo Recepción.;Esta temporización es de 1,5 con respecto a la del resto de bits.;Así se consigue que el chequeo se produzca, aproximadamente, en el;centro de cada célula de bit recibido.;********************************************************************

TBITST: clrwdtmovlw DURSTHmovwf CONDURH

TBITST1: movlw DURSTLmovwf CONDURL

TBITST2: decfsz CONDURL,Fgoto TBITST2decfsz CONDURH,Fgoto TBITST1retlw 0

Página 3

Page 18: Subrutinas pic

rs232b

; - PROGRAMA Nº 53 -; "rs232.inc";********************************************************************;Conjunto de rutinas de control de transmisión vía RS232.;El programa principal que usa estas rutinas tiene que cargar las;siguientes variables:

;CLKIN: Frecuencia del oscilador en ciclos/segundo.;BAUDIOS: Frecuencia de comunicación.;TXMOD: Modo de transmisión: "1" transmite primero bit LSB.;RXMOD: Modo de recepción: "1" recibe primero bit LSB.;BITTR: Número de bits a transmitir: 7 u 8.;BITRC: Número de bits a recibir: 7 u 8.;BITSP: Número de bits de stop: 1 o 2.;CONBIT: Contador de bits.;********************************************************************

CLKOUT equ CLKIN >> 2 ;CLKOUT=CLKIN/4.DURBIT equ ((CLKOUT/BAUDIOS)/3)-.5 ;Establece duración del bit.DURBITL equ low DURBIT ;Calcula la parte baja de RET.DURBITH equ high DURBIT+1 ;Calcula la parte alta de RET.DURST equ (DURBIT/2)+DURBIT ;Calcula duración del bit de inicio (START).DURSTL equ low DURST ;Calcula parte baja de START.DURSTH equ high DURST+1 ;Calcula parte alta de START.

CBLOCK 0x5E REGRC ;Registro de recepción.REGTR ;Registro de transmisión.CONTR ;Contador de bits transmitidos.CONDURL ;Contador de delay parte baja.CONDURH ;Contador de delay parte alta.CONBIT ;Contador de bits.ENDC

#define PATTR PORTB,4 ;Línea de transmisión#define PATRC PORTB,5 ;Línea de recepción

;********************************************************************; "REC";Rutina de recepción. Después de la detección del bit de inicio;espera la recepción de una palabra de 7 u 8 bits, según se programe;la variable "BITRC". Además, según el valor de "RXMOD", se recibirá;primero el bit de mayor o menor peso ("RXMOD"=1 primero el LSB).;********************************************************************

REC: clrf REGRC ;Borrar registro receptor.

REC1: clrwdtbtfsc PATRCgoto REC1 ;Espera el bit de inicio (0).call TBSTREC ;Tiempo de retraso del bit de inicio

;(1.5 de la célula

de bit).

IF BITRC == 8

movlw 8 ;8 bits de datos.

ELSE

movlw 7 ;7 bits de datos.

ENDIF

movwf CONBIT

REC2:bcf STATUS,C

IF RXMOD == 1

rrf REGRC,F ;Recibir primero el LSB.

ELSE

rlf REGRC,F ;Recibir primero el MSB.

ENDIF

btfsc PATRC ;Chequea bit de entrada.

IF RXMOD == 1IF BITRC == 8

bsf REGRC,7 ;Activa bit 7 de REGREC si nºbits=8;y 1º bit LSB.

ELSE

bsf REGRC,6 ;Activa bit 6 de Rxdreg si nºbits=7

Página 1

Page 19: Subrutinas pic

rs232b;y 1º bit LSB.

ENDIFELSE

bsf REGRC,0 ;Activa bit 0 de Rxdreg si 1º el bit MSB.

ENDIF

call RETBIT ;Espera entre bits.decfsz CONBIT,F ;Decrementa contador de nº de bits.goto REC2call RETBIT

IF BITSP == 2

call RETBIT

ENDIF ;Espera 1 o 2 bits de stop.

retlw 0

;********************************************************************; "TR";Rutina de transmisión. Tras el bit de inicio se transmite la palabra;contenida en el registro transmisor REGTR, seguido de uno o dos;bits de stop, según se programe la variable BITSP.;********************************************************************

TR:IF BITTR == 8

movlw 8 ;Transmisión de palabras de 8 bits.

ELSE

movlw 7 ;Transmisión de palabras de 7 bits.

ENDIF

movwf CONBIT

IF TXMOD == 1 ;Si se transmite 1º el LSB y la palabraELSE ;es de 7 bits, el registro transmisor IF BITTR == 8 ;se desplaza una posición a la

izquierda ELSE ;para descartar el 8º bit.

rlf REGTR,F

ENDIFENDIF

bcf PATTR ;Transmite el bit de inicio.call RETBIT

TR1:bcf STATUS,C

IF TXMOD == 1

rrf REGTR,F ;Desplaza a dcha. si 1º es el LSB.

ELSE

rlf REGTR,F ;Desplaza a izda. si 1º es el MSB.

ENDIF

btfsc STATUS,C ;Si el carry es uno, se transmite 1bsf PATTR ; "btfss STATUS,C ;Si el carry es cero se transmite 0.bcf PATTR ; "call RETBIT ;decfsz CONBIT,F ;Decrementa contador de bits.goto TR1 ;Si no es cero repite ciclo.bsf PATTR ;Si es cero transmite un bit de stop.call RETBIT ;IF BITSP == 2

bsf PATTR ;Transmite segundo bit de stop.call RETBIT ;

ENDIF

retlw 0

;********************************************************************; "TempB";Rutina de temporización para los intervalos entre bit y bit.;********************************************************************

TempB: clrwdt

Página 2

Page 20: Subrutinas pic

rs232bmovlw DURBITHmovwf CONDURH

TempB1: movlw CONDURLmovwf CONDURL

TempB2: decfsz CONDURL,Fgoto TempB2decfsz CONDURH,Fgoto TempB1retlw 0

;********************************************************************; "TempST";Rutina de temporización para el bit de inicio en modo Recepción.;Esta temporización es de 1,5 con respecto a la del resto de bits.;Así se consigue que el chequeo se produzca, aproximadamente, en el;centro de cada célula de bit recibido.;********************************************************************

TempST: clrwdtmovlw DURSTHmovwf CONDURH

TempST1:movlw DURSTLmovwf CONDURL

TempST2: decfsz CONDURL,Fgoto TempST2decfsz CONDURH,Fgoto TempST1retlw 0

Página 3

Page 21: Subrutinas pic

rut_i2c

;******************************************************************************; "rut_i2c";Aquí se engloban el conjunto de subrutinas necesarias para la comunicación I2C.;Subrutinas:;; ENVINI: envía el MAESTRO la condición de inicio.; ENVSTOP: envía el MAESTRO la condición de STOP.; ENVBYTE: envía el byte contenido en el registro W.; LEEBYTE: se lee un byte del SERVIDOR. El byte leído estará en W.;******************************************************************#define SCL PORTC,3#define SDA PORTC,4

;******************************************************************; "SDABAJO";Pone la línea de dato en nivel bajo;******************************************************************SDABAJO:

bsf STATUS,RP0 ;Programa SDA como salida.bcf SDA ; "bcf STATUS,RP0 ;bcf SDA ;Pone a 0 la línea SDA.return

;******************************************************************; "SCLBAJO";Pone la línea de reloj en nivel bajo.;******************************************************************SCLBAJO:

bsf STATUS,RP0 ;Programa SDL como salida.bcf SDL ; "bcf STATUS,RP0 ;bcf SDL ;Pone a 0 la línea SDL.return

;******************************************************************; "SDAZ;Pone la línea de datos en alta impedancia.;******************************************************************SDAZ:

bsf STATUS,RP0 ;Programa SDA como entrada.bsf SDA ; "bcf STATUS,RP0 ;return

;******************************************************************; "ENVINI;Se envía la condición de Inicio.;******************************************************************ENVINI: bcf PIR1,SSPIF ;Borra indicador de interrupción.

bsf STATUS,RP0 ;Selecciona banco 1.bsf SSPCON2,SEN ;Activa secuencia de inicio.bcf STATUS,RP0 ;Selecciona banco 0.

ENVINI1: btfss PIR1,SSPIF ;¿Fin de secuencia de inicio?goto ENVINI1 ;No: espera.return ;Sí: retorna

;********************************************************************; " ENVSTOP ";Envía la secuencia de stop.;********************************************************************

ENVSTOP: bcf PIR1,SSPIF ;Borra indicador de interrupción.bsf STATUS,RP0 ;Selecciona banco 1.bsf SSPCON2,PEN ;Activa secuencia de Stop.bcf STATUS,RP0 ;Selecciona banco 0.

ENVSTOP1:btfss PIR1,SSPIF ;¿Fin de secuencia de Stop?goto ENVSTOP1 ;No: espera.return ;Sí: retorna.

;********************************************************************; " ENVBYTE ";Transmite byte del W vía I2C. La rutina finalizará al recibir /ACK.;********************************************************************

ENVBYTE: bcf PIR1,SSPIF ;Borra indicador de interrupción.movwf SSPBUF ;Carga byte en buffer de salida el

;byte a transmitir.

ENVBYTE1: btfss PIR1,SSPIF ;¿Recibido el bit /ACK?goto ENVBYTE1 ;No: espera.return ;Sí: retorna.

;********************************************************************; " LEEBYTE ";Lee byte procedente del dispositivo I2C seleccionado, y lo devuelve;en W. Seguidamente se genera y transmite el bit /ACK.;********************************************************************

Página 1

Page 22: Subrutinas pic

rut_i2c

LEEBYTE: bcf PIR1,SSPIF ;Borra indicador de interrupción.bsf STATUS,RP0 ;Selecciona banco 1.bsf SSPCON2,RCEN ;Activa el modo receptor.bcf STATUS,RP0 ;Selecciona banco 0.

LEEBYTE1: btfss PIR1,SSPIF ;¿Recibidos los 8 bits?goto LEEBYTE1 ;No: espera.bcf PIR1,SSPIF ;Sí: restaura el indicador.bsf STATUS,RP0 ;Selecciona banco 1.bcf SSPCON2,ACKDT ;Pone bit ACK a "0".bsf SSPCON2,ACKEN ;Activa secuencia de generación de ACK.bcf STATUS,RP0 ;Selecciona banco 0.

LEEBYTE2: btfss PIR1,SSPIF ;¿Secuencia ACK finalizada?goto LEEBYTE2 ;No: espera.movf SSPBUF,W ;Sí: lee el byte recibido.return

Página 2

Page 23: Subrutinas pic

ruti2c;********************************************************************; I2C.INC;;Conjunto de rutinas para transmisión/recepción de bytes en bus I2C.;********************************************************************

;********************************************************************;Definición de registros empleados por el software del bus I2C ;********************************************************************Clkout equ CLKIN >> 2 ;Frecuencia de trabajo (Clkin/4)

Ret4us set (Clkout/.250000) ;Constante para 4 uSRet47us set (Clkout/.212766) ;Constante para 4.7 uSRet5us set (Clkout/.200000) ;Constante para 5 uS

CBLOCK 0x58

Datrans ;Dato que va a ser transmitidoConbit ;Nº de bits a transmitir/recibir (0:7)Estadobus ;Registro de estado del bus I2CControlbus ;Registro de control del bus I2CRetcon ;Variable de temporizaciónDatranscop ;Copia del dato a transmitirENDC

;********************************************************************;Definición de las líneas del bus I2C;********************************************************************

#define SCL PORTB,7#define SDA PORTB,6#define SCLDIR PORTB,7#define SDADIR PORTB,6#define ESCRITURA 0#define LECTURA 1

;********************************************************************;Definición de los bits del registro de estado del bus I2C;********************************************************************

#define Busocup Estadobus,0 ;Bus I2C ocupado#define Abandon Estadobus,1 ;Comunicación abortada#define Transprog Estadobus,2 ;Transmisión en progreso#define Recprog Estadobus,3 ;Recepción en progreso#define Transfin Estadobus,4 ;Transmisión finalizada#define Recfin Estadobus,5 ;Recepción finalizada#define Errcom Estadobus,6 ;Error en comunicación#define ErrACK Estadobus,7 ;Error en bit ACK

;********************************************************************;Definición de los bits del registro de control del bus I2C;********************************************************************

#define Ultbytetr Controlbus,2 ;Indica si es el último byte a recibir

;********************************************************************; Macro de propósito general;********************************************************************

LIBUS MACRO bsf STATUS,RP0 ;Selecciona banco 1 bsf SDA ;SDA en triestado bsf SCL ;SCL en triestado bcf Busocup ENDM

;********************************************************************; " Inibus ";Inicialización del Bus I2C;********************************************************************

Inibus: bcf STATUS,RP0 ;Selecciona página 0 de datos movf PORTB,W ;Carga puerta B andlw 0x3f movwf PORTB ;Pone a 0 los latch internos ;de las líneas SCL y SDALIBUS ;Coloca SDA y SCL en triestad

clrf Controlbus ;Borra registro de controlclrf Estadobus ;Borra registro de estadoreturn

;********************************************************************; " Inic ";Transmisión de la condición de inicio;********************************************************************

Inic: bsf STATUS,RP0 ;Selecciona página 1bsf SDA ;Pone como entradas las señales SDA ybsf SCL ;SCL que al estar con resistencia

Página 1

Page 24: Subrutinas pic

ruti2c ;pull-up, las líneas SDA y SCL se mantienen a "1"

call Ret4uSbcf SDA ;La señal SDA se configura como salida

;que saca el "0" del latch interno ha-;ciendo que la línea SDA caiga a "0";mientras SCL se mantiene a "1" (con-;dición de inicio)

call Ret47uSbsf Busocup ;Activa flag de bus ocupadoreturn

;********************************************************************; " Envstop ";Transmisión de la condición de stop;********************************************************************

Envstop: bsf STATUS,RP0 ;Selecciona página 1 de datosbcf _SCL ;Las señales SCL y SDA se programanbcf _SDA ;como salidas. El contenido de los

;latch internos hace que las líneas;SCL y SDA se pongan a "0"

bsf _SCL ;Esta señal se programa ahora como;entrada en alta impedancia que, gra-;cias a las pull-up internas, pone a;"1" la línea SCL.

call Delay4uSbsf _SDA ;Esta señal se programa ahora como

;entrada en alta impedancia que, gra-;cias a las pull-up internas, genera un;flanco de subida en la línea SDA (con-;dición de stop).

call Delay47uS ;Asegura que no se envía una nueva;condición de start justo después de la;de stop.

bcf _Bus_Busy ;Tras el stop se considera que el bus ;está libre borrando el bit de estado

return

;********************************************************************; " Trcancel ";Abortar la transmisión;********************************************************************

Trcancel: call Txt_Stop_Bit ;Transmite la condición de stopbsf _Abort ;Activa flag en registro de estadoreturn

;********************************************************************; " Trbyte ";Transmisión de un byte de datos. El byte a transmitir debe cargarse;previamente en el registro DataByte (---0xCh---);********************************************************************

Trbyte: movf DataByte,w ;Realiza una copia del byte a trans-movwf DataByteCopy ;mitir (pos.0x0e)bsf _Txmt_Progreso ;Activa flag de transmisión en cursobcf _Txmt_Acabada ;Desactiva flag de finalizaciónmovlw 8movwf BitCount ;Número de bits a transmitirbsf STATUS,RP0 ;Selecciona página 1 de datos

TxtNextBit:clrwdt ;Refresco del WDTbcf _SCL ;Pone a "0" la línea SCLrlf DataByteCopy,f ;Desplaza bit de más pesobcf _SDA ;Pone a "0" la l¡nea SDAbtfsc STATUS,C ;Testea bit a sacar sito en el carrybsf _SDA ;Saca "1" por la línea SDA poniendo

;la señal SDA como entrada pull-upcall Delay47uSbsf _SCL ;Pone a "1" la línea SCL poniendo

;la señal SCL como entrada pull-upcall Delay4uSdecfsz BitCount,f ;Decrementa contador de bitsgoto TxtNextBit ;Chequeo del bit ACK

bcf _SCL ;Pone a "0" la línea SCLbsf _SDA ;Pone a "1" la línea SDA para detec-

;tar cuándo el slave la pone a "0"call Delay47uSbsf _SCL ;Pone a "1" línea de relojcall Delay4uSbcf STATUS,RP0 ;Selecciona página 0 de datosbtfsc _SDA ;La señal SDA debe estar a "0" envia-

;do por el slavegoto TxtErrorAckbsf STATUS,RP0 ;Selecciona página 1 de datosbcf _SCL ;Pone a "0" la línea SCLbcf _Txmt_Progreso ;Borra flag de transmisión en cursobsf _Txmt_Acabada ;Activa flag de fin de transmisiónbcf _ACK_Error ;Bit ACK okey

Página 2

Page 25: Subrutinas pic

ruti2cbcf _Bus_Busy ;Flag de que el bus está librereturn

TxtErrorAck:LIBERA_BUS bcf _Txmt_Progreso ;Borra flag de transmisión en cursobcf _Txmt_Acabada ;Borra flag de fin de transmisiónbsf _ACK_Error ;Activa bit de error ACK (NACK)

return

;********************************************************************; " RecByte ";Recepción de un byte desde el slave;El dato recibido se almacena en el registro DataByte (posición 0xch);El bit _Ultimo_Byte del registro de control determina si se espera recibir;más bytes desde el slave, en cuyo caso se le manda ACK o, si es el último,;en cuyo caso se envía NACK.;********************************************************************

RcvByte: bsf _Rcv_Progreso ;Flag de recepción en cursobcf _Rcv_Acabada ;Desactiva flag de fin de recepciónmovlw 0x08 ;Carga el contador de bits a recibirmovwf BitCount

RcvNextBit:clrwdtbsf STATUS,RP0 ;Selección de página 1 de datosbcf _SCL ;Pone a "0" la línea de relojbsf _SDA ;Pone a "1" la línea de datoscall Delay47uSbsf _SCL ;El reloj pasa a "1". El bit de datos

;es puesto por el slavecall Delay4uSbcf STATUS,RP0 ;Seleciona página 0 de datosbcf STATUS,C ;Pone el flag carry a "0"btfsc _SDA ;Chequea el nivel en línea de datosbsf STATUS,C ;Está a "1", activa el carryrlf DataByte,f ;Desplaza a la izda. (primero el bit

;de más peso)decfsz BitCount,f ;Decrementa contador de bits a recibirgoto RcvNextBit

;El Master genera ACK si no es el último byte a recibir. Si es el último;se genera NACK y a continuación se debe generar la condición de stop.

bsf STATUS,RP0 ;Selecciona página 1 de datosbcf _SCL ;Pone a "0" la línea de relojbcf _SDA ;Pone a "0" la línea de datos (ACK)btfsc _Ultimo_Byte ;Determina si es el último bytebsf _SDA ;Pone a "1" la línea de datos (NACK)call Delay47uSbsf _SCL ;Pone a "1" la línea de relojcall Delay4uSbcf _SCL ;Pone a "0" la línea de relojbcf _Rcv_Progreso ;Desactiva flag de recepción en cursobsf _Rcv_Acabada ;Activa flag de fin de recepciónbcf _ACK_Error ; ACK okreturn

;********************************************************************;Rutinas de temporización de propósito general;********************************************************************

Delay5uS:movlw ((_5uS_Delay-5)/3+1)

delay: movwf DelayCountdecfsz DelayCount,fgoto $-1return

Delay47uS:movlw ((_47uS_Delay)-8/3+1)goto delay

Delay4uS:movlw ((_4uS_Delay)-8/3+1)goto delay

end

Página 3

Page 26: Subrutinas pic

teclado;********************************************************************; "teclado.inc";;Es un conjunto de subrutinas para la gestión de un teclado hexadecimal;organizado en una matriz de 4 x 4, tal y como es el caso del teclado;incorporado en la tarjeta de ampliación MicroPic Trainer PLUS.;Este fichero se debe incluir en los futuros programas fuente mediante;la directiva INCLUDE.;;CHEQTEC: Realiza un barrido del teclado y detecta si hay alguna; tecla pulsada. La variable "CODTEC" retorna con el código; de la tecla pulsada, o el 0x80 en caso de no existir; pulsación.;;TECHEX: Convierte el código de tecla en código HEX (del 0 a F).; Antes de llamar a esta rutina, la variable "CODTEC" debe; contener el código de tecla; al finalizar, la rutina; devolverá, en la misma variable "CODTEC", el código HEX.;;El teclado está conectado al PORTB, y su disposición es la siguiente:;; RB0 RB1 RB2 RB3; ^ ^ ^ ^ TECLA CODIGO; | | | | ----- --------------; |---|---|---|---| 0 01111101 = 0x7D; RB4 --> | 1 | 2 | 3 | F | 1 11101110 = 0xEE; |---|---|---|---| 2 11101101 = 0xED; RB5 --> | 4 | 5 | 6 | E | 3 11101011 = 0xEB; |---|---|---|---| 4 11011110 = 0xDE; RB6 --> | 7 | 8 | 9 | D | 5 11011101 = 0xDD; |---|---|---|---| 6 11011011 = 0xDB; RB7 --> | A | 0 | B | C | 7 10111110 = 0xBE; |---|---|---|---| 8 10111101 = 0xBD; 9 10111011 = 0xBB; A 01111110 = 0x7E; B 01111011 = 0x7B; C 01110111 = 0x77; D 10110111 = 0xB7; E 11010111 = 0x; F 11100111 = 0xE7;;Hubiera sido más interesante que RB4-RB7 actuaran como entradas para;poder utilizar la capacidad que tiene el PIC de provocar interrupción;al cambiar de estado estas líneas. Pero esto no es posible dado que,;en la Trainer, las líneas RB6 y RB7 forman parte también del circuito;de grabación.

CBLOCK 0x54 ;Inicio de las variables.CODTEC ;Código final de tecla.COLUM ;Nº de columnas a explorar.TTEC ;Temporal de código.TTRISB ;Estado temporal de TRISBENDC

;********************************************************************; "CHEQTEC";Rutina de exploración del teclado. La variable "CODTEC" retorna con;el código de la tecla pulsada, o el código 0x80 si no hay pulsación.;********************************************************************

CHEQTEC: bsf STATUS,RP0 ;Selecciona banco 1.movf TRISB,W ;Salva el estado actual de TRISB.movwf TTRISB ; "movlw b'00001111' ;Programa RB0-RB3 como entradasmovwf TRISB ;y RB4-RB7 como salidas.bcf OPTION_REG,7 ;Habilita resistencias de PORTB.bcf STATUS,RP0 ;Selecciona banco 0.movlw 4 ;Nº de columnas a explorar.movwf COLUM ; "movlw b'01111111' ;Saca "0" por la fila RB7.movwf CODTEC ; "

CHEQTEC1:movf CODTEC,W ; "movwf PORTB ; "

nop ;Separación de seguridad.movf PORTB,W ;Lectura del PORTB.movwf TTEC ;Guarda temporalmente la lectura.subwf CODTEC,W ;Chequea pulsación.btfss STATUS,Z ;Hay alguna pulsada ?goto CHEQTEC2 ;Sí: va a CHEQTEC2.bsf STATUS,C ;No: activa Carry.rrf CODTEC,F ;Prepara selección de ladecfsz COLUM,F ;siguiente columna.goto CHEQTEC1 ;Si no es la última salta a CHEQTEC1.movlw 0x80 ;Si es la última carga 80h en W.

Sale: movwf CODTEC ;Carga el 80h en CODTEC (sin pulsación).

movf TTRISB,W ;Recupera dirección de PORTB original.bsf STATUS,RP0 ;Selecciona banco 1.movwf TRISB ;Repone valor original en TRISB.bsf OPTION_REG,7 ;Inhibe resistencias de PORTB.bcf STATUS,RP0 ;Selecciona banco 0.

Página 1

Page 27: Subrutinas pic

tecladoreturn

CHEQTEC2: call R20MS ;Retardo de 20 ms para rebotes.movf CODTEC,W ;Chequea teclado para ver hay nuevamovwf PORTB ;pulsación.nop ; "movf PORTB,W ; "subwf TTEC,W ; "btfss STATUS,Z ;¿Es la misma pulsación?goto CHEQTEC1 ;No: continúa con la exploración.movf TTEC,W ;Si: se guarda valor en "CODTEC" elgoto Sale

;********************************************************************; "TECHEX";Convierte el código de tecla que haya en la variable "CODTEC" a código;Hexadecimal. El resultado se tiene en la variable "CODTEC".;******************************************************************** TECTAB movf COLUM,W

addwf PCL,F ;Calcula desplazamientoretlw 0x7D ;0retlw 0xEE ;1retlw 0xED ;2retlw 0xEB ;3retlw 0xDE ;4retlw 0xDD ;5retlw 0xDB ;6retlw 0xBE ;7retlw 0xBD ;8retlw 0xBB ;9retlw 0x7E ;Aretlw 0x7B ;Bretlw 0x77 ;Cretlw 0xB7 ;Dretlw 0xD7 ;Eretlw 0xE7 ;F

TECHEX: movf CODTEC,W ;Carga en W el código de tecla. movwf TTEC ;Salva el código temporalmente. clrf COLUM ;Pone a 0 el contador de columnas, que

;en este caso se emplea como código de;carácter hexadecimal.

TECHEX1: call TECTAB ;Busca código en la tabla. subwf TTEC,W ;Compara con el de la tecla. btfsc STATUS,Z ;¿Coincide? goto TECHEX2 ;Sí: va a conseguir el código hexadecimal. incf COLUM,F ;No: incrementa contador columnas. goto TECHEX1 ;Repite conversión.

TECHEX2: movf COLUM,W ;Graba en CODTEC el contadormovwf CODTEC ;de columnas.return

Página 2

Page 28: Subrutinas pic

tecpc

;********************************************************************; "tecpc";Son un conjunto de subrutinas para comunicación con un teclado PC.;Es necesaria la conexión del teclado y el entrenador a través de;una placa de adaptación.;Las señales a manejar son las siguientes:; CONECTOR TECLADO CONECTOR MICRO; Reloj <---------INVERSOR------------- RC1 (RELSAL); -----------------------------> RC2 (RELEN); Datos <------------------------------ RC7 (DATSAL); -----------------------------> RC0 (DATEN);Subrutinas disponibles para el teclado PC.

;rtecpc: Recibe un dato de teclado que se guarda en Rdato.

;captec: Capta en serie el dato del teclado y actualiza el error.

;rsend: Envía el código de reeenvío al teclado.

;manda: Envía al teclado el byte contenido en Rdato.

;obtpar: Obtiene el bit de paridad del dato entrante en serie.

;cheqpar: Comprueba que la paridad de Rdato (parobt) y la del bit entrante coinciden en impar.

;mandack: Envía al teclado el byte de Rdato y espera hasta recibir un código ACK de reconocimiento.

;cheqbat: comprueba que el chequeo del teclado ha sido correcto y programa el bit de error;en consecuencia.

;veltec: Programa la velocidad de escrutación de teclas y el retardo;entre pulsaciones. El byte de programación debe estar contenido en Rdato.

;progled: Activación o desactivación de los leds del teclado.

;modtec: Programación del modo en que el teclado envía una tecla.;El MSB del registro Rest es el bit de paridad leído en el;dato recibido en serie.;; Registro Rest;; Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0; parent - - biterr - - - parobt;********************************************************************

CBLOCK 0x4ARdato, T1rtec, T2rtec, Tinter Cgentec, Rest, TRdato, MtriscRtecla, CcheqbatENDC

;Rdato: #define RELSAL PORTC,1#define DATSAL PORTC,7#define DATEN PORTC,0#define RELEN PORTC,2#define biterr Rest,4#define parobt Rest,0#define parent Rest,7

;********************************************************************; "rtecpc";Esta subrutina recibe un byte desde el teclado del PC, que estará;disponible en el registro Rdato. Si en la recepción ocurriese algún;error el registro Rest tendrá a 1 su quinto bit (biterr).;********************************************************************

rtecpc: bsf STATUS,RP0 ;Selección de banco 1.movf TRISC,W ;Guarda las direcciones de las líneasbcf STATUS,RP0 ;del puerto C en el registro Mtrisc,movwf Mtrisc ;del banco 0.andlw b'01111101' ;Programa RC7 y RC1 como salidas, RC2iorlw b'00000101' ;y RC0 como entradas. El resto no

varía.bsf STATUS,RP0 ;Selección de banco 1.movwf TRISC ;Programación del registro TRISC.bcf STATUS,RP0 ;Selección del banco 0.bcf RELSAL ;Libera el reloj para el teclado.movlw 0x40 ;Carga valores para intentos de

lectura.movwf T1rtec ; "

rtecpc1: movlw 0xFF ; "movwf T2rtec ; "

rtecpc2: btfsc RELEN ;¿Reloj de entrada=0?goto rtecpc3 ;No: sigue intentando leer 0.btfsc DATEN ;Sí: ¿Teclado envía bit de START?goto rtecpc3 ;No: sigue intentando bit de START.call captec ;Sí: captura byte.goto rtecpc4

Página 1

Page 29: Subrutinas pic

tecpcrtecpc3: decfsz T2rtec,F ;Bucle de retardo.

goto rtecpc2 ; "decfsz T1rtec,F ; "goto rtecpc1 ; "bsf biterr ;Activa bit de error.

rtecpc4: bsf RELSAL ;Cancela reloj al teclado.movf Mtrisc,W ;Recupera direcciones de PORTC.bsf STATUS,RP0 ; "movwf TRISC ; "bcf STATUS,RP0 ; "return

;********************************************************************; "captec";Subrutina encargada de leer bit a bit los nueve que envía el teclado,;incluída la paridad. Si existe algún error en la comunicación o en;paridad, la subrutina activa el bit de error. El dato estará presente;en el registro Rdato. ;********************************************************************

captec: bcf biterr ;Borra marca de error.bcf RELSAL ;Pone a "1" el reloj al teclado PC.

rel0_1: btfsc RELEN ;Espera a que el teclado ponga a 0goto rel0_1 ;su señal de reloj.btfsc DATEN ;Espera a recibir el bit de STARTgoto rel0_1 ; "movf INTCON,W ;Salva registro de interrupciones.movwf Tinter ; "bcf INTCON,GIE ;Inhibe interrupciones.movlw 8 ;Carga el número de bits a recibir,movwf Cgentec ;sin contar el de paridad.

rel0_2: btfss RELEN ;Espera a que pase el nivel 0 delgoto rel0_2 ;reloj emitido por el teclado.

rel1_1: btfsc RELEN ;Espera a que pase el nivel 1 delgoto rel1_1 ;reloj emitido por el teclado.btfss DATEN ;Capta bit entrante y lo va cargandogoto captec2 ;en Rdato mediante rotaciones.bsf STATUS,C ;Carga 1 en Rdato.

captec1: rrf Rdato,F ; "decfsz Cgentec,F ;Decrementa contador de bits.goto rel0_2 ;Si no se ha terminado salta a rel0_2.goto rel0_3 ;Si ha finalizado sigue en rel0_3.

captec2: bcf STATUS,C ;Carga 0 en Rdato.goto captec1

rel0_3: btfss RELEN ;Espera a que pase el nivel 0 delgoto rel0_3 ;reloj emitido por el teclado.

rel1_3: btfsc RELEN ;Espera a que pase el nivel 1 delgoto rel1_3 ;reloj emitido por el teclado.btfsc DATEN ;Capta bit entrante de paridad.goto captec3bcf parent ;Programa bit de paridad entrante.goto captec4

captec3: bsf parent ;Programa bit de paridad entrante.

captec4: call obtpar ;Se obtiene la paridad del byte de;Rdato y se compara con la recibida.

call cheqpar ;Programa bit de error.

rel0_4: btfss RELEN ;Espera a que pase el nivel 0 delgoto rel0_4 ;reloj emitido por el teclado.

rel1_4: btfsc RELEN ;Espera a que pase el nivel 1 delgoto rel1_4 ;reloj emitido por el teclado.btfss DATEN ;¿Bit de STOP=1?bsf biterr ;No: error.

rel0_5: btfss RELEN ;Espera a que pase el nivel 0 delgoto rel0_5 ;reloj emitido por el teclado.movf Tinter,W ;Recupera estado de interrupciones.movwf INTCON ; "bsf RELSAL ;Anula reloj al teclado PC.btfss biterr ;¿Existe condición de error?return ;No: retorno.call rsend ;Sí: rutina de reenvío de byte.btfss biterr ;¿Existe condición de error?goto captec ;No: repite captación de byte.return ;Sí: retorna con marca de error.

;********************************************************************; "rsend";Esta subrutina envía al teclado el código que aquél interpreta como;petición de reenvío del último byte. El código concreto es "FEh".;********************************************************************

Página 2

Page 30: Subrutinas pic

tecpcrsend: movlw 0xFE ;Escribe código de reenvío.

call manda ;Envía al teclado un byte.return

;********************************************************************; "manda";Subrutina que envía al teclado el byte contenido en el registro Rdato.;Se activa el bit de error si éste se produjese. No altera Rdato.;********************************************************************

manda: bsf STATUS,RP0 ;Selección de banco 1.movf TRISC,W ;Guarda las direcciones de las líneasbcf STATUS,RP0 ;del puerto C en el registro Mtrisc,movwf Mtrisc ;del banco 0.andlw b'01111101' ;Programa RC1 y RC7 como salidas, RC0iorlw b'00000101' ;y RC2 como entradas. El resto no

varía.bsf STATUS,RP0 ;Selección de banco 1.movwf TRISC ;Programación del registro TRISC.bcf STATUS,RP0 ;Selección del banco 0.bcf DATSAL ;Pone bit de START.bcf RELSAL ;Libera señal de reloj.movlw 0xFF ;Carga valores para intentos demovwf T1rtec ;comunicación.

mrecar: movlw 0xFF ; "movwf T2rtec ; "

mrel0_1: btfss RELEN ;¿Reloj de teclado igual a 1?goto conrut ;No: continúa rutina.decfsz T2rtec,F ;Sí: Bucle de espera hasta ver elgoto mrel0_1 ;nivel bajo del reloj procedente deldecfsz T1rtec,F ;teclado PC.goto mrecar ;salta a recargar registro.bsf biterr ;Se activa la señal de error.

salida: bsf RELSAL ;Bloquea la línea de reloj.movf Mtrisc,W ;Recupera direcciones de PORTC.bsf STATUS,RP0 ; "movwf TRISC ; "bcf STATUS,RP0 ; "return

conrut: movf INTCON,W ;Salva registro de interrupciones.movwf Tinter ; "bcf INTCON,GIE ;Inhibe interrupciones.movlw 8 ;Carga el número de bits a enviar,movwf Cgentec ;sin contar el de paridad.

manda1: rrf Rdato,F ;Rotamos dato a enviar para ponerbtfsc STATUS,C ;en C el bit a enviar.goto manda2bcf DATSAL ;Envía un 0 al teclado.goto mrel0_2

manda2: bsf DATSAL ;Envía un 1 al teclado.

mrel0_2: btfss RELEN ;Espera a que pase el nivel 0 delgoto mrel0_2 ;reloj.

mrel1_1: btfsc RELEN ;Espera a que pase el nivel 1 delgoto mrel1_1 ;reloj.decfsz Cgentec,F ;Decrementa contador de bits.goto manda1 ;Repite envío de bit.rrf Rdato,F ;Rota dato para dejarlo como estabacall obtpar ;Obtiene la paridad del byte.btfss parobt ;¿Paridad impar?goto manda3 ;No: sigue en manda3.bcf DATSAL ;Sí: saca 0 para paridad impar.goto mrel0_3

manda3: bsf DATSAL ;Manda 1 para paridad impar.

mrel0_3: btfss RELEN ;Espera a que pase el nivel 0 delgoto mrel0_3 ;reloj.

mrel1_2: btfsc RELEN ;Espera a que pase el nivel 1 delgoto mrel1_2 ;reloj.bsf DATSAL ;Deja a nivel alto la línea de datos

;para quedar en ESPERA.mrel0_4: btfss RELEN ;Espera a que pase el nivel 0 del

goto mrel0_4 ;reloj.

mrel1_3: btfsc RELEN ;Espera a que pase el nivel 1 delgoto mrel1_3 ;reloj.btfss DATEN ;Chequea el dato de entrada.goto manda4 ;Error si datos está a 0.bsf biterr ;Borra ERROR si datos está a 1.

mrel0_5: btfss RELEN ;Espera a que pase el nivel 0 delgoto mrel0_5 ;reloj.

mdat1: btfss DATEN ;Espera a encontrar el nivel 1 en

Página 3

Page 31: Subrutinas pic

tecpcgoto mdat1 ;línea de datos.bsf RELSAL ;Bloquea reloj.movf Tinter,W ;Recupera estado de interrupciones.movwf INTCON ; "goto salida

manda4: bcf biterr ;Si DATEN=1 programa ERROR.goto mrel0_5

;********************************************************************; "cheqpar";Subrutina para chequear paridad y programar en consecuencia el bit;de error.;********************************************************************

cheqpar: btfss parobt ;¿Paridad obtenida es impar?goto cheqpar2 ;No: continúa en proger1.btfsc parent ;Sí: ¿bit de paridad entrante es 0?goto cheqpar3 ;No: va a programar error.

cheqpar1: bcf biterr ;Sí: borra bit de error y retorna.return

cheqpar2: btfsc parent ;¿Paridad entrante es par?goto cheqpar1 ;No: va a borrar el error.

cheqpar3: bsf biterr ;Programa bit de error.return

;********************************************************************; "mandack";Subrutina que envía al teclado el byte contenido en el registro;Rdato y espera recibir un ACK (0xFA). Altera el registro Rdato.;Se activa el bit de error si éste se produjese.;********************************************************************

mandack: call manda ;Envía el dato al teclado.btfsc biterr ;¿Existe error?return ;Sí: retorna con el error.call rtecpc ;Subrutina para recibir un byte.btfsc biterr ;¿Existe error?return ;Sí: retorna con el error.movf Rdato,W ;¿Dato recibibido es ACK?xorlw 0xFA ; "btfsc STATUS,Z ; "return ;Sí: retorno.movf Rdato,W ;No: ¿es un RESEND?xorlw 0xFE ; "btfsc STATUS,Z ; "goto mandack ;Sí: repite el envío.bsf biterr ;No: activa error.return

;********************************************************************; "cheqbat";Subrutina que mira si el chequeo del teclado ha sido correcto. Si no;lo fuese se activaría el bit de error.;********************************************************************

cheqbat: movlw 0xFF ;Carga número de intentos.movwf Ccheqbat ; "

cheqbat1: call rtecpc ;Recibe byte desde el teclado.btfss biterr ;¿Hay error?goto cheqbat3 ;No: sigue en cheqbat3.decfsz Ccheqbat,F ;Sí: decrementa contador.goto cheqbat1 ;Salto a repetir consulta.

cheqbat2: bsf biterr ;Si hay error después de los intentosreturn ;se retorna con el error.

cheqbat3: movf Rdato,W ;¿Byte es AAh?xorlw 0xAA ; "btfss STATUS,Z ; "goto cheqbat2 ;No: activa error.return

;********************************************************************; "veltec";Subrutina que programa la velocidad de escrutación de las teclas y el;retardo entre pulsaciones. El byte de programación debe estar en el;registro Rdato.;********************************************************************

veltec: movf Rdato,W ;Salva Rdato en registro temporal.movwf TRdato ; "movlw 0xF3 ;Envía el código previo a la programa-movwf Rdato ;ción de velocidad y retardo.call mandack ; "movf TRdato,W ;Recupera byte de programación demovwf Rdato ;velocidad y retardo.btfss biterr ;¿Ha habido error en el envío anterior?call mandack ;No: envía el byte de programación.

Página 4

Page 32: Subrutinas pic

tecpcreturn ;Retorna.

;********************************************************************; "progled";Subrutina que activa o desactiva los leds del teclado de acuerdo al;1 o 0, respectivamente, que programemos en los bits de Rdato, de la;siguiente, manera:;Rdato0: Scroll Lock;Rdato1: Num Lock;Rdato2: Caps Lock;Rdato3 - Rdato7 = 0;biterr: 1 si hay error.;********************************************************************

progled: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xED ;Envía código para activación o desac-movwf Rdato ;tivación de leds.call mandack ; "movf TRdato,W ;Recupera valor de Rdato.movwf Rdato ; "btfss biterr ;¿Hay error en envío?call mandack ;No: manda código de leds.return ;Retorna.

;********************************************************************; "modtec";Subrutina que programa el modo en que el teclado va a enviar una;tecla.;Rdato = 0xFB -> Typematic;Rdato = 0xFC -> Make/Break;Rdato = 0xFD -> Make;Rtecla = Código de tecla.;biterr: 1 si hay error.;********************************************************************

modtec: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "call mandack ;Envía el código de modo.btfss biterr ;¿Error en el envío?goto modtec2 ;No: sigue en modtec2.

modtec1: movf TRdato,W ;Sí: recupera valor de Rdato.movwf Rdato ; "return

modtec2: movf Rtecla,W ;Envía el código de la teclacall mandack ;correspondiente a ese modo.goto modtec1

;********************************************************************; "teciden";Subrutina que lee la identificación del teclado. Si no fuese correcta;se activaría el bit de error.;********************************************************************

teciden: movlw 0xF2 ;Envía el código de identificación.movwf Rdato ; "call mandack ; "btfsc biterr ;¿Existe error?return ;Sí: retorna con el error.call rtecpc ;No: recibe byte desde teclado.btfsc biterr ;¿Existe error?return ;Sí: retorna con el error.movf Rdato,W ;No: ¿dato es igual a 0xAB?xorlw 0xAB ; "btfsc STATUS,Z ; "goto teciden1 ;Sí: sigue en teciden1.bsf biterr ;No: activa error.return ;Retorna.

teciden1: call rtecpc ;Recibe byte de identificación.btfsc biterr ;¿Error en la recepción?return ;Sí: retorno con error.movf Rdato,W ;No: ¿byte es igual a 83h?xorlw 0x83 ; "btfss STATUS,Z ; "bsf biterr ;No: activa error y retorna.return

;********************************************************************; "acttec";Subrutina para activar el teclado. Si se produce error se activa el;bit de error.;********************************************************************

acttec: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xF4 ;Envía código para activación delmovwf Rdato ;teclado.call mandack ; "movf TRdato,W ;Recupera valor de Rdato.movwf Rdato ; "return ;Retorna.

Página 5

Page 33: Subrutinas pic

tecpc

;********************************************************************; "destec";Subrutina para desactivar el teclado. Si se produce error se activa;el bit de error.;********************************************************************

destec: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xF5 ;Envía código para desactivación delmovwf Rdato ;teclado.call mandack ; "movf TRdato,W ;Recupera valor de Rdato.movwf Rdato ; "return ;Retorna.

;********************************************************************; "echotec";Subrutina que manda un ECHO al teclado y espera la recepción del ECO;de éste. Si se produce error se activa biterr.;********************************************************************

echotec: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xEE ;Envía código de ECHO.movwf Rdato ; "call manda ; "btfss biterr ;¿Hay error?goto echotec2 ;No: sigue en echotec2.

echotec1: movf TRdato,W ;Sí: recupera valor de Rdato.movwf Rdato ; "return ;Retorna.

echotec2: call rtecpc ;Recibe del teclado el byte de ECO.btfsc biterr ;¿Hay error?goto echotec1 ;Sí: recupera Rdato y retorna.movf Rdato,W ;No: compara byte recibido con elxorlw 0xEE ;valor del byte de ECO.btfss STATUS,Z ;¿Es byte de ECO?bsf biterr ;No: activa error.goto echotec1 ;Sí: recupera Rdato y retorna.

;********************************************************************; "initec";Subrutina que inicializa al teclado en las condiciones por defecto.;Si se produce error se activa biterr.;********************************************************************

initec: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xF6 ;Envía código de ECHO.movwf Rdato ; "call mandack ; "movf TRdato,W ;Recupera valor de Rdato.movwf Rdato ; "return

;********************************************************************; "modcod";Subrutina que determina el modo en que va a enviar el teclado el;código de exploración.;Rdato = 01 Modo 1;Rdato = 02 Modo 2;Rdato = 03 Modo 3;Rdato = 00 Detecta el modo actual, que queda depositado en Rdato.;biterr = 1 si hay error.;********************************************************************

modcod: movf Rdato,W ;Salva Rdato en TRdato.movwf TRdato ; "movlw 0xF0 ;Envía código de ECHO.movwf Rdato ; "call mandack ; "movf TRdato,W ;Recupera valor de Rdato.movwf Rdato ; "btfsc biterr ;¿Existe error?return ;Sí: retorna.call mandack ;No: envía el contenido de Rdato.btfsc biterr ;¿Existe error?return ;Sí: retorna.movf TRdato,W ;¿El contenido de Rdato inicial esxorlw 00 ;igual a 00h?btfss STATUS,Z ; "return ;No: retorna.call rtecpc ;Sí: recibe el byte de teclado quereturn ;informará del Modo actual.

;********************************************************************; "restec";Subrutina que envía al teclado el código de RESET.;Si se produce error se activa biterr.;********************************************************************

Página 6

Page 34: Subrutinas pic

tecpc

restec: movlw 0xFF ;Envía código de RESET.movwf Rdato ; "call mandack ; "btfss biterr ;¿Hay error?call cheqbat ;No: chequea la correcta

inicialización.return ;Sí: retorna.

Página 7