;============================================
; inf.pic.suky@live.com.ar
;============================================
list p=16f877A ; list directive to define processor
#include <p16f877A.inc> ; processor specific variable definitions
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF
;===========================================
; Declaración de Registros
;===========================================
W_TEMP equ 0x21 ;registro para guardar temporalmente W
STATUS_TEMP equ 0x22 ;registro para guardar temporalmente STATUS
FLAGS equ 0x23 ;registro para guardar las banderas
CONTADOR equ 0x24 ;registro para realizar conteo
RDATO equ 0x25 ;registro para guardar dato recibido
RPARIDAD equ 0x26 ;registro para guardar el bit paridad
CONT_BIT equ 0x27 ;registro para controlar paridad
PDel0 equ 0x28 ;registro utilizado para demoras
PDel1 equ 0x29 ;registro utilizado para demoras
PDel2 equ 0x2A ;registro utilizado para demoras
DATORS232 equ 0x2B ;Registro utilizado para almacenar dato enviado por la PC
TEMP_RDATO equ 0x2C ;registro para cargar el registro RDATO temporalmente
;===============================
; Declaracion de bits
;===============================
CLOCK equ 0 ; Clock siempre será RB0.-
ATDATA equ 1 ; Bits definido como Data del Teclado.
; FLAGS--> [KBHIT, ACK, RECEPCION, KBHIT_AT, PARIDAD, DATO, START]
START equ 0 ;si es 1 indica que se produjo el bit start
DATO equ 1 ;si es 1 cargamos los 8 bits de datos
PARIDAD equ 2 ;si es 1 recibimos paridad
KBHIT_AT equ 3 ;si es 1 se genero el stop
RECEPCION equ 4 ;si es 0 se recibe dato desde teclado
ACK equ 5 ;si es 1 se esta en espera del bit ack
KBHIT equ 6 ;si es 1 llego dato de Usart.-
;--------------------------------------------------------
;===============================
; INICIO
;===============================
org 0x00
goto inicio
;**********************************************
org 0x04
goto interrupciones
;===============================
; Interrupciones
;===============================
interrupciones
banksel STATUS
movwf W_TEMP ;Guardamos temporalmente W
swapf W_TEMP,1
movf STATUS,w ;Guardamos temporalmente STATUS
movwf STATUS_TEMP
btfsc INTCON,INTF ;Interrupcion por RB0
goto interrupcion_rb0
btfsc PIR1,RCIF ;Interrupcion USART
goto interrupcion_rx
;**********************************************
salida_interrupcion
bcf INTCON,INTF ;borra banderas
bcf PIR1,RCIF
bsf INTCON,GIE ;activa interrupcion global
movf STATUS_TEMP,w
movwf STATUS
swapf W_TEMP,w
retfie
;**********************************************
;Interrupcion por RB0
;**********************************************
interrupcion_rb0
bcf INTCON,GIE ; Desactiva interrupciones.-
btfsc FLAGS,RECEPCION ;determina si es transmision o recepcion
goto transmision
;***********************************************
;**** RECEPCION DESDE EL TECLADO **************
;***********************************************
; determina cual de los 11 bit a recibir
btfss FLAGS,START
goto espera_start
btfss FLAGS,DATO
goto cargar_datos
btfss FLAGS,PARIDAD
goto espera_paridad
goto espera_stop
;***********************************************
espera_start
btfsc PORTB,ATDATA ; Testeamos Data del Teclado
goto salida_interrupcion ; No se genero Start
bsf FLAGS,START ; se genero el bit start
goto salida_interrupcion ;salimos para esperar Dato
;***********************************************
cargar_datos
btfss PORTB,ATDATA ;Testeamos Data
bcf RDATO,7 ; Cargamos un cero en Dato recibido desde Teclado.-
btfsc PORTB,ATDATA
bsf RDATO,7 ; Cargamos un uno en Dato recibido dede Teclado
conteo
incf CONTADOR,1 ;
movlw d'8'
subwf CONTADOR,0
btfsc STATUS,Z ;Determinamos si se recibio por completo el Dato
goto salida_data ;Si
rrf RDATO,1 ; No, rotamos y esperamos demás bit's
goto salida_interrupcion ;Salimos para esperar proximo bit
salida_data
clrf CONTADOR ;ya se cargaron los 8 bits
bsf FLAGS,DATO
goto salida_interrupcion ;salimos para espera bit de paridad
;***********************************************
espera_paridad
btfss PORTB,ATDATA ; Detectamos paridad del Dato enviado
bcf RPARIDAD,0 ;
btfsc PORTB,ATDATA
bsf RPARIDAD,0
bsf FLAGS,PARIDAD ;Indicamos que se recibio Paridad
goto salida_interrupcion ;Salimos para esperar Stop
;***********************************************
espera_stop
bsf FLAGS,KBHIT_AT ;Se recibio por completo el Dato--> Star, Dato, Paridad y Stop.-
goto salida_interrupcion
;***********************************************
;***** TRANSMISION AL TECLADO *******
;***********************************************
;______________________________________________________________
;¨¨|___|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨|_|¨¨¨¨¨¨ teclado.- |
;¨¨¨¨¨|____|¨¨¨¨|¨¨¨¨¨|¨¨¨¨|¨¨¨¨¨|¨¨¨¨|¨¨¨¨|¨¨¨¨¨|¨¨¨¨|¨¨¨¨¨|¨¨¨¨|___|¨¨¨¨¨¨ micro.- |
; start 0 1 2 3 4 5 6 7 P s ack |
;______________________________________________________________ |
transmision
;En nivel del bit a enviar debe estar estable cuando el reloj esta a nivel alto.-
;El bits se carga al generarse el flanco descendente del clock.-
;transmision de dato
bcf INTCON,GIE ; Desactiva interrupciones.-
movfw CONTADOR ;Contador controla que bit enviar al Teclado.-
sublw d'7' ;w = 7 - CONTADOR
btfss STATUS,C
goto envio_paridad ;Se enviaron los 8 bit's del Dato, Pasamos a paridad.-
btfss RDATO,0 ;testeamos que enviar...
bcf PORTB,ATDATA ;Reseteamos DATA del Teclado.-
btfsc RDATO,0
bsf PORTB,ATDATA ;Setemoas DATA del Teclado.-
rrf RDATO,f ;Rotamos Data a enviar para el proximo bit a enviar.-
goto incf_contador ;
;**********************************************
;transmision de paridad
envio_paridad
movfw CONTADOR ;Contador controla que bit enviar al Teclado.-
sublw d'8'
btfss STATUS,C
goto envio_stop ;Ya se envio Paridad, enviamos Stop.-
btfss RPARIDAD,0 ;enviamos paridad segun como se halla determinado anteriormente.-
bcf PORTB,ATDATA ;Reseteamos Data, bits paridad = 0.-
btfsc RPARIDAD,0
bsf PORTB,ATDATA ;Seteamos Data, bit paridad =1.-
goto incf_contador
;**********************************************
;transmision de stop
envio_stop
movfw CONTADOR ;Contador controla que bit enviar al Teclado.-
sublw d'9'
btfss STATUS,C
goto espera_bit_ack ;Ya se envio Stop, esperamos ack.-
banksel TRISB ;Enviamos Stop, colocamos a nivel alto Data.-
bsf TRISB,ATDATA ; Liberamos DATA del Teclado.-
bcf OPTION_REG,7 ;habilita pull-up portb
banksel PORTB
goto incf_contador
;**********************************************
;espera de ack
espera_bit_ack
movfw CONTADOR ;Contador controla que bit enviar al Teclado.-
sublw d'11'
btfss STATUS,C
goto incf_contador ; Se recibe Ack, lo ignoramos.-
clrf CONTADOR
bcf FLAGS,RECEPCION ; Indicamos que ya se ha enviado Dato al Teclado.-
goto salida_interrupcion
;**********************************************
incf_contador
incf CONTADOR,f ; Incrementa Contador, el cual controla el bit a enviar.-
goto salida_interrupcion ; Salimos para esperar proximo clock.-
;***********************************************
; ***** Se recibe Dato por Usart ***************
;***********************************************
interrupcion_rx
bcf INTCON,GIE ; Desactiva interrupciones.-
btfss PIR1,RCIF ;se espera que cargue dato
goto $-1
movf RCREG,w ;Copiamos dato recibido a DATORS232
movwf DATORS232
bsf FLAGS,KBHIT ; Indicamos que ha llegado un dato.-
goto salida_interrupcion
;***********************************************
;=========================================
; PRINCIPAL
;=========================================
inicio
; configuracion de puertos
banksel TRISB
movlw b'00000011' ; RB0 --> Clck, RB1 --> DATA
movwf TRISB
movlw b'10000000' ;configura RS232
movwf TRISC
bcf OPTION_REG,7 ; habilitamos pull_ups al puerto B, Porque el teclado tiene sus pines a colector abierto.-
bcf OPTION_REG,INTEDG ;interrupción RB0 por flanco descendente
;**********************************************
; CONFIGURACION PUERTO SERIE
movlw 0x04
movwf TXSTA ;configura modo asincrono, baud rate de alta velocidad
movlw 0x81 ;configura velocidad a 9600 baudios para 20 MHz.-
movwf SPBRG
call demora_150ms
call demora_150ms
bsf INTCON,GIE ;activar habilitador general de interrupciones.
bsf INTCON,PEIE ;habilitacion de interrupciones por perifericos
bsf INTCON,INTE ;activar interrupción por RB0.
bsf PIE1,RCIE ;habilita interrupcion de puerto serie para recepcion
; activar recepcion transmision
banksel RCSTA
bsf RCSTA,SPEN ;habilitacion puerto serie
bsf RCSTA,CREN ;habilita recepcion
banksel TXSTA
bsf TXSTA,TXEN ; habilita transmision
banksel PORTB
;Reseteamos Bytes de Control.-
clrf RPARIDAD
clrf CONTADOR
clrf FLAGS
;**********************************************
;//////////////////////////////////////////////
espera_dato
btfsc FLAGS,KBHIT_AT ; Testeamos si ha llegado Dato desde el Teclado.-
goto envia_a_PC ; Si, eviamos dato a PC
btfsc FLAGS,KBHIT ; No, testeamos si llego dato desde PC.-
goto comunicacion_con_teclado ; si, nos comunicamos con el teclado.-
goto espera_dato ;bucle infinito
;***********************************************
;Enviamos Dato recibido por el Teclado a la PC por Usart.-
envia_a_PC
clrf FLAGS ; Borramos controles para recibir de nuevo
banksel TXSTA ; Banco 1
btfss TXSTA,TRMT ; chequea si esta listo
goto $-1 ; Esperamos a que se desocupe.-
banksel TXREG ; Banco 0
movfw RDATO ; enviamos Dato del teclado a PC
movwf TXREG ; envia caracter
goto espera_dato
;************************************************
comunicacion_con_teclado
; Enviamos peticion de control de leds--> 0xED y luego el dato de control de leds enviado
; por la PC ([0,0,0,0,0, Caps, Num, Scroll])
clrf FLAGS ; Borramos controles para recibir de nuevo
movlw 0xED ; Comando de control de leds
movwf RDATO ; Dato a enviar al Teclado
call determino_paridad ; se determina paridad del dato a enviar.-
call config_envia_dato ; se configura para enviar y se trasmite el dato.-
btfss FLAGS,KBHIT_AT ; espero a que se reciba ACK desde el teclado.-
goto $-1
clrf FLAGS ; Borramos controles para recibir de nuevo
movlw 0xFA ;verificamos si es un ACK
subwf RDATO,w
btfss STATUS,Z
goto espera_dato ;No se recibio ACK,
movfw DATORS232 ;enviamos a teclado el byte recibido por Usart
movwf RDATO
call determino_paridad
call config_envia_dato ; se configura para enviar y se trasmite el dato.-
btfss FLAGS,KBHIT_AT ; espero a que se reciba ACK desde el teclado.-
goto $-1
clrf FLAGS ; Borramos controles para recibir de nuevo
goto espera_dato
;===============================
; Subrutinas
;===============================
;****************************************************
;Rutinas para transmision de Micro a teclado
;****************************************************
;determina paridad del registro RDATO para envio al teclado
; Si el nro de 1 de RDATO es par, RPARIDAD = 1.-
determino_paridad
movfw RDATO
movwf TEMP_RDATO
movlw 0x08
movwf CONTADOR
clrf CONT_BIT
bucle_0
btfsc TEMP_RDATO,0
incf CONT_BIT
rrf TEMP_RDATO
decfsz CONTADOR
goto bucle_0
bcf RPARIDAD,0
btfss CONT_BIT,0
bsf RPARIDAD,0
return
;***********************************************
;configura para establecer comunicacion con el teclado, envia dato y espera bit ack
config_envia_dato
clrf CONTADOR
bsf FLAGS,RECEPCION ;es para transmision.
bcf INTCON,INTE ;desactivar interrupción por rb0.
banksel TRISB
clrf TRISB ;configuro como salida
banksel PORTB
bcf PORTB,CLOCK ;clock=0, data=1
bsf PORTB,ATDATA
call demora_35us
bcf PORTB,CLOCK ;clock=0, data=0
bcf PORTB,ATDATA
call demora_125us
banksel TRISB
bsf TRISB,CLOCK ;configura RB0 como entrada
bcf OPTION_REG,7 ; habilitamos pull_up al puerto B
banksel PORTB
bcf PORTB,ATDATA
bcf INTCON,INTF
bsf INTCON,INTE ;activar interrupción por rb0.
btfsc FLAGS,RECEPCION ;verifica si se ha enviado el dato
goto $-1 ; no
clrf FLAGS ; Borramos controles para recibir de nuevo
return
;***********************************************
; Demoras
;***********************************************
demora_35us
movlw .7
movwf PDel0
PLoop0
nop
decfsz PDel0, 1
goto PLoop0
PDelL1
goto PDelL2
PDelL2
return
;***********************************************
demora_125us
movlw .30
movwf PDel0
PLoop0_125
nop
decfsz PDel0, 1
goto PLoop0_125
return
;***********************************************
demora_150ms
movlw .117
movwf PDel0
PLoop0_
movlw .213
movwf PDel1
PLoop1_
movlw .1
movwf PDel2
PLoop2_
nop
decfsz PDel2, 1
goto PLoop2_
decfsz PDel1, 1
goto PLoop1_
decfsz PDel0, 1
goto PLoop0_
PDelL1_
goto PDelL2_
PDelL2_
nop
return
;************************************************
end