Muchas gracias de nuevo, Jonathan!! Pues me he pasado ayer toda la tarde revisando y no encuentro nada, las variables de memoria las declaro todas seguidas en el programa principal. Lo que si he observado es que si introduzco los valores por teclado muy rapido funciona bien, pero si los introduzco a una velocidad normal ya va mal... no se si esto servira de algo, asi que voy a colgar el codigo, es bastante extenso, pero puede que otros ojos lo vean mejor que los mios.. Hay subrutinas que no pongo porque es evidente lo que hacen y ocuparia mucho mas el codigo:
; ZONA DE DATOS
GUARDA_W EQU 0X20 ; variables para guardar los registros
GUARDA_S EQU 0X21
GUARDA_FSR EQU 0X22
PDel0 EQU 0x24
PDel1 EQU 0x25
PDel2 EQU 0x26
R_ContA EQU 0x27 ; Contadores para los retardos.
R_ContB EQU 0x28
R_ContC EQU 0x29
ASCII_H EQU 0x2A
ASCII_M EQU 0x2B
ASCII_L EQU 0x2C
HEXADECIMAL EQU 0x2D
HEXADECIMAL_X EQU 0X2E
ASCII1 EQU 0X2F
ASCII2 EQU 0X30
INNER EQU 0x31 ;delay variable mS
OUTER EQU 0x32 ;delay variable mS
Digito EQU 0x33
CBLOCK 0X40 ; aqui esta el status de lo enviado
startdelimiterst
lenght_hst
lenght_lst
apiidentifierst ; desde aqui se calcula el checksum
frameidst ;
statusst ; (ack/nack)
checksumst
FF
CHECK
ENDC
CBLOCK 0X50 ; aqui estan los datos enviados
startdelimitertx
lenght_htx
lenght_ltx
apiidentifiertx ; desde aqui se calcula el checksum
frameid ;
address_htx ;
address_ltx ; CHECKSUM
optionstx ;
dato1tx ;
dato2tx ; hasta aqui
checksumtx
datotx
rc_reg ; 0x5C
ENDC
CBLOCK 0x5F ; aqui estaran los datos recibidos
counter
startdelimiter
lenght_h
lenght_l
apiidentifier
saddress_h
saddress_l
rssi
options
dato1
dato2
checksum
cuenta_timer1 ; 0x5B
posicion_cursor
ENDC
CBLOCK 0x6E
TEMPORAL
CONTADOR ; todo esto sirve para los comandos AT
MEMORIA
MEMORIA2
MEMORIA3
MEMORIA4
MEMORIA5
MEMORIA6
teclapulsada ; almacena la tecla actual pulsada
pulsaciones ; pulsaciones que quedan para finalizar
centenas
decenas
unidades
velocidad ; velocidad en hexadecimal
tipo ; tipo
circ ; circunstancia
flujo ; sirve para saber en que punto nos encontramos
ENDC
processor 16F876
LIST P=16F876 ;Se indica el modo de procesador
INCLUDE <P16f876.inc> ;se incluye la definicion de los
;registros internos
__config 3D31
;----------------------------------------------------------------------------
org 0x00 ;vector de inicio
goto INICIO
org 0x04 ;despues del vector de interrupcion
goto ServicioInterrupcion
;<<<<<<----------------- INICIO PROGRAMA PRINCIPAL ------------------->>>>>>>
;----------------------------------------------------------------------------
INICIO
call configura_micro
call inicializa_lcd
call MuestraBien
call PDelay ; retardo de 2 segundos
otratipo
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call PideTipo
movlw 0x01
movwf pulsaciones ; inicializamos pulsaciones maximas
clrf flujo ; esta en tipo --> flujo=0
movlw 0xFF ; ponemos a algo distinto de 0
movfw centenas
movfw decenas
movfw unidades
otra
call Teclado_Inicializa
call Habilita_Int_Teclado
sleep
; mira si tiene que volver a dormir o no
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otratipo ; si, borra
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto fintipo ; si, pasa a lo siguiente
call Retardo_100ms
goto otra
fintipo
;********************************************************************
otravel
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call PideVel
movlw 0x03
movwf pulsaciones ; inicializamos pulsaciones maximas
movlw 0x01
movwf flujo ; esta en velocidad --> flujo=1
clrf centenas
clrf decenas
clrf unidades
call Cursor_on
otra2
call Teclado_Inicializa
call Habilita_Int_Teclado
sleep
; mira si tiene que volver a dormir o no
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otravel ; si, borra
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto FinVel ; si, va a calcular
call Retardo_100ms
goto otra2
FinVel
; metemos el valor de la velocidad en dato1tx
movfw velocidad
movwf dato1tx
;********************************************************************
otracirc
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call PideCirc
movlw 0x01
movwf pulsaciones ; inicializamos pulsaciones maximas
movlw 0x02
movwf flujo ; esta en circunstancia --> flujo=2
movlw 0xFF
movwf centenas
movwf decenas
movwf unidades ; para que sea erroneo si no se mete nada
call Cursor_on
otra3
call Teclado_Inicializa
call Habilita_Int_Teclado
sleep
; mira si tiene que volver a dormir o no
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otracirc ; si, borra
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto FinCirc ; si, va a calcular
call Retardo_100ms
goto otra3
FinCirc
call montadato2tx
;*******************************************************************
;*******************************************************************
;*******************************************************************
;*******************************************************************
;
; ya esta todo metido, nos preparamos para transmitir
;
call configura_micro
;**************************
call Borra_home
call INITX ; inicializamos la transmision
call SET125K ; micro a 125Kbps
retransmitir
movlw 0X40 ; dirección de memoria RAM a escribir.
movwf counter ; el TX STATUS que manda el Xbee
call BORRAAPIST
call RX ; nos preparamos para recibir por interrupciones
call APITX
call Retardo_10ms ; tiempo reducido al maximo
call MUESTRAAPIST
LeeVelocidad
banksel PORTA
bcf PORTA,2 ;Desactiva LCD
call LeeTecla
movwf teclapulsada
bsf STATUS,RP0 ;banco 1
movlw b'00000000' ; deshabilita interrupciones
movwf INTCON
bcf STATUS,RP0 ; banco 0
;*******************************************************
; aqui lee lo introducido, lo almacena en variables y calcula lo que va a enviar
; antes de nada ha de mirar si es A o B para salir del bucle y ordenar los datos
; antes de calcular el valor de la velocidad en hexadecimal
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otravel ; si, repite
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto calcular_vel ; si, va a calcular
; no es ni A ni B
; almacena lo tecleado
;
goto continuavel ; esta bien, continua
error_vel
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call Cursor_off
call MensVelInc
call PDelay ; retardo 2 segundos
goto otravel ; vuelve a pedir la velocidad
continuavel
decf pulsaciones
movlw 0x02
subwf pulsaciones,0 ; es centenas?
btfsc STATUS,Z ;
goto mete_centenas ; si, lo guarda
movlw 0x01
subwf pulsaciones,0 ; es decenas?
btfsc STATUS,Z ;
goto mete_decenas ; si, lo guarda
movlw 0x00
subwf pulsaciones,0 ; es unidades?
btfsc STATUS,Z ;
goto mete_unidades ; si, lo guarda
; si llega aqui es que se ha pasado, no hace nada y
; espera a que se pulse A o B
goto finesperavel
mete_centenas
movfw teclapulsada
movwf centenas
goto fincalcula
mete_decenas
movfw teclapulsada
movwf decenas
goto fincalcula
mete_unidades
movfw teclapulsada
movwf unidades
goto fincalcula
calcular_vel ; llega aqui si se pulsa B
; aqui mira si son 1, 2 o 3 digitos pulsados y organiza los datos
; si pulsaciones es 0 es que ha metido 3 datos, si es 1 ha metido 2 datos
movlw 0x00
subwf pulsaciones,0 ; pulsaciones-0=pulsaciones --> afecta al flag Z
btfsc STATUS,Z ; ha metido 3 digitos?
goto bienmetido ; si, esta bien ordenado
; no, hay que reordenar los 2 datos
movlw 0x01 ; ha metido 2?
subwf pulsaciones,0 ;
btfss STATUS,Z ; ha metido 2 digitos?
goto error_vel ; no, esta mal
; si, hay que ordenarlos
movfw decenas
movwf unidades
movfw centenas
movwf decenas ; ya esta ordenado
clrf centenas ; centenas tiene que ser 0
bienmetido ; a partir de aqui hay que pasar los 3 bytes a un solo valor
clrf velocidad
; centenas
movlw 0x00
subwf centenas,0 ; centenas-0 --> afecta al flag Z
btfsc STATUS,Z ; centenas es 0?
goto metedecenas ; si, centenas es 0
; no, centenas no es 0
movlw d'100'
addwf velocidad ; valor+100
metedecenas ; multiplica las decenas por 10 (bucle)
movlw 0x0B
movwf TEMPORAL ; reutilizo esta variable como contador
bucle
decf TEMPORAL
btfsc STATUS,Z ; es 0?
goto meteunidades ; si, guarda el resultado
; no, sigue en el bucle
movfw decenas
addwf velocidad,1 ; decenas+decenas
goto bucle
; ya esta almacenado en valor
meteunidades ; solamente hay que sumar las unidades
movfw unidades
addwf velocidad,1
; en valor tenemos el resultado de la velocidad en hexadecimal
; si es mayor de 120 esta mal
movlw 0x79 ; 121
subwf velocidad,0 ; velocidad-121 = negativo
btfsc STATUS,C ; si C=0 es negativo --> salta
goto error_vel ; la velocidad esta mal --> repetir
movlw 0xA ; 10
subwf velocidad,0 ; velocidad-10 = negativo
btfss STATUS,C ; si C=1 es positivo --> bien
goto error_vel ; si C=0 es negativo --> error
; la velocidad esta bien
goto finesperavel
;****************************************************
fincalcula
movfw teclapulsada
call hextoascii
movfw ASCII2
call LCD_DATOS ; Visualiza caracter
finesperavel
return
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
LeeTipo
banksel PORTA
bcf PORTA,2 ; Desactiva LCD
call LeeTecla
movwf teclapulsada ; guardamos la tecla pulsada
bsf STATUS,RP0 ;banco 1
movlw b'00000000' ; deshabilita interrupciones
movwf INTCON
bcf STATUS,RP0 ; banco 0
;*******************************************************
; aqui lee lo introducido, lo almacena en variables y calcula lo que va a enviar
; antes de nada ha de mirar si es A o B para salir del bucle y ordenar los datos
; antes de calcular el valor de la velocidad en hexadecimal
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otratipo ; si
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto mete_unidades_tipo ; si
; no es ni A ni B
; almacena lo tecleado
decf pulsaciones
movlw 0x00
subwf pulsaciones,0 ; es unidades?
btfss STATUS,Z ;
goto finespera_tipo ; no, no hace nada
movfw teclapulsada ; si
movwf unidades ; guarda unidades
goto fincalcula_tipo ; pinta la letra y vuelve al sleep
mete_unidades_tipo ; llega aqui si pulsa correctamente B
; solo puede haber 1 digito, 0, 1 o 2
movlw 0x01
subwf pulsaciones,0 ; ha pulsado solo B?
btfsc STATUS,Z ; si, Z estara a 1
goto error_tipo ; no, no hace nada
movlw 0x03 ; comprueba si es mayor de 2
subwf unidades,0 ; unidades-3 = negativo
btfsc STATUS,C ; si C=0 es negativo --> salta
goto error_tipo ; el tipo esta mal --> repetir tipo
movfw unidades ; el tipo esta bien, lo almacena
movwf tipo ; en tipo
goto finespera_tipo
error_tipo
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call Cursor_off
call MensTipoInc
call PDelay ; retardo 2 segundos
; call Borra_home
goto otratipo ; vuelve a pedir el tipo
;****************************************************
fincalcula_tipo
movfw teclapulsada
call hextoascii
bsf PORTA,2 ; activa LCD
movfw ASCII2
call LCD_DATOS ; Visualiza caracter
finespera_tipo
return
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
;************************************************************************
LeeCirc
banksel PORTA
bcf PORTA,2 ;Desactiva LCD
call LeeTecla
movwf teclapulsada ; guardamos la tecla pulsada
bsf STATUS,RP0 ;banco 1
movlw b'00000000' ; deshabilita interrupciones
movwf INTCON
bcf STATUS,RP0 ; banco 0
;*******************************************************
; aqui lee lo introducido, lo almacena en variables y calcula lo que va a enviar
; antes de nada ha de mirar si es A o B para salir del bucle y ordenar los datos
; antes de calcular el valor de la velocidad en hexadecimal
movlw 0x0A
subwf teclapulsada,0 ; es A?
btfsc STATUS,Z ;
goto otracirc ; si
movlw 0x0B
subwf teclapulsada,0 ; es B?
btfsc STATUS,Z ;
goto mete_unidades_circ ; si
; no es ni A ni B
; almacena lo tecleado
decf pulsaciones
movlw 0x00
subwf pulsaciones,0 ; es unidades?
btfss STATUS,Z ;
goto finespera_circ ; no, no hace nada
movfw teclapulsada ; si
movwf unidades ; guarda unidades
goto fincalcula_circ ; pinta la letra y vuelve al sleep
mete_unidades_circ ; llega aqui si pulsa correctamente A o B
; solo puede haber 1 digito, 0, 1 o 2
movlw 0x0A ; comprueba si es mayor de 9
subwf unidades,0 ;unidades-A = negativo
btfsc STATUS,C ; si C=0 es negativo --> salta
goto error_circ ; el tipo esta mal --> repetir mensaje
movfw unidades ; el tipo esta bien, lo almacena
movwf circ ; en tipo
goto finespera_circ
error_circ
call Borra_home
movlw 0x80 ;Direccion caracter
call LCD_REG
call Cursor_off
call MensCircInc
call PDelay ; retardo 2 segundos
call Borra_home
goto otracirc ; vuelve a pedir el tipo
;****************************************************
fincalcula_circ
movfw teclapulsada
call hextoascii
bsf PORTA,2 ; activa LCD
movfw ASCII2
call LCD_DATOS ; Visualiza caracter
finespera_circ
return
;************************************************************************
ServicioInterrupcion
; GUARDAR WREG, STATUS, FSR EN LA PILA
MOVWF GUARDA_W
SWAPF STATUS,W
MOVWF GUARDA_S
SWAPF FSR,W
MOVWF GUARDA_FSR
bcf STATUS,RP0 ; banco 0
btfss PIR1,RCIF ; ha sido por recepcion?
goto otras ; no, mira otras interrupciones
bcf PIR1,RCIF ; si, borra el bit de aviso
; escribimos en ram con direccionamiento indirecto
call escribeindir ; pinta en pantalla lo recibido
goto finirq
otras ; aqui ponemos las otras interrupciones (teclado)
bcf STATUS,RP0 ;banco 0
movlw 0x00
subwf flujo,0 ; mira a ver si es 0
btfsc STATUS,Z ; si es velocidad (1) o circunstancia (2), salta
goto estaentipo
movlw 0x01
subwf flujo,0 ; mira a ver si es 1
btfss STATUS,Z ; si es velocidad (1), salta
goto estaencirc
goto estaenvel
estaentipo
call LeeTipo
goto finirq
estaenvel
call LeeVelocidad
goto finirq
estaencirc
call LeeCirc
goto finirq
finirq
; RECUPERAMOS DE LA PILA
MOVF GUARDA_FSR,W
MOVWF FSR
SWAPF GUARDA_S,W
MOVWF STATUS
SWAPF GUARDA_W,W
retfie
INCLUDE <MENSAJES_P.INC>
INCLUDE <MICRO.INC>
INCLUDE <CONVIERTE.INC>
INCLUDE <LCD.INC>
INCLUDE <RETARDOS.INC>
INCLUDE <COMUNICACION.INC>
INCLUDE <TECLADO_3X4.INC>
INCLUDE <API.INC>
INCLUDE <AT.INC>
END