Potenciometro para atrasar disparo

markonikov, esta mi sugerencia del como podrías solucionar el problema con el LCD.
Asumiendo que tienes un detector de cruce por cero externo y que entrega una onda cuadrada de modo que cuando empieza un semi ciclo positivo genera un flanco de subida y cuando empieza un semi ciclo negativo genera un flanco de bajada.
Periodo de cada semi ciclo igual a 10ms, asumiendo que la frecuencia de línea es 50Hz.

Los procesos prioritarios para el microcontrolador son.
-detección de cruce por cero
-pulso de disparo para el triac.

Procesos que no son muy prioritarios
-visualización en el LCD
-lectura del conversor analógico a digital

Código:
En la rutina principal (main)
     Configurar la interrupción externa por flanco de subida
     Configurar la interrupción temporizada (por ejemplo el timer 0) a 100us.
     En bucle infinito (while=true)
          Lectura del adc
          Calculo de tiempo de disparo del triac en ente 1 y 90 en función del dato leído por el ADC
          Mostar en el LCD el mensaje deseado
     Fin de bucle infinito
Fin de main

Rutina de interrupción externa
     Si es flanco de subida
          Cambiar a flanco de bajada
     Si no
          Cambiar a flanco de subida
     Fin si
     Iniciar, activar, dispara al temporizador
Fin de interrupción externa

Rutina de interrupción temporizada
     Si variable de cuenta  = a tiempo de disparo del triac (1 y 90)
          Dispara el triac
          Reiniciar variable de cuenta
          Detener el temporizador
     Fin fi 
     Cargar los registros del temporizador para un tiempo de 100us
Fin de interrupción

Este pseudocodigo es funcional asumiendo que el compilador que usas no desactive las interrupciones cuando escribe mensajes en el LCD, de otro modo abría que buscar soluciones de mas bajo nivel como el manejo del LCD sin la ayuda de la librería.

PD. Normalmente trabajo en compiladores en C como el CCS PICC y Mikro C tambien en ASM, por lo cual no puedo hacer mucho con el código que tienes.
 
yo tambien trabajo con assembler lo entiendo mas que los demas, solo que por facilidad uso basic.. intentare hacer lo que dices compañero, en todo caso gracias por la ayuda.

me surge una duda referente al código:
para establecer el vector de interrupción escribo "on interrupt goto >>etiqueta<<" pero si tengo 2 interrupciones :S ?? solo puedo definir una sola etiqueta no ?
 
Última edición:
Una interrupcion en asm se vectoriz del siguente modo:

Código:
     org 0x04

     btfsc INTCON,TMR0IF
     goto interrupcion_timer0
     btfsc INTCON,INTF
     goto interrupcion_externa
     .
     .
     .
interrupcion_timer
     codigo
interrupcion_externa
     codigo
obiamente antes de salir de la interrupcion hay que borrar el flag de interrupcion correspondiente y terminar con un retfie para que regrese a la rutina principal.
 
Una interrupcion en asm se vectoriz del siguente modo:

Código:
     org 0x04

     btfsc INTCON,TMR0IF
     goto interrupcion_timer0
     btfsc INTCON,INTF
     goto interrupcion_externa
     .
     .
     .
interrupcion_timer
     codigo
interrupcion_externa
     codigo
obiamente antes de salir de la interrupcion hay que borrar el flag de interrupcion correspondiente y terminar con un retfie para que regrese a la rutina principal.

mmm falta bastante, se debe guardar el contenido de los REGs auxiliares (W, STATUS y etc) porque si la rutina de INT los modifica se producen errores al retrornar al programa principal, ademas antes de salir de la INT se deben restaurar a su estado original dichos REGs, lo mejor copia esta parte de la plantilla del pic que sugiere microchip, chauuuuuuu
 
fdsergio, lo que dices es cierto, en el caso respodi a la forma vectorizar las interrupciones y obviamente di por hecho esos detalles, pero valga la observación.
 
hola @marconikov, "pensandolo un poco, como que esta complicadito" hacer el programa es asm, pero a grandes problemas, grandes soluciones.
aqui va, fue hecho en MPLABX
Código:
    include <p16f877.inc>
    list p=16f877
     __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_ON & _CP_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_ON
;*****************************************************
;Declaracion de variables y constantes
;*****************************************************
#define     lcd     PORTD       ;puerto d para el el lcd
#define     rs      PORTC,0     ;
#define     en      PORTC,1     ;
cargar_timer equ .178
;****************************
;Para la rutina de divicion
;****************************
TRUE    equ     1       ;
FALSE   equ     0       ;
SIGNED  equ     FALSE   ;divicion sin signo
;****************************
udata   0x20
cont_timer  res 1
;****************************
;Para la rutina de divicion
;****************************
ACCaLO      res 1
ACCaHI      res 1
ACCbLO      res 1
ACCbHI      res 1
ACCcLO      res 1
ACCcHI      res 1
ACCdLO      res 1
ACCdHI      res 1
temp        res 1
sign        res 1
;*****************************************************
n1          res 1
W_TEMP      res 1
STATUS_TEMP res 1
PCLATH_TEMP res 1
;***************************************************
;Para la rutina de convercion bin16 a BCD
;***************************************************
count       res 1
;temp        res 1
H_byte      res 1
L_byte      res 1
R0          res 1
R1          res 1
R2          res 1
;***************************************************
PDel0       res 1   ;para el terardo de 10ms
PDel1       res 1   ;
n_lcd        res 1    ;contador de caracteres para el LCD



    org 0x00
    goto    inicio
    org 0x04
;**********************************************
;Bloque de interrupciones
;**********************************************
interrupciones
push
    MOVWF   W_TEMP
    SWAPF   STATUS,W
    CLRF    STATUS
    MOVWF   STATUS_TEMP
    MOVF    PCLATH,W
    MOVWF   PCLATH_TEMP
    CLRF    PCLATH

    btfsc   INTCON,INTF
    goto    interrupcion_externa
    btfss   INTCON,TMR0IF
    goto    salida_de_interrupcion
;************************************************
interrupcion_temporizada
    bcf     INTCON,TMR0IF
    btfss   PORTB,1
    goto    i0
    banksel OPTION_REG              ;bank 1
    bsf     OPTION_REG,T0CS         ;timer0 stop
    banksel PORTB                   ;bank 0
    bcf     PORTB,1
i0
    decfsz  n1,F
    goto    siguiente_carga
    bsf     PORTB,1
siguiente_carga
    movlw   cargar_timer
    movwf   TMR0
    goto    salida_de_interrupcion
;************************************************
interrupcion_externa
    movlw   cargar_timer+.12
    movwf   TMR0
    banksel OPTION_REG          ;bank1
    btfss   OPTION_REG,INTEDG
    goto    config_flanco_subida
config_fanco_bajada
    bcf     OPTION_REG,INTEDG
    goto    $+2
config_flanco_subida
    bsf     OPTION_REG,INTEDG
    bcf     OPTION_REG,T0CS     ;timer0 run
    banksel INTCON              ;bank0
    bcf     INTCON,INTF
    movfw   cont_timer
    movwf   n1
salida_de_interrupcion
pop
    MOVF    PCLATH_TEMP, W
    MOVWF   PCLATH
    SWAPF   STATUS_TEMP,W
    MOVWF   STATUS
    SWAPF   W_TEMP,F
    SWAPF   W_TEMP,W
    retfie
;*********************************************
inicio
;*********************************************
;Cionfiguracion de las interrupciones
;*********************************************
    movlw   b'10110000'
    movwf   INTCON
;*********************************************
;configuracion de puertos de entrada y salida
;*********************************************
    clrf    PORTB
    banksel TRISB           ;bank 1
    movlw   b'11111101'
    clrf    TRISD
    bcf     TRISC,0
    bcf     TRISC,1
    movwf   TRISB
;*********************************************
;Configuracion del ADC
;*********************************************
    banksel ADCON0          ;bank 0
    movlw   b'11000001'
    movwf   ADCON0
    banksel ADCON1          ;bank 1
    movlw   b'11001110'
    movwf   ADCON1
;*********************************************
    banksel ADCON0          ;bank 0
    call        limpiar_lcd
    call        c_der_quieto
    call        si_visual_no_cur_no_parpadeo
    call        cursor_home
    call        esc_mensaje
    call        desp_cur_iz
    call        desp_cur_iz
    call        desp_cur_iz
loop
    bsf     ADCON0,GO
    btfsc   ADCON0,GO
    goto    $-1
    movfw   ADRESH
    movwf   ACCbHI
    banksel ADRESL          ;bank 1
    movfw   ADRESL
    banksel PORTA           ;bank 0
    movwf   ACCbLO
    clrf    ACCaHI
    movlw   0x0a
    movwf   ACCaLO
    call    D_divS
    movfw   ACCbLO
    movwf   cont_timer
    movwf   L_byte
    clrf    H_byte
    call    B2_BCD
    call        desp_cur_iz
    call        desp_cur_iz
    call        desp_cur_iz
    swapf       R2,W
    andlw       0x0f
    iorlw       0x30
    call        escribir
    call        desp_cur_der
    movfw       R2
    andlw       0x0f
    iorlw       0x30
    call        escribir
    goto    loop
;*******************************************
;Subrutinas
;*******************************************
;subrutina de divicion
;*******************************************************************
;SIGNED  equ     FALSE           Set This To 'TRUE' if the routines
;                               ; for Multiplication & Division needs
;                               ; to be assembled as Signed Integer
;                               ; Routines. If 'FALSE' the above two
;                               ; routines ( D_mpy & D_div ) use
;                               ; unsigned arithmetic.
;*******************************************************************
;       Double Precision Divide ( 16/16 -> 16 )
;       ( ACCb/ACCa -> ACCb with remainder in ACCc ) : 16 bit output
; with Quotiont in ACCb (ACCbHI,ACCbLO) and Remainder in ACCc (ACCcHI,ACCcLO).
;   NOTE  :  Before calling this routine, the user should make sure that
;            the Numerator(ACCb) is greater than Denominator(ACCa). If
;            the case is not true, the user should scale either Numerator
;            or Denominator or both such that Numerator is greater than
;            the Denominator.
;********************************************************************
D_divS
    IF   SIGNED
    CALL    S_SIGN
    ENDIF
    call    setup
    clrf    ACCcHI
    clrf    ACCcLO
dloop
    bcf     STATUS,C
    rlf     ACCdLO, F
    rlf     ACCdHI, F
    rlf     ACCcLO, F
    rlf     ACCcHI, F
    movf    ACCaHI,W
    subwf   ACCcHI,W          ;check if a>c
    btfss   STATUS,Z
    goto    nochk
    movf    ACCaLO,W
    subwf   ACCcLO,W        ;if msb equal then check lsb
nochk
    btfss   STATUS,C    ;carry set if c>a
    goto    nogo
    movf    ACCaLO,W        ;c-a into c
    subwf   ACCcLO, F
    btfss   STATUS,C
    decf    ACCcHI, F
    movf    ACCaHI,W
    subwf   ACCcHI, F
    bsf     STATUS,C    ;shift a 1 into b (result)
nogo
    rlf     ACCbLO, F
    rlf     ACCbHI, F
    decfsz  temp, F         ;loop untill all bits checked
    goto    dloop
    IF    SIGNED
    btfss   sign,MSB        ; check sign if negative
    retlw   0
    goto    neg_B          ; negate ACCa ( -ACCa -> ACCa )
    ELSE
    retlw   0
    ENDIF
;*******************************************************************
setup
    movlw   .16             ; for 16 shifts
    movwf   temp
    movf    ACCbHI,W          ;move ACCb to ACCd
    movwf   ACCdHI
    movf    ACCbLO,W
    movwf   ACCdLO
    clrf    ACCbHI
    clrf    ACCbLO
    retlw   0
;*******************************************************************
neg_A
    comf    ACCaLO, F       ; negate ACCa ( -ACCa -> ACCa )
    incf    ACCaLO, F
    btfsc   STATUS,Z
    decf    ACCaHI, F
    comf    ACCaHI, F
    retlw   0
;*******************************************************************
;  Assemble this section only if Signed Arithmetic Needed
    IF    SIGNED
S_SIGN
    movf    ACCaHI,W
    xorwf   ACCbHI,W
    movwf   sign
    btfss   ACCbHI,MSB        ; if MSB set go & negate ACCb
    goto    chek_A
    comf    ACCbLO          ; negate ACCb
    incf    ACCbLO
    btfsc   STATUS,Z
    decf    ACCbHI
    comf    ACCbHI
chek_A
    btfss   ACCaHI,MSB        ; if MSB set go & negate ACCa
    retlw   0
    goto    neg_A
    ENDIF
;********************************************************************
;                  Binary To BCD Conversion Routine
;      This routine converts a 16 Bit binary Number to a 5 Digit
; BCD Number. This routine is useful since PIC16C55 & PIC16C57
; have  two 8 bit ports and one 4 bit port ( total of 5 BCD digits)
;       The 16 bit binary number is input in locations H_byte and
; L_byte with the high byte in H_byte.
;       The 5 digit BCD number is returned in R0, R1 and R2 with R0
; containing the MSD in its right most nibble.
;*******************************************************************;
B2_BCD
    bcf     STATUS,0                ; clear the carry bit
    movlw   .16
    movwf   count
    clrf    R0
    clrf    R1
    clrf    R2
loop16
    rlf     L_byte, F
    rlf     H_byte, F
    rlf     R2, F
    rlf     R1, F
    rlf     R0, F
    decfsz  count, F
    goto    adjDEC
    RETLW   0
adjDEC
    movlw   R2
    movwf   FSR
    call    adjBCD
    movlw   R1
    movwf   FSR
    call    adjBCD
    movlw   R0
    movwf   FSR
    call    adjBCD
    goto    loop16
adjBCD
    movlw   3
    addwf   0,W
    movwf   temp
    btfsc   temp,3          ; test if result > 7
    movwf   0
    movlw   30
    addwf   0,W
    movwf   temp
    btfsc   temp,7          ; test if result > 7
    movwf   0               ; save as MSD
    RETLW   0
;**************************************************************
; Libreria de subrutinas para el manejo de LCD alfanumerico
;**************************************************************
;                Retardo de 10ms para el LCD (Frec xtal=4MHz)
;Se deben configurar manualmente los puertos para que seran
;utilizados para el LCD
;**************************************************************
;cblock
;PDel0
;PDel1
;endc
;#define        lcd PORTB
;#define        rs PORTA,3
;#define        en PORTA,0
;*******************************************************
retardo     movlw     .15                        ;.8
            movwf     PDel0
PLoop1      movlw     .249
            movwf     PDel1
PLoop2      clrwdt
            clrwdt
            decfsz    PDel1, 1
            goto      PLoop2
            decfsz    PDel0,  1
            goto      PLoop1
PDelL1      goto       PDelL2
PDelL2      clrwdt
            return
;*******************************************************************
;            Habilita el regisyro de control del LCD
;*******************************************************************
comando
            bcf     rs
            movwf     lcd
            bsf     en
            nop
            nop
            bcf     en
            call     retardo
            return
;*******************************************************************
; Habilita el registro de datos del LCD requiere dato en w
;*******************************************************************
escribir
            bsf     rs
            movwf     lcd
            bsf     en
            nop
            nop
            bcf     en
            call     retardo
            return
;*******************************************************************
;            Comandos para el LCD
;*******************************************************************
limpiar_lcd
            movlw    b'00000001'
            call    comando
            return
;*******************************************************************
cursor_home
            movlw    b'00000010'
            call    comando
            return
;*******************************************************************
;            Modo de funcionamiento
;*******************************************************************
;    desplazamiento de cursor a la izquierda, lcd permanese quieto
;*******************************************************************
c_iz_quieto
            movlw    b'00000100'
            call    comando
            return
;********************************************************************
;    desplazamiento de cursor a la izquierda, lcd se desplaza
;********************************************************************
c_iz_desplaza
            movlw    b'00000101'
            call    comando
            return
;********************************************************************
;    desplazamiento de cursor a la derecha, lcd permanese quieto
;********************************************************************
c_der_quieto
            movlw    b'00000110'
            call    comando
            return
;********************************************************************
;    desplazamiento de cursor a la derecha, lcd permanese quieto
;********************************************************************
c_der_desplaza
            movlw    b'00000111'
            call    comando
            return
;********************************************************************
;            Comtrol ON/OFF
;********************************************************************
;No se visualiza datos, el cursor no se ve, cursor no parpadea
;********************************************************************
no_visual_no_cur_no_parpadeo
            movlw    b'00001000'
            call    comando
            return
;********************************************************************
;No se visualiza datos, el cursor no se ve, cursor parpadea
;********************************************************************
no_visual_no_cur_si_parpadeo
            movlw    b'00001001'
            call    comando
            return
;********************************************************************
;No se visualiza datos, el cursor se ve, cursor no parpadea
;********************************************************************
no_visual_si_cur_no_parpadeo
            movlw    b'00001010'
            call    comando
            return
;********************************************************************
;No se visualiza datos, el cursor se ve, cursor parpadea
;********************************************************************
no_visual_si_cur_si_parpadeo
            movlw    b'00001011'
            call    comando
            return
;********************************************************************
; Se visualiza datos, el cursor no se ve, cursor no parpadea
;********************************************************************
si_visual_no_cur_no_parpadeo
            movlw    b'00001100'
            call    comando
            return
;********************************************************************
; Se visualiza datos, el cursor no se ve, cursor parpadea
;********************************************************************
si_visual_no_cur_si_parpadeo
            movlw    b'00001101'
            call    comando
            return
;********************************************************************
;Se visualiza datos, el cursor se ve, cursor no parpadea
;********************************************************************
si_visual_si_cur_no_parpadeo
            movlw    b'00001110'
            call    comando
            return
;********************************************************************
;Se visualiza datos, el cursor se ve, cursor parpadea
;********************************************************************
si_visual_si_cur_si_parpadeo
            movlw    b'00001111'
            call    comando
            return
;********************************************************************
;    Desplazamienro de cursor/LCD
;********************************************************************
;    Se desplaza el cursor a la izquierda
;********************************************************************
desp_cur_iz
            movlw    b'00010000'
            call    comando
            return
;********************************************************************
;    Se desplaza el cursor a la derecha
;********************************************************************
desp_cur_der
            movlw    b'00010100'
            call    comando
            return
;********************************************************************
;    Se desplaza el LCD a la izquierda
;********************************************************************
desp_lcd_iz
            movlw    b'00011000'
            call    comando
            return
;********************************************************************
;    Se desplaza el LCD a la derecha
;********************************************************************
desp_lcd_der
            movlw    b'00011100'
            call    comando
            return
;********************************************************************
;                Transferencia de Informacion
;********************************************************************
;    Bus en modo de 4 y 8 bits
;********************************************************************
bus_4_bits
            movlw    b'00101000'
            call    comando
            return
;********************************************************************
bus_8_bits
            movlw    b'00111000'
            call    comando
            return
;*********************************************************************
;Acceso a la CGRam(cargar en w la direccion,64 direciones,8 caracteres)
;*********************************************************************
cg_ram
            iorlw    b'01000000'
            call     comando
            return
;*********************************************************************
; Acceso a la DDRam(cargar en w la direccion, 40 caracteres por linea)
;*********************************************************************
dd_ram_linea_1
            iorlw    b'10000000'
            call    comando
            return
;*********************************************************************
dd_ram_linea_2
            iorlw    b'11000000'
            call    comando
            return
;********************************************************************
;        Escribir un mensage el el LCD
;********************************************************************
;cblock
;n_lcd            ;contador de caracteres
;endc
;***********************************************************************
esc_mensaje
            clrf        n_lcd
            incf        PCLATH
lcd_0
            movfw         n_lcd
            call        men_0
            xorlw         0
            btfsc         STATUS,Z
            goto        lcd_1
            call         escribir
            incf         n_lcd
            goto         lcd_0
lcd_1
            return
;***************************************************
men_0
            addwf    PCL,F
            dt    "Disparo a: . ms.",0
;***************************************************
    end
te correspode agregarle el TRIAC y demas cosas que falten.
 

Adjuntos

  • Dibujo.JPG
    Dibujo.JPG
    172.8 KB · Visitas: 12
  • lcd_triac.rar
    181.9 KB · Visitas: 12
buenas a todos compañeros, me encuentro realizando la depuracion del siguiente codigo y me he encontrado con algo un tanto extraño... y es que la interrupcion por medio del temporizador no esta ocurriendol, he revisado el codigo y encuanto a configuraciones todo esta bien realmente no lo entiendo.. puedo ver que esta fallando porque cuando carga el valor al TMR0 de 50, lo veo en los registros que carga a "50" y luego empieza a incrementarse hasta que se desborda y regresa a la rutina de interrupcion pero esto no ocurre, simplemente sigue y sigue

254, 255, 0, 1, 2, 3 .... hasta llega un momento donde cambia de signo :confused:,
estoy censando cuando se mete en la rutina de interrupcion, verificando las intrucciones que se estan ejecutando.

estoy usando el PBP, y lo estoy depurando en PROTEUS

Código:
;CONFIGURACION DEL LCD
DEFINE LCD_DREG PORTD 
DEFINE LCD_BITS 4 
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTC 
DEFINE LCD_RSBIT 0 
DEFINE LCD_EREG PORTC 
DEFINE LCD_EBIT 1 
X VAR BYTE
CONT VAR BYTE
AUX VAR BYTE
A var byte
;CONFIGURACIONES DE LOS PUERTOS E/S
TRISB = %00000001  
TRISD = 0
TRISC = 0
;HABILITO LAS INTERRUPCIONES, POR RB0 Y POR TMR0
INTCON = %10110000
on interrupt goto INTERRUPCION
Symbol INTF = INTCON.1
SYMBOL GIE = INTCON.7
SYMBOL TMR0IF = INTCON.2
SYMBOL TOCS = OPTION_REG.5
SYMBOL INTEDG = OPTION_REG.6
X=0
;CONFIGURACION PARA CONVERSOR A/D
ADCON0 = %11000001
ADCON1 = %00001110
;RUTINA DEL LCD
lcdout $fe,1

BUCLE:
adcin 0, A
X = (((47)*A)-(175))/100 
LCDOUT $fe,2,"Disparo a "
lcdout $fe,$c0, "  ",dec X , "  "
goto BUCLE

;RUTINA DE INTERRUPCION
INTERRUPCION:
DISABLE
PORTB.3 = 1
if INTF = 1 THEN INT_EXT ;5 us
IF TMR0IF = 1 THEN INT_TIMER ; 5 us
;INTERRUPCION POR TEMPORIZADO
INT_TIMER:
TMR0IF = 0 ;1 us
IF PORTB.1 = 1 THEN ;10 us
	TOCS = 1
	PORTB.1 = 0 
endif
IF x-1=0 THEN PORTB.1 = 1 ;44us
TMR0 = 100 ; 2 us
GOTO SALIDA_INT ;5 us
;INTERRUPCION POR CRUCE POR CERO
INT_EXT:
INTF = 0 ; 1 us
TMR0 = 50 ; 2 us ; 23.132 ms
SELECT CASE INTEDG ; 0 us
CASE 0 ; 21 us 
INTEDG = 1 ; 3 us
CASE 1 ; 21 us
INTEDG = 0 ; 3 us
END SELECT
TOCS = 0 ; 3 us  23.157 ms 
CONT=X ; 2 us
;FIN DE LA RUTINA DE INTERRUPCION
SALIDA_INT:
GIE = 1 ; 1 us
ENABLE
RESUME
END
 
marconikov dijo:
Buenas a todos compañeros.
Me encuentro realizando la depuración del siguiente código y me he encontrado con algo un tanto extraño, y es que la interrupción por medio del temporizador no está ocurriendo, he revisado el código y en cuanto a configuraciones todo esta bien realmente no lo entiendo.. puedo ver que esta fallando porque cuando carga el valor al TMR0 de 50, lo veo en los registros que carga a "50" y luego empieza a incrementarse hasta que se desborda y regresa a la rutina de interrupción pero esto no ocurre, simplemente sigue y sigue

254, 255, 0, 1, 2, 3 .... Hasta llega un momento donde cambia de signo :confused:,
estoy censando cuando se mete en la rutina de interrupción, verificando las instrucciones que se están ejecutando.

Estoy usando el PBP, y lo estoy depurando en PROTEUS
No mencionas que tipo de PIC estás usando, pero al parecer es un PIC16F877/A :confused:
Tampoco veo que estés definiendo la velocidad de reloj y por defecto serán 4MHz.

Por lo que no debe estar trabajando bien tu rutina de interrupción es porque no estás configurando el prescaler.
Por defecto el valor del prescaler para el TMR0 es de 1:256 si el bit PSA estuviera en 0, pero al estar en 1 queda asignado al Watch Dog Timer, o sea, el registro OPTION_REG se encuentra siempre en 0xFF.

Configura el registro OPTION_REG, por ejemplo con este valor: %10000000
Así tendrás el prescaler a 1:2 y asignado al TMR0.

Si necesitas otro tipo de valor en el prescaler, ve el registro OPTION_REG en la hoja de datos.

Nota:
Preferentemente también pon en 1 el bit 6 (PEIE: Peripheral Interrupt Enable bit) del registro INTCON.
Para depurar mejor el programa en proteus debes usar PBP3 para que te genere el archivo *.cof.

Suerte.
 
estoy consciente de lo del preescaler de hecho asi como esta funciona tal como necesito, con cada ciclo de instruccion este se incrementa en uno. por cierto tienes razon se me olvido decir el pic y lo demas, es tal como dijiste arriba compañero
 
bueno en una parte lo que pasa es que esta sucediendo algo extraño.. en Picabasic pro esta la sentencia "ON INTERRUPT GOTO <LABEL>" que se supone es adonde tiene que ir SIEMPRE que ocurra una interrupcion no? el problema esta en que cuando cargo el tmr0 y este se desborda, NO va a esa LABEL (se cambia el bit y todo del intcon) sino que sigue en el programa :S es demasiado raro y en serio no se que hacer, ya verifique las configuraciones y lo corri con el mplab paso a paso y ocurre lo mismo
 
marconikov dijo:
bueno en una parte lo que pasa es que esta sucediendo algo extraño.. en Picabasic pro esta la sentencia "ON INTERRUPT GOTO <LABEL>" que se supone es adonde tiene que ir SIEMPRE que ocurra una interrupción no? el problema esta en que cuando cargo el tmr0 y este se desborda, NO va a esa LABEL (se cambia el bit y todo del intcon) sino que sigue en el programa :S es demasiado raro y en serio no se que hacer, ya verifique las configuraciones y lo corrí con el mplab paso a paso y ocurre lo mismo
Sip, cuando se desborda el TMR0 el programa debe entrar en la rutina de control de la interrupción.
La única forma que tengo para que veas que sucede con el programa es mostrándote un vídeo.
Mira las secuencias y ve viendo el valor de TMR0 para que notes como entra y sale de la interrupción.

El programa fue compilado usando PBP3 y usé el archivo *.cof generado para usarlo en proteus.

Nota:
Ve el vídeo con la pantalla maximizada para que notes mejor los detalles.
 

Adjuntos

  • Debug.rar
    743 KB · Visitas: 2
vaya hermano con ese programa se ve que es mas viable depurar el programa, ese pbp3 trate de descargarlo pero solo sonsigo la version de prueba de 15 dias, el programa deberia hacer lo siguiente:
Arranca el proteus
- detectar un cruce por cero por RB0, en ese instante ocurre una interrupcion mientras se ejecuta el programa.
- en la rutina de la interrupcion externa se carga por primera vez el tmr0 con ese valor, la idea es que el programa se interrumpa cada 100 us para verificar si RB1 esta activo
- cuando este activo rb1, se pone tocs = 1 con ese deberia detenerse el timer0, para ello la configuracion inicial del option reg es 11111111

te adjunto el archivo de proteus

Estuve realizando la corrida paso a paso con el PBP3 y el proteus y si te das cuenta ocurre el problema que te mencione, si pones un breakpoint al inicio de la interrupcion este no entra cuando se desborda el timer0, es mas aun cuando el registro INTCON cambia sus bit GIE Y TOIF no entra en la rutina "INTERRUPCION" .. :S no entiendo..
 

Adjuntos

  • Nuevo Archivo WinRAR.rar
    18 KB · Visitas: 2
marconikov dijo:
- en la rutina de la interrupción externa se carga por primera vez el tmr0 con ese valor.
La idea es que el programa se interrumpa cada 100 us para verificar si RB1 esta activo
Deberías unicamente comprobar la interrupción por RB0 y posteriormente usar el TMR0.

Mira este programa Dimmer (realizado por @dinoelectro)
Está escrito en C, pero lo podrás entender fácilmente.
Es muy parecido a lo que intentas realizar, únicamente tendrías que poner las rutinas para el LCD.
 
En realidad no manejor mucho (nada..) el C, aunque he pensando en cambiarme, pero quisiera intentar ver cual es el problema del codigo en basic de hecho he indagado en busca de la falla y mira lo que he conseguido, lo pongo segun la secuencia de imagenes:
1-inicio la corrida de programa
2-establezco la interrupcion externa mediante el stimulus y se me abre una pequeña ventana de instruccion en assembler referente a interrupciones
3-ejecuta las instrucciones de la rutina de interrupcion, y carga el timer0 haciendo que este empiece a correr.
4- mientras ejecuta las intrucciones veo que entra en ese ciclo de instrucciones que se refiere a unas instrucciones del programa principal, ya el timer0 esta apunto de desbordarse.
5- fijense que el timer0 se desborda y abre otra vez la ventana referente a interrupciones en assembler.
6- -.- se regresa al programa principal y se olvida de pasar por la rutina de interrupciones.

en lo personal CREO que el problema es las instrucciones de assembler de la interrupcion, pero la verdad es que no se que pueda hacer para solventar eso, si alguien pudiera echarme una mano se lo agradeceria
 

Adjuntos

  • 1.jpg
    1.jpg
    73.5 KB · Visitas: 5
  • 2.jpg
    2.jpg
    74.5 KB · Visitas: 6
  • 3.jpg
    3.jpg
    73.5 KB · Visitas: 4
  • 4.jpg
    4.jpg
    77.8 KB · Visitas: 6
  • 5.jpg
    5.jpg
    77.6 KB · Visitas: 4
  • 6.jpg
    6.jpg
    79.8 KB · Visitas: 4
1-inicio la corrida de programa
2-establezco la interrupción externa mediante el stimulus y se me abre una pequeña ventana de instrucción en assembler referente a interrupciones
3-ejecuta las instrucciones de la rutina de interrupción, y carga el timer0 haciendo que este empiece a correr.
4- mientras ejecuta las instrucciones veo que entra en ese ciclo de instrucciones que se refiere a unas instrucciones del programa principal, ya el timer0 esta apunto de desbordarse.
5- fíjense que el timer0 se desborda y abre otra vez la ventana referente a interrupciones en assembler.
6- -.- se regresa al programa principal y se olvida de pasar por la rutina de interrupciones.

en lo personal CREO que el problema es las instrucciones de assembler de la interrupción, pero la verdad es que no se que pueda hacer para solventar eso
Realicé un programa sencillo para poder comprobar que sucedía durante el bloque cuando se deben atender 2 o varias interrupciones en PICBasic Pro.

Sucede que, como únicamente se puede utilizar una etiqueta para atender las interrupciones,
si se colocan otras etiquetas dentro del bloque, cualquier otra interrupción que se ejecute podrá pasar por ellas.

Así que, para que se cumplan se deben ejecutar las rutinas dentro de una única sentencia IF
Se tiene que comprobar que flag se activó, limpiarlo y continuación realizar las rutinas correspondientes y cerrar ese bloque.
Así mismo para las otras rutinas del servicio de interrupciones.

Con esto se podrá realizar una cascada de verificación a las interrupciones que se ejecutan.
Si los tiempos de ejecución están coordinados y no se ejecutan al mismo tiempo, así debería funcionar.

Saludos.
 
ah.. poco a poco compañero ! te soy sincero no entendi a lo que te refieres, cuando dices que se puede utilizar una etiqueta para atender las interrupciones, te refieres a la instrucción en assembler ? y otra cuestión esa sentencias de if que dices tengo que hacerlo en los bloques assembler ?? realmente quisiera entender como solventar esto
 
Me refiero al nombre de las subrutinas del programa. (Etiquetas)
Tu programa está escrito en PICBasic Pro y también lo que mencioné es válido para lenguaje ensamblador.
Sin embargo no es necesario que escribas bloques en ensamblador.

Lo que debes hacer, es generar las subrutinas de cada interrupción dentro de bloques IF y cerrarlos.

Por ejemplo, de esta forma:
Código:
Interrupts_ISR:
    Disable
    If INTCON.1 = 1 Then
        INTCON.1 = 0
        ; Código a ejecutar en interrupción por RB0
    EndIf
    
    If INTCON.2 = 1 Then
        INTCON.2 = 0
        ; Código a ejecutar en interrupción por TMR0
    EndIf
    
    Resume
    Enable

¿Ya comprendes como?
 
Ah ok ! si ya entiendo a lo que te refieres, voy a modificar eso y te cuento luego a ver que tal !(y)



Hola compañero, ya hice las modificaciones pertinentes al codigo quedo asi:

Código:
'****************************************************************
'*  Name    : UNTITLED.BAS                                      *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS] *
'*          : All Rights Reserved                               *
'*  Date    : 5/6/2014                                          *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
DEFINE LCD_DREG PORTD 
DEFINE LCD_BITS 4 
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTC 
DEFINE LCD_RSBIT 0 
DEFINE LCD_EREG PORTC 
DEFINE LCD_EBIT 1 
X VAR BYTE
CONT VAR BYTE
AUX VAR BYTE
A var byte
;CONFIGURACIONES DE LOS PUERTOS E/S
TRISB = %00000001  
TRISD = 0
TRISC = 0
;HABILITO LAS INTERRUPCIONES, POR RB0 Y POR TMR0
INTCON = %10110000
OPTION_REG = %11110000
on interrupt goto INTERRUPCION
Symbol INTF = INTCON.1
SYMBOL GIE = INTCON.7
SYMBOL TMR0IF = INTCON.2
SYMBOL TOCS = OPTION_REG.5
SYMBOL INTEDG = OPTION_REG.6
X=0
PORTB = 0
;CONFIGURACION PARA CONVERSOR A/D
ADCON0 = %11000001
ADCON1 = %00001110
;RUTINA DEL LCD

lcdout $fe,1

BUCLE:

adcin 0, A

X = (((47)*A)-(175))/100 
LCDOUT $fe,2,"Disparo a "
lcdout $fe,$c0, "  ",dec X , "  "
goto BUCLE


DISABLE
;RUTINA DE INTERRUPCION 
INTERRUPCION:
PORTB.3 = 1 ;23.135ms

;INTERRUPCION POR CRUCE POR CERO
if INTF = 1 THEN  ;5 us
    INTF = 0 ; 1 us
    TMR0 = 230 ; 2 us ; 
    SELECT CASE INTEDG ; 0 us
    CASE 0 ; 21 us 
    INTEDG = 1 ; 3 us
    CASE 1 ; 21 us
    INTEDG = 0 ; 3 us
    END SELECT
    TOCS = 0 ; 3 us  23.157 ms 
    CONT=X ; 2 us
endif

;INTERRUPCION POR TEMPORIZADO
if TMR0IF = 1 THEN ; 5 us
    TMR0IF = 0 ;1 us
    if PORTB.1 = 1 THEN ;10 us
        TOCS = 1
        PORTB.1 = 0 
    endif
    IF x-1=0 THEN PORTB.1 = 1 ;44us
    TMR0 = 200 ; 2 us
endif

;FIN DE LA RUTINA DE INTERRUPCION
GIE = 1 ; 1 us
RESUME
ENABLE
END
Aún así, hice la corrida en frio con el mplab y sigue el problema compañero :/
Cuando se desborda no se para a la etiqueta y se regresa como te dije anteriormente.
 
Última edición por un moderador:
Atrás
Arriba