Código Ensamblador PIC16F84: Comunicación Serie UART, Control de Paridad y Antirrebote con Interrupciones
Programación en ensamblador del PIC16F84: interrupciones, comunicación serie y control de paridad
A continuación se presenta el código en ensamblador de un microcontrolador PIC16F84 que combina interrupciones, comunicación serie asíncrona (USART), control de paridad y eliminación de rebotes en pulsadores.
Definición de variables
Las variables se asignan a posiciones de la memoria RAM mediante la directiva EQU. Algunas variables, como DATO3RX a DATO11RX o R1, O1 y N1, no tienen dirección explícita, por lo que deberían revisarse.
N EQU 0X20
CONTROL EQU 0X21
;BIT 7 ESTÁ A 0: PARIDAD PAR. A 1: PARIDAD IMPAR
;BIT 6 SE PONE A 1 CUANDO SE RECIBE UNA 'w' Y ESTÁ DENTRO DEL RANGO
DATO EQU 0X22
UNOS EQU 0X23
ACTUAL EQU 0X24
PREVIO EQU 0X25
XOR EQU 0X26
DATO1RX EQU 0X27
DATO2RX EQU 0X28
DATO3RX EQU
DATO4RX EQU
DATO5RX EQU
DATO6RX EQU
DATO7RX EQU
DATO8RX EQU
DATO9RX EQU
DATO10RX EQU
DATO11RX EQU
DATO12RX EQU 0X32
E1 EQU 0X33
R1
R2 EQU 0X35
D1 EQU 0X36
O1
N1
E2 EQU 0X39
PUNTERORX EQU 0X3A
CONTADOR EQU 0X3B
NUMDATOSTX EQU 0X3C
N_AUX EQU 0X3DVector de reset e interrupciones
ORG 0
GOTO INICIO
ORG 4
GOTO ISR
ORG 5Configuración inicial (INICIO)
Configuración de puertos
Se seleccionan las páginas de memoria mediante RP0 y se configuran los puertos como entradas o salidas usando el registro TRIS:
INICIO
BSF STATUS,RP0
BSF TRISA,0
BSF TRISA,1
BSF TRISA,2
BSF TRISA,3
BSF TRISA,4
BSF TRISA,5
MOVLW 0X06
MOVWF ADCON1
BCF TRISB,1 ; RB1 como salida
BSF TRISB,0
BSF TRISB,7
BSF TRISB,6
BSF TRISC,7 ; RX como entrada
BCF TRISC,6 ; TX como salidaHabilitación de interrupciones
BSF INTCON,GIE
BSF INTCON,PEIE
BSF INTCON,T0IE
BSF INTCON,RBIE
BSF INTCON,INTE
BCF PIE1,TXIE
BSF PIE1,RCIEConfiguración del TMR0 y del preescalador
BCF OPTION_REG,T0CS
BSF OPTION_REG,PSA
BCF OPTION_REG,PS2
BCF OPTION_REG,PS1
BCF OPTION_REG,PS0
BCF OPTION_REG,INTEDGConfiguración de la USART
Se establece la velocidad de transmisión mediante el registro SPBRG y el bit BRGH (alta velocidad):
BSF TXSTA,BRGH
BCF TXSTA,SYNC
BSF TXSTA,TXEN
MOVLW .12
MOVWF SPBRG
BCF STATUS,RP0
BSF RCSTA,SPEN
BSF RCSTA,CRENInicialización de variables
MOVLW .106
MOVWF TMR0
MOVLW .100
MOVWF N
MOVWF N_AUX
MOVLW 0X28
MOVWF PUNTERORX
MAIN
GOTO MAINRutina de servicio de interrupción (ISR)
La ISR identifica la fuente de la interrupción mediante la consulta de los flags correspondientes y salta a la rutina adecuada:
ISR
BTFSC INTCON,T0IF
GOTO TEMPORIZADOR
BTFSC INTCON,RBIF
GOTO BOTONX
BTFSC INTCON,INTF
GOTO BOTON0
BTFSC PIR1,RCIF
GOTO RECEPCION
BTFSC PIR1,TXIF
GOTO TRANSMISION
RETFIETransmisión serie (TRANSMISION)
Envía sucesivamente los bytes almacenados a partir de la dirección apuntada por FSR:
TRANSMISION
INCF FSR,1
MOVFW INDF
MOVWF TXREG
DECFSZ NUMDATOSTX,1
RETFIE
BSF STATUS,RP0
BCF PIR1,TXIE
BCF STATUS,RP0
MOVFW PUNTERORX
MOVWF FSR
RETFIEPulsador en RB0 (BOTON0): cambio de paridad
Cada pulsación alterna el modo de paridad activo, almacenado en el bit 7 de la variable CONTROL:
BOTON0
BCF INTCON,INTF
BTFSC CONTROL,7
GOTO CAMBIAMOS_A_PAR
GOTO CAMBIAMOS_A_IMPAR
CAMBIAMOS_A_IMPAR
BSF CONTROL,7
RETFIE
CAMBIAMOS_A_PAR
BCF CONTROL,7
RETFIEPulsadores en RB6 y RB7 (BOTONX): ajuste del valor N
Al detectarse un cambio en PORTB, se compara el estado actual con el anterior para determinar qué pulsador ha cambiado. Se implementa un antirrebote sencillo mediante la verificación del estado del pin tras el cambio.
BOTONX
MOVFW PORTB
MOVWF ACTUAL
XORWF PREVIO,0
MOVWF XOR
BTFSC XOR,7
GOTO BOTON7
BTFSC XOR,6
GOTO BOTON6
RETFIE
BOTON6
MOVFW ACTUAL
MOVWF PREVIO
BCF INTCON,RBIF
BTFSS PORTB,6
RETFIE
MOVFW N
XORLW .1
BTFSS STATUS,Z
DECF N,1
MOVFW N
MOVWF N_AUX
RETFIE
BOTON7
MOVFW ACTUAL
MOVWF PREVIO
BCF INTCON,RBIF
BTFSS PORTB,7
RETFIE
MOVFW N
XORLW .255
BTFSS STATUS,Z
INCF N,1
MOVFW N
MOVWF N_AUX
RETFIETemporizador (TEMPORIZADOR)
Cada desbordamiento del TMR0 genera una interrupción. Cuando el contador N_AUX llega a cero, se realiza la lectura del puerto PORTA y el cálculo de la paridad:
TEMPORIZADOR
BCF INTCON,T0IF
MOVLW .106
MOVWF TMR0
DECFSZ N_AUX,1
RETFIE
; YA HE CONTADO N x 150 US
MOVFW N
MOVWF N_AUX
MOVFW PORTA
ANDLW B'00111111'
MOVWF DATO
MOVLW .6
MOVWF CONTADOR
CLRF UNOS
BUCLE
BTFSS DATO,0
GOTO TENGO_UN_CERO
GOTO TENGO_UN_UNO
TENGO_UN_CERO
RRF DATO,1
DECFSZ CONTADOR,1
GOTO BUCLE
GOTO SEGUIMOS
TENGO_UN_UNO
RRF DATO,1
INCF UNOS,1
DECFSZ CONTADOR,1
GOTO BUCLE
GOTO SEGUIMOSEvaluación de la paridad
Tras contar los unos en los 6 bits, se determina si el número es par o impar y se compara con el modo configurado en CONTROL,7. El resultado se refleja en RB1:
SEGUIMOS
BTFSS UNOS,0
GOTO TENEMOS_PARIDAD_PAR
GOTO TENEMOS_PARIDAD_IMPAR
TENEMOS_PARIDAD_PAR
BTFSC CONTROL,7
GOTO ME_PIDEN_IMPAR
GOTO ME_PIDEN_PAR
ME_PIDEN_IMPAR
BSF PORTB,RB1
RETFIE
ME_PIDEN_PAR
BCF PORTB,RB1
RETFIE
TENEMOS_PARIDAD_IMPAR
BTFSS CONTROL,7
GOTO ME_PIDEN_IMPAR
GOTO ME_PIDEN_PARRecepción serie (RECEPCION)
La recepción utiliza la variable CONTADOR para distinguir entre el primer y el segundo byte recibido. Cuando se recibe la letra 'w' seguida de un valor dentro del rango 0x50 - 0x70, se activa el bit 6 de CONTROL y se inicia la recepción de los bytes restantes:
RECEPCION
; CONTADOR
; 00 -> RX DATO 1
; 01 -> RX DATO 2
; BIT 6 SE PONE A 1 CUANDO SE RECIBE UNA 'w' Y ESTÁ DENTRO DEL RANGO
BTFSC CONTROL,6
GOTO SEGUIMOS_RECIBIENDO
MOVFW CONTADOR
BTFSC STATUS,Z
GOTO RX_DATO1
GOTO RX_DATO2
RX_DATO1
INCF CONTADOR,1
MOVFW RCREG
MOVWF DATO1RX
RETFIE
RX_DATO2
CLRF CONTADOR
MOVFW RCREG
MOVWF DATO2RX
; YA EMPIEZO A COMPROBAR
MOVFW DATO1RX
XORLW 'w'
BTFSS STATUS,Z
GOTO TX_ERR
MOVFW DATO2RX
SUBLW 0X50
BTFSC STATUS,C
GOTO TX_ERR
MOVFW DATO2RX
SUBLW 0X70
BTFSS STATUS,C
GOTO TX_ERR
BSF CONTROL,6
RETFIE
SEGUIMOS_RECIBIENDO
INCF FSR,1
MOVFW RCREG
MOVWF INDF
MOVFW FSR
XORLW 0X32
BTFSS STATUS,Z
RETFIE
GOTO TX_DONE
BCF CONTROL,6
RETFIEGestión de respuestas (TX_ERR y TX_DONE)
Según el resultado de la verificación, se prepara el envío de una respuesta de error (3 bytes) o de confirmación (4 bytes) activando la interrupción de transmisión:
TX_ERR
MOVLW 0X32
MOVWF FSR
MOVLW .3
MOVWF NUMDATOSTX
BSF STATUS,RP0
BSF PIE1,TXIE
BCF STATUS,RP0
RETFIE
TX_DONE
MOVLW 0X35
MOVWF FSR
MOVLW .4
MOVWF NUMDATOSTX
BSF STATUS,RP0
BSF PIE1,TXIE
BCF STATUS,RP0
RETFIE
ENDObservaciones sobre el código
- Las variables DATO3RX a DATO11RX, así como R1, O1 y N1, carecen de dirección asignada y deben completarse antes de compilar.
- Las etiquetas TRANSMISION y RECEPCION utilizan el registro FSR como puntero indirecto sobre INDF, lo que requiere que el área de datos esté correctamente inicializada.
- La instrucción ANDLW B'00111111',0 de la versión original contenía un argumento sobrante que se ha eliminado, ya que ANDLW solo admite un operando.