Aplicación de pantalla tactil

Anuncio
M-Turret
(Diseño de Sistemas basados en Microprocesadores)
Christopher Orihuela Sosa
David M. Godoy Delgado
José Luis Santana Acosta
Miércoles, 25 de Junio de 2008
Introducción
El presente documento corresponde a la memoria del trabajo realizado por Christopher
Orihuela Sosa, David M. Godoy Delgado y José Luis Santana Acosta, alumnos de la asignatura
Diseño de Sistemas Basados en Microprocesadores, durante el año académico 2007/2008.
El objetivo del proyecto (bautizado con el nombre de M-Turret) es la construcción de un
artefacto mecánico capaz de apuntar en determinadas direcciones, en función de los datos
que, a través de una pantalla táctil, el usuario le facilite al artefacto. Una vez que el objeto se
encuentre apuntando en la dirección correcta, deberá detenerse. Para detectar que el
artefacto ha llegado a la posición correcta, los motores que mueven el puntero están
conectados a sendos potenciómetros, por lo que podemos adivinar la posición del puntero
digitalizando las entradas de dichos potenciómetros. Cuando el usuario pulsa en alguna zona
de la pantalla, la M-Turret utilizará sus motores para posicionarse de manera que apunte en la
dirección del punto en que ha pulsado el usuario. El movimiento del puntero es diferencial, se
moverá más rápido cuanto más lejos esté el puntero de su destino.
Podemos así dividir el proyecto en tres partes bien diferenciadas, a saber:



Control y lectura de la pantalla táctil
Digitalización de las entradas de los potenciómetros
Control de los motores
Las siguientes secciones explican detalladamente estos tres módulos del proyecto. A grandes
rasgos, el módulo de pantalla táctil se encarga de configurar dicho dispositivo y leer las
pulsaciones del usuario, el módulo de digitalización realiza la conversión analógico/digital de
las entradas de los potenciómetros y el módulo de motores controla el movimiento y velocidad
de los mismos.
Control de la pantalla táctil
El control de la pantalla táctil se realiza por medio de RS232. Para ello empleamos gran parte
del código de la práctica de Humberto Luis Barriento González y Mario Castellano Díaz,
disponible en http://serdis.dis.ulpgc.es/~itis-dsm/_private/2005-2006/pic-tactil.pdf.
La conexión física al PIC se realizó en PORT.B0 que implementa RX y PORT.B2 que implementa
TX:
#DEFINE
#DEFINE
#DEFINE
#DEFINE
MIRX PORTB,0
MITX PORTB,2
CONF_MIRX TRISB,0
CONF_MITX TRISB,2
Utilizamos las siguientes variables para la transmisión RS232:
; VARIABLES
;
Inicio_Memoria
DATO
RET1
RET2
CONT8
SOH
EQU 0x0C
EQU (Inicio_Memoria+1) ;Dato a Transmitir o Recibido
RS232
EQU (Inicio_Memoria+2) ;para retardo de bit RS232
EQU (Inicio_Memoria+3) ;para retardo de bit RS232
EQU (Inicio_Memoria+4) ;Contador de bits en rutinas
MIRX y MITX
EQU (Inicio_Memoria+5) ;Registro para guardar el byte
y comprobar si es carita
Y las siguientes para los datos que nos llegan de la pantalla:
; Variables nuevas para recoger los datos del paquete de datos
;
Numero_Byte_Datos
EQU
(Inicio_Memoria+6) ;Un indice dentro del
paquete de datos
PTactil_X_MSB
EQU
(Inicio_Memoria+7) ;Most Significant Byte
de la X (10 bits)
PTactil_X_LSB
EQU
(Inicio_Memoria+8) ;Least Significant Byte
de la X (10 bits)
PTactil_Y_MSB
EQU
(Inicio_Memoria+9) ;Most Significant Byte
de la Y (10 bits)
PTactil_Y_LSB
EQU
(Inicio_Memoria+10) ;Least Significant
Byte de la Y (10 bits)
Nueva_Pulsacion
EQU
(Inicio_Memoria+11) ;Se pone a 1 si hay
pulsacion nueva de la
pantalla
Pantalla_Tactil_X
EQU
(Inicio_Memoria+12) ;Coordenada X de la
pantalla (en formato 8
bits)
Pantalla_Tactil_Y
EQU
(Inicio_Memoria+13) ;Coordenada Y de la
pantalla (en formato 8
bits)
STATUS_BAK
EQU
(Inicio_Memoria+14) ;Coordenada Y de la
pantalla (en formato 8
bits)
W_BAK
EQU
(Inicio_Memoria+15) ;Coordenada Y de la
pantalla (en formato 8
bits)
Configuración inicial de la pantalla
Tras configurar RX/TX correspondientemente para entrada y salida, procedemos a configurar
la pantalla en modo hexadecimal. En este modo, recibimos un paquete de datos de 9 bytes
para cada pulsación:
– 1 de cabecera.
– 3 de la X (solo se aprovechan los 4 últimos bits, salvo del primero que sólo son 2 bits)
– 1 byte de separación
– 3 de la Y (solo se aprovechan los 4 últimos bits, salvo del primero que sólo son 2 bits)
– 1 byte de terminación
En total esto nos da 10 bits para X y 10 para Y, aunque para simplificar los cálculos los
reducimos (más adelante en el código) a 8 bits. Los puertos A1 y A4 los utilizamos para indicar
la zona de la pulsación de pantalla, a modo de debug:
;configuración inicial de puertos PANTALLA
bcf CONF_LIBREA1; configurar el pin del led a salida (DEBUG)
bcf CONF_LIBREA4 ; configurar el pin del led a salida (DEBUG)
bcf CONF_MITX ;configurar TX a salida
bsf CONF_MIRX ;configurar RX a entrada
;configuración inicial de puertos PANTALLA
;Posiciones iniciales de los pines
BSF MITX
BSF MIRX
bcf LIBREA1 ;LED1
bcf LIBREA4 ;LED2
;Posiciones iniciales de los pines
La función FH envía el comando de configuración para modo hexadecimal por RS232 a la
pantalla:
;CONFIGURACION DEL CONTROLADOR DE LA PANTALLA EN FORMATO hexadecimal
call Espera_Larga
CALL FH ;COMANDO PARA ESTABLECER FORMATO HEXADECIMAL
call Espera_Larga
CALL FH ;REPETIMOS POR SI NO FUNCIONA LA PRIMERA VEZ
La recepción de los bytes de la pantalla se hará en la interrupción del pin de RX, cuando reciba
un start bit, así que lo configuramos:
;HABILITAMOS LAS INTERRUPCIONES para dar paso al programa principal
BSF INTCON,INT0IE ;HABILITA INTERRUPCIÓN INT0
Bcf INTCON, INT0IF ;borrar la flag de "ocurrido int0"
BSF INTCON,GIE ;HABILITA INTERRUPCIONES GLOBALMENTE
;Según el manual IPEN está a 0 por defecto (prioridades altas)
;e INT0 es siempre de prioridad alta
Recepción de bytes
Lo mostrado a continuación es el código de la interrupción. Tras comprobar el motivo de la
interrupción (en realidad no podría haber otro), guardamos registros y empezamos a recibir
bytes.
Para todos los bytes comprobamos el número de byte (número de secuencia en variable
Numero_Byte_Datos).
Para recibir cada byte llamamos a MIRXDATO y comprobamos que W sea TRUE, que indica
recepción correcta.
Tras el primer byte comprobamos que sea el de cabecera, y luego tras cada uno de los otros
bytes comprobamos que el start bit sea correcto, si no lo fuera iría a Error_de_transmisión que
inicializaría los contadores esperando otra pulsación. Si todo va bien, los bytes de las
coordenadas estarán en Ptactil_X_MSB, Ptactil_X_LSB, Ptactil_Y_MSB y Ptactil_Y_LSB (10 bits
cada uno).
;Código de la interrupción (sólo usamos INT0)
INTERRUPCION
BTFSS INTCON,INT0IF ;COMPROBACIÓN DE INTERRUPCION INT
RETFIE
;
movff
STATUS, STATUS_BAK ;guardamos status
movwf
W_BAK ;guardamos W
;
movf
Numero_Byte_Datos,W
btfss
STATUS, Z
goto
Siguiente_Byte_1
CALL
MIRXSOH ;Aquí llama para recibir SOH (cabecera)
XORLW
TRUE ;Esto es una comprobación para saber si el
procedimiento a ejecutado
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
goto
Salir_Interrupcion
Siguiente_Byte_1
movf
Numero_Byte_Datos,W
xorlw
1
btfss
STATUS, Z
goto
Siguiente_Byte_2
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
movf
DATO,W
andlw
0x0f
movwf
PTactil_X_MSB
goto
Salir_Interrupcion
Siguiente_Byte_2
movf
Numero_Byte_Datos,W
xorlw
2
btfss
STATUS, Z
goto
Siguiente_Byte_3
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
rlcf
DATO
rlcf
DATO
rlcf
DATO
rlcf
DATO
movf
DATO,W
andlw
0xf0
movwf
PTactil_X_LSB
goto
Salir_Interrupcion
Siguiente_Byte_3
movf
Numero_Byte_Datos,W
xorlw
3
btfss
STATUS, Z
goto
Siguiente_Byte_4
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
movf
DATO,W
andlw
0x0f
addwf
PTactil_X_LSB
goto
Salir_Interrupcion
Siguiente_Byte_4
movf
Numero_Byte_Datos,W
xorlw
4
btfss
STATUS, Z
goto
Siguiente_Byte_5
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
goto
Salir_Interrupcion
Siguiente_Byte_5
movf
Numero_Byte_Datos,W
xorlw
5
btfss
STATUS, Z
goto
Siguiente_Byte_6
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
movf
DATO,W
andlw
0x0f
movwf
PTactil_Y_MSB
goto
Salir_Interrupcion
Siguiente_Byte_6
movf
Numero_Byte_Datos,W
xorlw
6
btfss
STATUS, Z
goto
Siguiente_Byte_7
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
rlcf
DATO
rlcf
DATO
rlcf
DATO
rlcf
DATO
movf
DATO,W
andlw
0xf0
movwf
PTactil_Y_LSB
goto
Salir_Interrupcion
Siguiente_Byte_7
movf
Numero_Byte_Datos,W
xorlw
7
btfss
STATUS, Z
goto
Siguiente_Byte_8
CALL
MIRXDATO
XORLW
TRUE
btfss
STATUS, Z
goto
Error_Transmision
incf
Numero_Byte_Datos
movf
DATO,W
andlw
0x0f
addwf
PTactil_Y_LSB
goto
Salir_Interrupcion
Siguiente_Byte_8
;
bsf
Nueva_Pulsacion, 0 ; marcamos la llegada de
nuevos datos
;
; el resto de bytes no nos importa
Finalmente convertimos las variables de 10 bits a variables de 8 para manejarlas mejor
(Pantalla_Tactil_X y Pantalla_Tactil_Y). Luego indicamos la nueva pulsación en la variable
Nueva_Pulsacion. Tras ello, inicializamos contadores de bytes, restauramos W y STATUS y
salimos:
;ahora convertimos el formato de 10 bits en 8 bits (los más
significativos)
movff
PTactil_X_LSB, Pantalla_Tactil_X
rrncf
Pantalla_Tactil_X
rrncf
Pantalla_Tactil_X
bcf
Pantalla_Tactil_X,7
bcf
Pantalla_Tactil_X,6
btfsc
PTactil_X_MSB,1
bsf
Pantalla_Tactil_X,7
btfsc
PTactil_X_MSB,0
bsf
Pantalla_Tactil_X,6
;
movff
PTactil_Y_LSB, Pantalla_Tactil_Y
rrncf
Pantalla_Tactil_Y
rrncf
Pantalla_Tactil_Y
bcf
Pantalla_Tactil_Y,7
bcf
Pantalla_Tactil_Y,6
btfsc
PTactil_Y_MSB,1
bsf
Pantalla_Tactil_Y,7
btfsc
PTactil_Y_MSB,0
bsf
Pantalla_Tactil_Y,6
;termina la interrupcion normalmente
;
Error_Transmision
clrf
Numero_Byte_Datos ; para que lea otro paquete
Salir_Interrupcion
movf
W_BAK,W ;restauramos W
movff
STATUS_BAK,STATUS ;restauramos status
;
BCF
INTCON,INT0IF ;BORRA BANDERA INT
RETFIE
Rutina de Adquisición de datos Analógicos
La adquisición de datos de las entradas analógicas consta de dos partes, una primera etapa de
configuración del puerto y una segunda etapa donde activamos la susodicha conversión, pero
la mejor forma de comprender cómo realizar la conversión es siguiendo el código.
En una primera configuración nos centramos en el registro ADCON1 (A/D CONTROL REGISTER
1), que es el empleado para configurar si las entradas son digitales o analógicas, colocando un
0 en el bit correspondiente a la entrada ANx la configuraremos como analógica y en cambio
con un 1 la configuraremos como Digital.
movlw b'01111110' ;Seleccionamos la entrada AN0 como analógica
movwf ADCON1
El siguiente punto a configurar es el Registro ADCON2, que es el encargado de configurar cómo
se llevará a cabo la conversión, formato y tiempo de adquisición. El Bit 7 del registro nos
permite seleccionar el formato de la conversión, esto es, si queremos que la lectura esté
justificada a la Izquierda (0) o a la Derecha (1). Los Bits del 5 al 3 sirven para seleccionar el
tiempo de adquisición que queremos que emplee la conversión según la tabla suministrada
por el fabricante. Y por último los Bits del 2 al 0 se emplean para configurar los ciclos de reloj
que empleará la conversión.
movlw b'00000101' ;Justificación a la Izquierda, 0TAD , Fosc/16
movwf ADCON2
El siguiente registro de configuración es el ADCON0, que es el empleado para realizar el setup
del conversor Analógico-Digital, seleccionando los voltajes de referencia, el canal por el que se
realizará la conversión y la activación/aviso de la conversión. De esta forma los Bits 7 y 6 son
empleados para seleccionar las referencias de voltaje siguiendo la tabla que facilita el
fabricante, 11 para poner ambas referencias externamente. Los Bits 4 a 2 son los empleados
para seleccionar el canal por el que se realizará la conversión, según la tabla especifica, 000
para seleccionar el canal AN0. El Bit 1 hace referencia al GO/DONE que es el estado de la
conversión, de esta forma colocaremos a 1 este bit cuando queramos realizar la conversión y
se pondrá a 0 cuando la conversión esté terminada. El Bit 0 se refiere a ADON que se utiliza
para activar el modulo de conversión, 1 activo y 0 desactivado. Una vez activado el modulo de
conversión hay que realizar una pequeña espera, ya que un condensador interno debe
descargarse para que se pueda llevar a cabo la conversión correctamente.
movlw b'11000000' ;enable A/D, AN0, mod enable
movwf ADCON0
bsf
ADCON0,0 ; ACTIVAMOS EL CONVERSOR
;ESPERAMOS EL TIEMPO NECESARIO PARA LA ADQUISICION
call delayan
Para ahorrarnos problemas durante la conversión desactivamos las interrupciones. Una vez
listos para realizar la conversión activamos el bit GO del ADCON0 y esperamos a que se
desactive indicando que la conversión ha terminado.
BCF
bsf
INTCON,GIE ;Desactivamos las Interrupciones
ADCON0,GO ;Iniciamos la Conversión
adloop
btfsc ADCON0,DONE ;Esperamos a que se complete la Conversión
goto adloop
Una vez terminada la conversión sólo nos queda reactivar las interrupciones y mover el dato
desde los registros especiales ADRESH y ADRESL a nuestra variable. En este caso sólo
empleamos el H ya que hemos seleccionado la justificación a la Izquierda y despreciamos los 2
bits menos significativos de la conversión, ya que da valores que varían en estos bits para el
mismo voltaje, y desactivamos el módulo Analógico-Digital.
BSF INTCON,GIE ;Reactivamos las Interrupciones
movff ADRESH,ANDATA1 ;Movemos el resultado de la conversión
bcf
ADCON0,0 ;Desactivamos el Modulo AD
En caso de querer realizar capturas de varios puertos es recomendable realizar una espera
entre configuración y configuración, y seguir los pasos uno a uno, ya que tratamos de realizar
una configuración conjunta, la conversión fallaba y arrojaba datos erróneos.
Módulo motriz
Para controlar el uso de los motores utilizamos un chip L293D, que consta de 4 drivers con
señal de habilitación por parejas. A diferencia del L293, el L293D lleva integrados los diodos
necesarios para proteger los motores, por lo que podemos conectar tanto el PIC como los
motores al L293D “a pelo”. A continuación se muestra un esquema de la organización interna
del L293D.
Antes de mostrar las conexiones PIC-L293D-Motores, vamos a echar un vistazo al código para
ver qué patillas vamos a utilizar. El movimiento de los motores se divide en “pasos lógicos”, es
decir, cada cierto tiempo (concretamente después de digitalizar las entradas de los
potenciómetros) se ejecuta un paso del motor. Si el paso es 0, el motor se detiene. Si el paso
es uno, el motor gira. Un paso termina cuando se ejecuta el paso siguiente. La duración de
cada paso es muy pequeña, de manera que la estrategia que utilizamos para controlar la
velocidad es modificar la frecuencia de pasos con valor 1.
Veamos las patillas que usaremos. El siguiente trozo de código muestra los defines de las
patillas utilizadas, los utilizaremos posteriormente en las funciones. Nótese que para cada
motor tenemos declarados 2 defines para las direcciones del motor, 1 define para la
habilitación de movimiento y 3 defines para configurar las patillas de ese motor.
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
#DEFINE
ENABLEH PORTA,7
CONF_ENABLEH TRISA,7
ENABLEV PORTB,3
CONF_ENABLEV TRISB,3
IZQUIERDA PORTB,4
CONF_IZQUIERDA TRISB,4
DERECHA PORTB,5
CONF_DERECHA TRISB,5
ARRIBA PORTB,6
CONF_ARRIBA TRISB,6
ABAJO PORTB,7
CONF_ABAJO TRISB,7
A continuación se muestra la inicialización de los bytes que utilizaremos para controlar la
velocidad de los motores. Cada paso del motor invocará una de las 8 funciones de movimiento,
y cada una de ellas tiene su propio byte. Fijarse como los bytes FAST* se inicializan a 0xFF
(todo unos, todos los pasos son dados) y los SLOW* a 0xEE (el 75% de los pasos son dados).
FASTRIGHT
FASTLEFT
FASTUP
FASTDOWN
SLOWRIGHT
SLOWLEFT
SLOWUP
SLOWDOWN
movlw
movwf
movwf
movwf
movwf
movwf
movlw
movwf
movwf
movwf
movwf
EQU
EQU
EQU
EQU
EQU
EQU
EQU
EQU
(Inicio_Memoria+22)
(Inicio_Memoria+23)
(Inicio_Memoria+24)
(Inicio_Memoria+25)
(Inicio_Memoria+26)
(Inicio_Memoria+27)
(Inicio_Memoria+28)
(Inicio_Memoria+29)
(…)
0xFF
HORIZONTAL
FASTRIGHT
FASTLEFT
FASTUP
FASTDOWN
0xEE
SLOWRIGHT
SLOWLEFT
SLOWUP
SLOWDOWN
Para terminar con las inicializaciones, configuramos las patillas que vamos a utilizar en modo
salida.
bcf
bcf
bcf
bcf
bcf
bcf
CONF_ENABLEH
CONF_ENABLEV
CONF_IZQUIERDA
CONF_DERECHA
CONF_ARRIBA
CONF_ABAJO
Veamos ahora las funciones desarrolladas. Existe un total de 12 funciones relacionadas con el
control de los motores, 4 de ellas para (des)habilitación y 8 para movimiento. Las funciones de
(des)habilitación de motores simplemente ponen a 1 o a 0 ENABLEH o ENABLEV, que como
veremos en breve son las patillas que van conectadas a las entradas ENABLE del L293D. En
cuanto a las funciones de movimiento, todas tienen la misma estructura: primero se ponen a 0
las salidas que controlan el movimiento en el eje del motor, luego se testea el bit más
significativo del byte asociado a la función (en caso de ser 1 se activa una de las salidas antes
desactivadas) para acabar rotando el registro asociado a través del CARRY.
inith
bsf
ENABLEH
return
initv
bsf
ENABLEV
return
stoph
bcf
ENABLEH
return
stopv
bcf
ENABLEV
return
fleft
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
IZQUIERDA
DERECHA
FASTRIGHT, 7
IZQUIERDA
STATUS,C
FASTRIGHT, 1
STATUS,C
FASTRIGHT, 0
fup
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
ARRIBA
ABAJO
FASTUP, 7
ARRIBA
STATUS,C
FASTUP, 1
STATUS,C
FASTUP, 0
fright
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
IZQUIERDA
DERECHA
FASTLEFT, 7
DERECHA
STATUS,C
FASTLEFT, 1
STATUS,C
FASTLEFT, 0
fdown
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
ARRIBA
ABAJO
FASTDOWN, 7
ABAJO
STATUS,C
FASTDOWN, 1
STATUS,C
FASTDOWN, 0
sleft
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
IZQUIERDA
DERECHA
SLOWRIGHT, 7
IZQUIERDA
STATUS,C
SLOWRIGHT, 1
STATUS,C
SLOWRIGHT, 0
sup
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
ARRIBA
ABAJO
SLOWUP, 7
ARRIBA
STATUS,C
SLOWUP, 1
STATUS,C
SLOWUP, 0
sright
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
IZQUIERDA
DERECHA
SLOWLEFT, 7
DERECHA
STATUS,C
SLOWLEFT, 1
STATUS,C
SLOWLEFT, 0
sdown
bcf
bcf
btfsc
bsf
bcf
rlcf
btfsc
bsf
return
ARRIBA
ABAJO
SLOWDOWN, 7
ABAJO
STATUS,C
SLOWDOWN, 1
STATUS,C
SLOWDOWN, 0
Para concluir la explicación sobre el funcionamiento de los motores, se muestra a continuación
el esquema de conexión PIC-L293D-Motores.
Anexo I: Código
list p=18f1320
include <P18F1320.INC>
; MACROS Y DEFINICION DE BITS
#DEFINE BANK0 BCF STATUS,RP0
#DEFINE BANK1 BSF STATUS,RP0
;
TRUE EQU 1
FALSE EQU 0
CTRAN EQU 0XFE ; SOH NEGADO (ASCII)
;
#DEFINE MIRX PORTB,0 #DEFINE MITX PORTB,2
#DEFINE CONF_MIRX TRISB,0 #DEFINE CONF_MITX TRISB,2
#DEFINE CONF_MIAN0 TRISA,0
#DEFINE CONF_MIAN5 TRISB,1
#DEFINE
ENABLEH PORTA,7
#DEFINE
CONF_ENABLEH TRISA,7
#DEFINE
ENABLEV PORTB,3
#DEFINE
CONF_ENABLEV TRISB,3
#DEFINE
IZQUIERDA PORTB,4
#DEFINE
CONF_IZQUIERDA TRISB,4
#DEFINE
DERECHA PORTB,5
#DEFINE
CONF_DERECHA TRISB,5
#DEFINE
ARRIBA PORTB,6
#DEFINE
CONF_ARRIBA TRISB,6
#DEFINE
ABAJO PORTB,7
#DEFINE
CONF_ABAJO TRISB,7
#DEFINE LIBREA1 PORTA,1
#DEFINE LIBREA4 PORTA,4
#DEFINE LIBREA5 PORTA,5
#DEFINE LIBREA6 PORTA,6
#DEFINE CONF_LIBREA1 TRISA,1
#DEFINE CONF_LIBREA4 TRISA,4
#DEFINE CONF_LIBREA5 TRISA,5
#DEFINE CONF_LIBREA6 TRISA,6
;
; VARIABLES
;
Inicio_Memoria
DATO RS232
RET1 RET2 CONT8 rutinas MIRX y MITX
SOH EQU 0x0C
EQU (Inicio_Memoria+1) ;Dato a Transmitir o Recibido EQU (Inicio_Memoria+2) ;para retardo de bit RS232
EQU (Inicio_Memoria+3) ;para retardo de bit RS232
EQU (Inicio_Memoria+4) ;Contador de bits en EQU (Inicio_Memoria+5) ; registro para guardar el byte y comprobar si es carita
;
; Variables nuevas para recoger los datos del paquete de datos
;
Numero_Byte_Datos EQU
(Inicio_Memoria+6) ; un indice dentro del paquete de datos
PTactil_X_MSB
EQU
(Inicio_Memoria+7) ; Most Significant Byte de la X (10 bits)
PTactil_X_LSB
EQU
(Inicio_Memoria+8) ; Least Significant Byte de la X (10 bits)
PTactil_Y_MSB
EQU
(Inicio_Memoria+9) ; Most Significant Byte de la Y (10 bits)
PTactil_Y_LSB
EQU
(Inicio_Memoria+10) ; Least Significant Byte de la Y (10 bits)
Nueva_Pulsacion
EQU
(Inicio_Memoria+11) ; Se pone a 1 si hay pulsacion nueva de la pantalla
Pantalla_Tactil_X EQU
(Inicio_Memoria+12) ; Coordenada X de la pantalla (en formato 8 bits)
Pantalla_Tactil_Y EQU
(Inicio_Memoria+13) ; Coordenada Y de la pantalla (en formato 8 bits)
STATUS_BAK
EQU
(Inicio_Memoria+14) ; Coordenada Y de la pantalla (en formato 8 bits)
W_BAK
EQU
(Inicio_Memoria+15) ; Coordenada Y de la pantalla (en formato 8 bits)
;
;Variables ADC
delayA
EQU
(Inicio_Memoria+16);
delayB
EQU
(Inicio_Memoria+17); cont3 EQU (Inicio_Memoria+18);temporal para el muestra_adc
delayC EQU (Inicio_Memoria+19)
ANDATA1 EQU (Inicio_Memoria+20)
ANDATA2 EQU (Inicio_Memoria+21)
;
FASTRIGHT
EQU (Inicio_Memoria+22)
FASTLEFT
EQU
(Inicio_Memoria+23)
FASTUP
EQU
(Inicio_Memoria+24)
FASTDOWN
EQU
(Inicio_Memoria+25)
SLOWRIGHT
EQU
(Inicio_Memoria+26)
SLOWLEFT
EQU
(Inicio_Memoria+27)
SLOWUP
EQU
(Inicio_Memoria+28)
SLOWDOWN
EQU
(Inicio_Memoria+29)
HORIZONTAL EQU (Inicio_Memoria+30)
VERTICAL
EQU
(Inicio_Memoria+31)
ADC EQU
(Inicio_Memoria+32);
;
Temp1
EQU
(Inicio_Memoria+33);
Temp2
EQU
(Inicio_Memoria+34);
;============================================================================
ORG 0
GOTO INICIO
ORG 0x8 ; interrupcion alta prioridad (solo tenemos INT0)
GOTO INTERRUPCION
;Inicio del programa ORG 0x20
GOTO INICIO ; ir a INICIO
; Codigo de la interrupcion (Solo usamos INT0)
INTERRUPCION
BTFSS INTCON,INT0IF ;COMPROBACIÓN DE INTERRUPCION INT
RETFIE
;
movff STATUS, STATUS_BAK ;guardamos status
movwf W_BAK ;guardamos W
;
movf Numero_Byte_Datos,W
btfss STATUS, Z
goto Siguiente_Byte_1
CALL MIRXSOH
;Aquí llama para recibir SOH (cabecera)
XORLW TRUE ;Esto es una comprobación para saber si el procedimiento a ejecutao
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
goto Salir_Interrupcion
Siguiente_Byte_1
movf Numero_Byte_Datos,W
xorlw 1
btfss STATUS, Z
goto Siguiente_Byte_2
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
movf DATO,W
andlw 0x0f
movwf PTactil_X_MSB
goto Salir_Interrupcion
Siguiente_Byte_2
movf Numero_Byte_Datos,W
xorlw 2
btfss STATUS, Z
goto Siguiente_Byte_3
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
rlcf
DATO
rlcf
DATO
rlcf
DATO
rlcf
DATO
movf DATO,W
andlw 0xf0
movwf PTactil_X_LSB
goto Salir_Interrupcion
Siguiente_Byte_3
movf Numero_Byte_Datos,W
xorlw 3
btfss STATUS, Z
goto Siguiente_Byte_4
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
movf DATO,W
andlw 0x0f
addwf PTactil_X_LSB
goto Salir_Interrupcion
Siguiente_Byte_4
movf Numero_Byte_Datos,W
xorlw 4
btfss STATUS, Z
goto Siguiente_Byte_5
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
goto Salir_Interrupcion
Siguiente_Byte_5
movf Numero_Byte_Datos,W
xorlw 5
btfss STATUS, Z
goto Siguiente_Byte_6
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
movf DATO,W
andlw 0x0f
movwf PTactil_Y_MSB
goto Salir_Interrupcion
Siguiente_Byte_6
movf Numero_Byte_Datos,W
xorlw 6
btfss STATUS, Z
goto Siguiente_Byte_7
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
rlcf
DATO
rlcf
DATO
rlcf
DATO
rlcf
DATO
movf DATO,W
andlw 0xf0
movwf PTactil_Y_LSB
goto Salir_Interrupcion
Siguiente_Byte_7
movf Numero_Byte_Datos,W
xorlw 7
btfss STATUS, Z
goto Siguiente_Byte_8
CALL MIRXDATO
XORLW TRUE
btfss STATUS, Z
goto Error_Transmision
incf Numero_Byte_Datos
movf DATO,W
andlw 0x0f
addwf PTactil_Y_LSB
goto Salir_Interrupcion
Siguiente_Byte_8
;
bsf
Nueva_Pulsacion, 0 ; marcamos la llegada de nuevos datos
;
;
; el resto de bytes no nos importa
;ahora convertimos el formato de 10 bits en 8 bits (los mas significativos)
movff PTactil_X_LSB, Pantalla_Tactil_X
rrncf Pantalla_Tactil_X
rrncf Pantalla_Tactil_X
bcf
Pantalla_Tactil_X,7
bcf
Pantalla_Tactil_X,6
btfsc PTactil_X_MSB,1
bsf
Pantalla_Tactil_X,7
btfsc PTactil_X_MSB,0
bsf
Pantalla_Tactil_X,6
;
movff PTactil_Y_LSB, Pantalla_Tactil_Y
rrncf Pantalla_Tactil_Y
rrncf Pantalla_Tactil_Y
bcf
Pantalla_Tactil_Y,7
bcf
Pantalla_Tactil_Y,6
btfsc PTactil_Y_MSB,1
bsf
Pantalla_Tactil_Y,7
btfsc PTactil_Y_MSB,0
bsf
P
Pantalla_Tactil_Y,6
;
;termina la interrupcion normalmente
;
Error_Transmision
clrf Numero_Byte_Datos ; para que lea otro paquete
Salir_Interrupcion
;
movf W_BAK,W ;restauramos W
movff STATUS_BAK,STATUS ;restauramos status
;
BCF
INTCON,INT0IF ;BORRA BANDERA INT
R
RETFIE
;;;;;;;;;;;;;;;;;;; COMIENZO DEL PROGRAMA PRINCIPAL ;;;;;;;;;;;;;;;;;;;;;;;;
INICIO
;
; Inicializacion de variables
clrf Numero_Byte_Datos
clrf Nueva_Pulsacion
; Inicializacion de variables
;
; Configuracion
;
movlw b'11101111'
movwf OSCCON; velocidad de reloj 4 MHz
movlw 0h
movwf OSCTUNE; 4mhz exactos
;Configuración de todo el tema de motores
clrf PORTA
clrf PORTB
bcf CONF_ENABLEH
bcf CONF_ENABLEV
bcf CONF_IZQUIERDA
bcf CONF_DERECHA
bcf CONF_ARRIBA
bcf CONF_ABAJO
movlw 0xFF
;Todos los FAST<X> valen 0xAA (motor se mueve el 75% de los "pasos")
movwf HORIZONTAL
movwf FASTRIGHT
movwf FASTLEFT
movwf FASTUP
movwf FASTDOWN
movlw 0xEE
;Todos los SLOW<X> valen 0x88 (motor se mueve el 25% de los "pasos")
movwf SLOWRIGHT
movwf SLOWLEFT
movwf SLOWUP
movwf SLOWDOWN
; configuracion inicial de puertos PANTALLA
bcf
CONF_LIBREA1; configurar el pin del led a salida (DEBUG)
bcf
CONF_LIBREA4 ; configurar el pin del led a salida (DEBUG)
bcf
CONF_MITX ;configurar TX a salida
bsf
CONF_MIRX ;configurar RX a entrada
; configuracion inicial de puertos PANTALLA
; configuracion inicial de puertos Analogico
bsf CONF_MIAN0
bsf CONF_MIAN5
; configuracion inicial de puertos Analogico
movlw 0x7F
movwf ADCON1 ;en un principio todos los canales AN son puestos a digitales
;
bcf
INTCON2, INTEDG0 ; int0 en flanco bajada
;;;;;;
;Posiciones iniciales de los pines
BSF MITX
BSF MIRX
bcf
LIBREA1;LED1
bcf
LIBREA4 ; LED2
;Posiciones iniciales de los pines
;
;;;;;CONFIGURACION DEL CONTROLADOR DE LA PANTALLA EN FORMATO hexadecimal
;
call Espera_Larga CALL FH ; COMANDO PARA ESTABLECER FORMATO HEXADECIMAL
call Espera_Larga
CALL FH ; REPETIMOS EL COMANDO POR SI NO FUNCIONA LA PRIMERA VEZ
;
;;PRUEBA DEL LED ;DEBUG
bsf
LIBREA1;LED1
bsf
LIBREA4 ; LED2
call Espera_Larga
bcf
LIBREA1;LED1
bcf
LIBREA4 ; LED2
call Espera_Larga ;DEBUG
;;PRUEBA DEL LED ;DEBUG
;;HABILITAMOS LA INTERRUPCIONES para dar paso al programa principal
;
BSF INTCON,INT0IE ;HABILITA INTERRUPCIÓN INT0
bcf
INTCON, INT0IF ; borrar la flag de "ocurrido int0"
BSF INTCON,GIE ;HABILITA INTERRUPCIONES GLOBALMENTE
; segun el manual IPEN esta a 0 por defecto (prioridades altas)
; e INT0 es siempre de prioridad alta
;
; Programa principal
;
Bucle_Principal
; DEBUG programa de prueba
btfss Nueva_Pulsacion,0
goto Salir_BP
clrf Nueva_Pulsacion
;;;;
Bucle_Mover_Motor1
bcf
LIBREA1;LED1
bcf
LIBREA4 ; LED2
btfsc Pantalla_Tactil_X,7
bsf
LIBREA1;LED1
btfsc Pantalla_Tactil_X,6
bsf
LIBREA4 ; LED2
call movf
subwf
movff
movwf
analog
ANDATA1,W
Pantalla_Tactil_X,W ; ahora W tiene el resultado de PX­AND
STATUS,Temp2;
T
Temp1; lo poenemos en temp1
;
; segun el manual si el resultado es negativo ni carry ni zero estan puestos
;
movff Temp2,STATUS;
btfsc STATUS,Z
goto Motor_Positivo
btfsc STATUS,C
goto Motor_Positivo
;
;motor negativo
btfss WREG,7
goto rapido_neg
btfss WREG,6;s
goto rapido_neg
btfss WREG,5;s
goto rapido_neg
;
call inith
call sleft
goto Salir_Bucle_Mover_Motor1 r
rapido_neg
call inith
c
call fleft
;motor negativo
goto Salir_Bucle_Mover_Motor1
S
;motor positivo
Motor_Positivo
M
;zona muerta
;cuando estemos en un ciclo positivo y el valor <16 parar
andlw 0xf0
btfss STATUS,Z
goto Mover_positivo_Normal
call stoph
goto Salir_Bucle_Mover_Motor1
;
;
Mover_positivo_Normal
; recuperacion zona muerta
movf Temp1,W
;
andlw b'11100000'
btfsc STATUS,Z
goto rapido_pos
;
call inith
call fright
goto Salir_Bucle_Mover_Motor1 r
rapido_pos
call inith
c
call sright
;
;motor positivo
Salir_Bucle_Mover_Motor1
goto Bucle_Mover_Motor1
B
;;;
Salir_BP
goto
B
Bucle_Principal
;
;
;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;­­­retardo doble
Ret_2max
movlw 8
movwf delayC
Ret2max
call delay
decfsz delayC
goto Ret2max
return
;­­­­­retardo
Ret_max
movlw 4
movwf delayC
Retmax
call delay
decfsz delayC
goto Ret2max
return
;­­­­­­­­retardo mitad
Ret_max2
movlw 2
movwf delayC
Retmax2
call delay
decfsz delayC
goto Ret2max
return
delay
movlw 0xFF
movwf delayA
d
loopA
movlw 0xFF
movwf delayB
d
loopB
decfsz
delayB, f
goto loopB
decfsz
delayA, f
goto loopA
l
r
return
;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;Delay Routine
delayan
movlw 0x03
movwf delayA
loopAan
movlw 0xFF
movwf delayB
loopBan
decfsz
delayB, f
goto loopBan
decfsz
delayA, f
goto loopAan
return
;
;
; ******* Rutinas RS232
;
;
;
; Rutinas de RS232
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MIRXDATO
;RECIBE UN BYTE POR MIRX
;W := FALSE SI NO HAY START BIT AL PRINCIPIO
;W := TRUE ; DATO := BYTE RECIBIDO POR MIRX EJECUCION CORRECTA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BTFSS MIRX
GOTO MIRXBYTE
RETLW FALSE
MIRXBYTE
CALL TIME2
MOVLW 8
MOVWF CONT8
BIT CALL TIME
RRCF DATO,F
BCF DATO,7
BTFSC MIRX
BSF DATO,7
DECFSZ CONT8,F
GOTO BIT
CALL TIME2
RETLW TRUE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MIRXSOH
;RECIBE UN BYTE POR MIRX
;W := FALSE SI NO HAY START BIT AL PRINCIPIO, si no es SOH
;W := TRUE ; SOH := BYTE RECIBIDO POR MIRX EJECUCION CORRECTA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BTFSS MIRX
GOTO MIRXBYTESOH
RETLW FALSE
MIRXBYTESOH
CALL TIME2
MOVLW 8
MOVWF CONT8
BITSOH CALL TIME
RRCF SOH,F
BCF SOH,7
BTFSC MIRX
BSF SOH,7
DECFSZ CONT8,F
GOTO BITSOH
CALL TIME2
MOVF SOH,0 ;Se mueve el valor de SOH a W
BZ SALIRFALSE ; Si es 0, no es SOH
ANDLW CTRAN ; Realizamos un And con SOH negado
BZ SALIRTRUE ;Si el resultado de la AND fue 0, el caracter era SOH
RETLW FALSE ; Si el resultado de la AND no fue 0, el caracter no era SOH
SALIRTRUE
RETLW TRUE
SALIRFALSE
RETLW FALSE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MITXDATO ; TRANSMITE EL BYTE GUARDADO EN DATO POR LA LINEA MITX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVLW 8
MOVWF CONT8
BCF MITX
BIT2
CALL TIME
RRCF DATO,F
BTFSS STATUS,C
BCF MITX
BTFSC STATUS,C
BSF MITX
DECON
DECFSZ CONT8,F
GOTO BIT2
CALL TIME
BSF MITX
CALL TIME
RETURN
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TIME2 ;RETARDO DE 52 uS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVLW 1
MOVWF RET1
T1
MOVLW .14
MOVWF RET2
T2
DECFSZ RET2,F
GOTO T2
DECFSZ RET1,F
GOTO T1
NOP
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TIME ;104 uS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVLW 1
MOVWF RET1
T3
MOVLW .28
MOVWF RET2
T4
DECFSZ RET2,F
GOTO T4
DECFSZ RET1,1
GOTO T3
NOP
NOP
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ESPERAW ;tiempo de espera = W*(10*104) uS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVWF CONT8
BUCLEW
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
CALL TIME
DECF CONT8,1
BZ CONTINUARW
GOTO BUCLEW
CONTINUARW
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RET_CARRO ;Envía el retorno de carro
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVLW d'13'
MOVWF DATO
CALL MITXDATO
MOVLW 0FFh
MOVWF CONT8
CALL TIME
DECFSZ CONT8,F
MOVLW d'10'
MOVWF DATO
CALL MITXDATO
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
FH ;Envía el comando FH (formato hexadecimal) para la pantalla tactil
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOVLW 0x01
MOVWF DATO
CALL MITXDATO
MOVLW "F"
MOVWF DATO
CALL MITXDATO
MOVLW "H"
MOVWF DATO
CALL MITXDATO
CALL RET_CARRO
RETURN
;
; Fin rutinas de RS232
;
;
; Otras rutinas
;
Espera_Larga
CALL ESPERAW
MOVLW 0FFh
CALL ESPERAW
MOVLW 0FFh
CALL ESPERAW
MOVLW 0FFh
CALL ESPERAW
MOVLW 0FFh
CALL ESPERAW
return
;­­­­­­­­­­­
; lectura ADC
analog
movlw b'01111110'
movwf ADCON1 ;1º SELECCIONAR CANAL 0
movlw b'00000101'; right justified, 0TAD, FOSC/16
movwf ADCON2 ; configrar adcon2
movlw b'11000000' ;enable A/D, AN0, mod enable
movwf ADCON0
bsf
ADCON0,0 ; ACTIVAMOS EL CONVERSOR
; ESPERAMOS EL TIEMPO NECESARIO PARA LA ADQUISICION 1000 INSTRUCCIONES
call delayan
; tras la espera hacemos 0la conversion
BCF INTCON,GIE
bsf
ADCON0,GO
;go do a/d conversion
adloop
btfsc ADCON0,DONE
goto adloop
BSF INTCON,GIE
movff ADRESH,ANDATA1
;get the value in speed
bcf
ADCON0,0
call delayan
;;
call Ret_2max ; ESPERAMOS UN TIEMPO ANTES DE LA SIGUIENTE CONFIGURACION
movlw b'01011111'
movwf ADCON1 ;1º SELECCIONAR CANAL 5
movlw b'00000101'; right justified, 0TAD, FOSC/16
movwf ADCON2 ; configrar adcon2
movlw b'11010100' ;enable A/D, AN0, mod enable
movwf ADCON0
bsf
ADCON0,0 ; ACTIVAMOS EL CONVERSOR
; ESPERAMOS EL TIEMPO NECESARIO PARA LA ADQUISICION 1000 INSTRUCCIONES
call delayan
; tras la espera hacemos la conversion
BCF INTCON,GIE
bsf
ADCON0,GO
;go do a/d conversion
adloop2
btfsc ADCON0,DONE
goto adloop2
BSF INTCON,GIE
movff ADRESH,ANDATA2
;get the value in speed
bcf
ADCON0,0
movlw 0x7F
movwf ADCON1
BSF INTCON,GIE
return
;INICIO DE FUNCIONES DE MOTORES
inith bsf
ENABLEH
return
initv bsf
ENABLEV
return
stoph bcf
ENABLEH
return
stopv bcf
ENABLEV
return
fleft bcf
IZQUIERDA
bcf
DERECHA
btfsc FASTRIGHT, 7
bsf
IZQUIERDA
bcf
STATUS,C
rlcf FASTRIGHT, 1
btfsc STATUS,C
bsf
FASTRIGHT, 0
return
fright
bcf
IZQUIERDA
bcf
DERECHA
btfsc FASTLEFT, 7
bsf
DERECHA
bcf
STATUS,C
rlcf FASTLEFT, 1
btfsc STATUS,C
bsf
FASTLEFT, 0
return
fup
bcf
ARRIBA
bcf
ABAJO
btfsc FASTUP, 7
bsf
ARRIBA
bcf
STATUS,C
rlcf FASTUP, 1
btfsc STATUS,C
bsf
FASTUP, 0
return
fdown bcf
ARRIBA
bcf
ABAJO
btfsc FASTDOWN, 7
bsf
ABAJO
bcf
STATUS,C
rlcf FASTDOWN, 1
btfsc STATUS,C
bsf
FASTDOWN, 0
return
sleft bcf
IZQUIERDA
bcf
DERECHA
btfsc SLOWRIGHT, 7
bsf
IZQUIERDA
bcf
STATUS,C
rlcf SLOWRIGHT, 1
btfsc STATUS,C
bsf
SLOWRIGHT, 0
return
sright
bcf
IZQUIERDA
bcf
DERECHA
btfsc SLOWLEFT, 7
bsf
DERECHA
bcf
STATUS,C
rlcf SLOWLEFT, 1
btfsc STATUS,C
bsf
SLOWLEFT, 0
return
sup
bcf
ARRIBA
bcf
ABAJO
btfsc SLOWUP, 7
bsf
ARRIBA
bcf
STATUS,C
rlcf SLOWUP, 1
btfsc STATUS,C
bsf
SLOWUP, 0
return
sdown bcf
ARRIBA
bcf
ABAJO
btfsc SLOWDOWN, 7
bsf
ABAJO
bcf
STATUS,C
rlcf SLOWDOWN, 1
btfsc STATUS,C
bsf
SLOWDOWN, 0
return
;FIN DE FUNCIONES DE MOTORES
;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;
; RUTINAS MOSTRADO DATOS ADC (PARPADEO BITS)
;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;MUESTRA EL CONTENIDO DEL REGISTRO ADC BIT A BIT DE MENOS A MAS SIGNIFICATIVO
;PORTB7 DATO
;PORTB6 RELOJ
;CUANDO EL RELOJ ESTÁ A UNO EL DATO ES VALIDO
;CUANDO EL RELOJ ESTÁ A CERO NO HACER CASO AL DATO
;PRESUPONE EL PORTB EN MODO SALIDA
;DESTRUYE ADC
mostrar_ADC
;
movff ANDATA1,ADC
movlw 3
movwf cont3
ppad1
BSF LIBREA4 ;ENCIENDE RELOJ
call Ret_max2 ; RETARDO
BCF LIBREA4 ; APAGA RELOJ
BCF LIBREA1 ; APAGA data; christopher
call Ret_max2 ;RETARDO
DECFSZ cont3
goto ppad1
call Ret_2max
movlw 8
movwf cont3
siguiente_bit BCF LIBREA4 ; APAGA RELOJ
BCF LIBREA1 ; APAGA dato ;chrstopher
call Ret_max ;RETARDO
BCF LIBREA1
BTFSC ADC,0
BSF LIBREA1 ;coloca el siguiente bit en Dato
BSF LIBREA4 ; activa el reloj
call Ret_2max ;retardo
RRCF ADC
DECFSZ cont3
goto siguiente_bit
; termina la transmision, se apagan los leds
BCF LIBREA1
BCF LIBREA4
call Ret_max
;­­­­­­­­­­indica fin de transmision
movlw 3
movwf cont3
ppad2
BSF LIBREA4 ;ENCIENDE RELOJ
call Ret_max2 ; RETARDO
BCF LIBREA4 ; APAGA RELOJ
call Ret_max2 ;RETARDO
DECFSZ cont3
goto ppad2
return
;FIN MUESTRA_ADC­­­­­­­­­­­
;
;
;===========================================================================
;­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­
;PROgramacion de configuracion
org 0x300000
CONFIG1
data 0xC9FF
CONFIG2
data 0x000C
CONFIG3
data 0x00FF
CONFIG4
data 0xFF80
CONFIG5
data 0xC003
CONFIG6
data 0xE003
CONFIG7
data 0x4003
END 
Descargar