Autor Tema: Desesperacion 16F877A  (Leído 2620 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado oticeip

  • PIC10
  • *
  • Mensajes: 2
Desesperacion 16F877A
« en: 30 de Marzo de 2011, 13:50:24 »
Hola!
Estoy empezando a programar microcontroladores y me he quedado en un punto en el que no se avanzar.
Mi programa tiene que tener 3 modos de funcionamiento , (en cada uno de ellos el display mostrará una cosa) , y dentro de cada modo, se podrá elegir entre mostrarlo en el display en sentido ascendente o descendente.
Para pasar de un modo de funcionamiento a otro, se tendrá que detectar una pulsación larga
Para pasar de modo ascendente a descendente o viceversa dentro de un mismo modo se tendrá que realizar una pulsación corta
Tengo habilitadas las interrupciones en el timer y son cada 20 mS. La rutina empieza en T1_INT
Cada vez que vuelva de la interrupción  compruebo en qué modo está,si no se pulsaestá pulsado el pulsador,  debe mostrar un 2 en un display de 7 segmentos, (eso lo hace bien).

Cuando vuelvo de la interrupción y el pulsador está pulsado, decremento una variable (pulsacionLarga) inicializada a 33h y así 33h*20mS me darán 1200 mS que es lo que considero como pulsación larga, y una variable pulsado a 1. cuando pulsacionLarga esta variable llegue a 0, deberia mostrar el numero 6, ir de nuevo al fin del tratamiento de la rutina (END_ISR) y al programa principal que es un bucle a si mismo.

Cuando vuelva a la interrupcion y ya no esté pulsado el pulsador, si antes había estado pulsado (lo se por la variable pulsado) deberia ir a mostrar3.

El problema es que siempre entra por donde muestra 6 y luego va a mostrar 3, sin importar cuanto vale pulsacionLarga o si ha llegado a 0es decir entra por los dos sitios seguidos, he intentado hacer un debug pero parece que en el debug funciona...
Si me pueden ayudar se lo agradecería mucho

Este es el código:

Código: [Seleccionar]
list p=16f877 ; Indicamos procesador destino y radix
#include P16F877A.INC ; Define gran cantidad de constantes relacionadas con este procesador

__CONFIG _DEBUG_OFF & _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _HS_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF



#define TICKS 13h ; Ticks entre parpadeo cada tick = 20 mS. = 0,4 segundos cada cambio
tiempoNoMostrar EQU 0x20   
display EQU 0x21
tiempoMostrar EQU 0X22
Tiempo EQU 0X23
pulsado EQU 0X24
modo EQU 0X25
cambioModo EQU 0X26
pulsacionLarga EQU 0X27
tarara EQU 0X28
;*********************** INICIO DE LA DEFINICION DE VARIABLES ***********************


w_temp EQU 0x71 ; variable usada pora salvar el contexto
status_temp EQU 0x72 ; variable usada pora salvar el contexto
;************************* FIN DE LA DEFINICION DE VARIABLES ************************



ORG 0x00 ; lo que hay después de esta línea, quedará en la declaración 0 de mi programa
nop     ; Este byte está reservado para el ICD
clrf PCLATH ; resetea solo la parte baja cuando hay un reset, no todo el PC counter.
    ; así garantizo que mi PC está en la parte baja a 0 cuando se resetee, en cualquier caso.
goto Inicio ; las interrupciónes de después se antenderían en la instrucción 4.




;|------------------------------------------------------------------------------|
;|-------------Inicio de las rutinas de atención a interrupción-----------------|


ORG 0x04 ; dirección del vector de interrupción
movwf w_temp ; Salvar el contenido de W
movf STATUS,w ; Salvar el contenido de STATUS
movwf status_temp ; Salvar el contenido de STATUS
goto T1_INT ; SI, atender interrupción.T1

END_ISR

;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
movlw   0B2h  ; 256-178= 78 pulsos en Timer0 para desbordarse
    ; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf   TMR0        ; t_tic = 20 mseg
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
retfie



T1_INT ; Rutina para la interrupción de Timer1 overflow
;COMPROBAR EN QUE MODO ESTOY

movlw 000h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo1
movlw 001h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo2
movlw 002h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo3
movlw 003h
xorwf modo,0
btfsc STATUS,2
goto TratamientoModo4
goto TratamientoModo5




TratamientoModo1


bcf PIR1,T0IF; Poner a 0 el flag de la interrupción del Timer0
btfsc PORTB,RB0
goto Ver1;no pulsado
bsf PORTB,1;PULSADO
movlw 01h
movwf pulsado
decf pulsacionLarga,1
movlw 00h
xorwf pulsacionLarga,0
btfss STATUS,2
goto END_ISR;si no ha llegado a pulsacion larga
goto CambiarModo3


Ver1;no pulsado
movlw 01h;si NO ha estado pulsado antes tengo que mostrar
xorwf pulsado,0
btfss STATUS,2
goto Mostrar;no activado con anterioridad
bcf PORTB,1;activado con anterioridad
goto CambiarSentido2 ;no es cambiar de modo


CambiarSentido2
movlw 03h
call hex27seg
movwf PORTC
call Pausa
goto END_ISR

CambiarModo3
movlw 00h
xorwf pulsacionLarga,0
btfss STATUS,2
goto END_ISR
movlw 06h
call hex27seg
movwf PORTC
goto END_ISR

TratamientoModo2
goto END_ISR

TratamientoModo3
goto END_ISR

TratamientoModo4
goto END_ISR

TratamientoModo5
goto END_ISR


Mostrar
movlw 02h
call hex27seg
movwf PORTC
call Pausa
goto END_ISR ; Fin de la rutina
Inicio

banksel TRISB ; Seleccionamos el Banco1
        ; TRISA, TRISB, etc. (están en el banco 1: por defecto estoy en el banco 0, por haber arrancado)

; Configuración puertos:   usaremos 2 elem de salida: led(pin 1 del puerto b) y dilplay(8 pines del puerto c)

movlw B'00000001'  ;llevar al registro de trabajo ese valor
movwf TRISB  ; Bit 0 de PORTB entrada, el resto como salida  (1 es entrada, 0 es salida)
clrf TRISC  ; PORTC configurado como salidas en todos sus bits

; Configuración del timer

movlw b'01010111'
  movwf OPTION_REG
banksel PORTB ; Seleccionamos el Banco0, pues como option reg está en todos los campos, no pasa nada, pero me debo mover a portb para después.
clrf PORTB

;////////////////////// Habilitar interrupciones //////////////////////
banksel PORTB ; banco 0
bsf INTCON,PEIE ; Habilito interrupciones de perifericos
bsf INTCON,GIE ; Habilito interrupciones globales

banksel TRISB ; banco 1
bsf INTCON,T0IE ; Habilitamos interrupcion overflow del timer 0

banksel PORTB ; banco 0
bcf INTCON,T0IF ; Limpio flag interrupción
;////////////////////// Habilitar interrupciones //////////////////////


;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------
movlw   0B2h     ; 256-178= 78 pulsos en Timer0 para desbordarse
    ; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf   TMR0        ; t_tic = 20 mseg
;--------------------- CADA 20 MILISEGUNDOS ME SALTA LA INTERRUPCIÓN DE DESBORDAMIENTO DEL TIMER0 -----------------

movlw 00h
movwf pulsado
movlw 00h
movwf modo
movlw 30h
movwf pulsacionLarga
movlw 00h
movwf cambioModo



Bucle
goto Bucle


Pausa
movlw TICKS       ; tiempo_espera = TICKs * t_tic
movwf Tiempo      ; guarda valor en memoria


Otro_tic
movlw   0B2h  ; 256-178= 78 pulsos en Timer0 para desbordarse
    ; 78 pulsos * 256 microSeg. por pulso = 20 mS. aprox.
movwf   TMR0        ; t_tic = 20 mseg
Sigue
btfss INTCON,T0IF  ; ¿desbordamiento?
goto Sigue       ; no
    bcf INTCON,T0IF    ; si -> repongo flag
decfsz Tiempo, F ;se repite el
goto    Otro_tic
return   





 
;****************************************
hex27seg
;****************************************
; Subrutina hex27seg, que recibe un valor hexadecimal de un dígito en W,
; y devuelve en el mismo registro el valor correspondiente al de un
; display de 7 segmentos.
; A continuación se muestra el nombre de cada segmento en un Display
;
;* RC0/RC7 Display de 7 segmentos
;*            -----
;*           |  a  |
;*          f|     |b
;*           |     |
;*            -----
;*           |  g  |
;*          e|     |c
;*           |     |
;*            -----
;/              d     .dp
;* RC0 dp
;* RC1 segmento c
;* RC2 segmento d
;* RC3 segmento e
;* RC4 segmento g
;* RC5 segmento f
;* RC6 segmento a
;* RC7 segmento b
;
andlw b'0001111' ; Nos aseguramos que está en el rango 0..15
addwf PCL, F ; se desplaza el PCL (funciona como un switch)
retlw b'11101110' ; se muestra 0
retlw b'10000010' ; se muestra 1
retlw b'11011100' ; se muestra 2
retlw   b'11010110'     ; se muestra 3
retlw b'10110010' ; se muestra 4
retlw b'01110110' ; se muestra 5
retlw b'01111110' ; se muestra 6
retlw b'11000010' ; se muestra 7
retlw b'11111110' ; se muestra 8
retlw b'11110010' ; se muestra 9
retlw b'11111011' ; se muestra A
retlw b'00111111' ; se muestra B
retlw b'01101101' ; se muestra C
retlw b'10011111' ; se muestra D
retlw b'01111101' ; se muestra E
retlw b'01111001' ; se muestra F

END

 











Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: Desesperacion 16F877A
« Respuesta #1 en: 30 de Marzo de 2011, 14:58:26 »
Tengo un poco olvidado el ASM y quizas esté equivocado pero te adjunto mis comentarios:

- Bajo mi punto de vista dentro e la interrupcion no deberias de poner tantos "goto" y llamadas "call"
- Para salir de la interrupcion hay que colocar la instruccion: "retfie". En vez de poner goto END_ISR despues de cada comprobacion dentro de la interrupcion, seria mejor poner un retfie
- Creo que las lineas de salvar el estado del W, pclath,.... lo deberias colocar justo despues de la etiqueta "T1_INT, segun está me da la impresion que no se guarda. Como te digo siempre lo guardara.
- Tampoco veo que antes de salir recuperes el valor de los registros guardados nada mas entrar en la interrupcion
- Para las pulsaciones largas no tendria muchos problemas, pero para las cortas debido a los rebotes que se producen en los contactos del pulsador podrias tener problemas. Creo que te faltaria añadir algun tipo de retardo bien por software o bien con algo de hardware.


F.
« Última modificación: 30 de Marzo de 2011, 15:05:08 por Fer_TACA »
Todos los días se aprende algo nuevo.

Desconectado oticeip

  • PIC10
  • *
  • Mensajes: 2
Re: Desesperacion 16F877A
« Respuesta #2 en: 31 de Marzo de 2011, 06:24:35 »
En primer lugar agradecerte tu respuesta
En segundo lugar, aunque el código tenga muchos goto no debería fallar por eso, todos los que van a END_ISR hacen retfie ya que es donde acaba la rutina
Lo de guardar el estado de los registros W, pclath,.... es una mera informalidad, porque cuando salta la interrupción no se ha trabajado con ninguno de ellos ya que lo que se hace es:

Bucle
               goto Bucle


¿Alguien sabe que más puedo probar? :(

Muchas gracias

Desconectado Fer_TACA

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 4154
Re: Desesperacion 16F877A
« Respuesta #3 en: 31 de Marzo de 2011, 17:09:07 »
Ya pero si no los guardas pquizas tengas problemas ya que dentro de las interrupciones realizas llamadas a varias subrutinas ¿me equivoco?
Todos los días se aprende algo nuevo.


 

anything