Uso del Timer 0 y Timer 1

En proteus armar un circuito en el cual el microcontrolador 16f877 genera por el pin 8 una señal periodica cuyo periodo se muestra en la figura 1.




______|---------|______|------------
T1 T0 T1 T0
6ms 2.5ms 3.5ms 4ms

Quiza alguien tenga alguna sugerencia para poder resolverlo. ...



Esa es la figura en donde se indica el timer con e cual se debe de generar el inetrvalo de tiemp. usar interrucion al termino de cada intervalo.
 
Última edición:
Te tiro una idea, el resto depende de vos:

1- Aprendé a configurar un timer.
2- Aprendé a usar las rutinas de interrupción.

Con 1 y 2, podrías hacer esto

1- Crear una variable de estado global.
2- Inicializar el timer y la variable de estado.
3- Habilitar interrupción.
4- En la rutina de interrupción, leer el valor de la varible estado, cambiar el estado del pin, configurar el nuevo tiempo del timer y llevar la variable de estado a su próximo valor.
5- Al llegar al último estado posible de la "variable de estado", llevarla al estado inicial y repetir el ciclo.
 
Gracias amigo pero como gnero los tiempos?
__________1______|---2---|___3__|------4-----
tramo 1 con TIMER 1 ---->> 6ms
tramo 2 con TIMER 0 ---->> 2.5ms
tramo 3 con TIMER 1 ---->> 3.5ms
tramo 4 con TIMER 0 ----->> 4ms




El calculo de los tiempos es el que me trae dudas, por ejemplo para generar 6ms ? tiene que ver algo con el duty cycle? :unsure::unsure:
 
Última edición:
A ver si este diagrama en bloques te ayuda:

Diagrama en bloques Timer.png

Cuya configuración dependerá del siguiente registro:

Registros Timer.png

¿Qué duda tenés?

Sobre el uso de 2 timers, insisto usá solo uno, te va a resultar más sencillo y encima vas a usar menos recursos en el uC.
 
A que te refieres con VARIABLE DE ESTADO GLOBAL? Gracias amigo

es lo que no entiendo muy bien

¿Qué lenguaje usás para programar, C o assembler?

En "C" una variable global es aquella que puede ser vista por cualquier función.

Y una variable de estado, no es más que una variable común que la usás para determinar el estado en que se encuentra cierta rutina, por ej.:

....
__________1______|---2---|___3__|------4-----
tramo 1 con TIMER 1 ---->> 6ms
tramo 2 con TIMER 0 ---->> 2.5ms
tramo 3 con TIMER 1 ---->> 3.5ms
tramo 4 con TIMER 0 ----->> 4ms

De la señal que publicaste, tenes 4 estados posibles, por lo tanto esa variable que usarías podría ir de 0 a 3 para indicar en que momento de la señal estas y en base a eso, configurás el timer con el tiempo adecuado.

Si usaras assembler, el principio podría ser el mismo.
 
Es en assenbler

Amigo gracias por el dato Aqui tengo algo que hise pero e problema es que no me sale como deberia ser cunado lo similo en proteus

LIST P=16F877A
#INCLUDE <P16F877A.INC>

__CONFIG _CP_OFF & _CPD_OFF & _PWRTE_ON & _LVP_OFF & _BODEN_OFF & _XT_OSC & _WDT_OFF

ERRORLEVEL -302

CBLOCK 0X20
S_STATUS_TMR0
S_STATUS_TMR1
REG

ENDC


ORG 0X00
GOTO INICIO
ORG 0X04
GOTO ISR
ORG 0X05

INICIO
BANKSEL INTCON ;CONFIGURACION TMR0 CON PRESCALER A 1:32
MOVLW B'11000000'
; --0----- DESACTIVA LA INTRRUPCON DEL TMR0
MOVWF INTCON
BANKSEL OPTION_REG
MOVLW B'00110100'
; --1----- DESACTIVA EN TIMER0 EL MODO TEMPORIZADOR
MOVWF OPTION_REG

BANKSEL PIR1 ;CONFIGURACI[ON TMR1 y TMR2 INTERRUPT ENABLE
CLRF PIR1 ;LIMPIA EL FLAG DEL TMR1, Y TMR2
BANKSEL PIE1 ;ACTIVA LA INTERRUPCION DEL TMR1 Y TMR2
MOVLW 0X03
MOVWF PIE1

BANKSEL TRISE
MOVLW 0X00
MOVWF TRISE
BANKSEL PORTE
CLRF PORTE ;CONFIGURA EL PUERTOA
BCF REG,0

INICIO_DE_PULSO
MOVLW 0XE8
MOVWF TMR1H
MOVLW 0XDB
MOVWF TMR1L
BCF PORTE,0
CALL ACTIVA_TMR1

MAIN
GOTO MAIN

ISR
BTFSC INTCON,TMR0IF
GOTO ISR_TMR0_ON ;INTERRUPCI[ON POR TIMER0
BTFSC PIR1,TMR1IF
GOTO ISR_TMR1_ON ;INTERRUPCION POR TIMER1

RETFIE


ISR_TMR0_ON
BTFSS REG,0
GOTO CASO_1
GOTO CASO_3
ISR_TMR1_ON
BTFSS REG,0
GOTO CASO_2
GOTO CASO_4


CASO_1 ;TIEMPO DE 6mS
CALL DESACTIVA_TMR0
MOVLW 0XE8 ;CARGAMOS EL VALOR E8DB EN EL TIMER1
MOVWF TMR1H
MOVLW 0XC1
MOVWF TMR1L
BCF PORTE,0
CALL ACTIVA_TMR1
BCF INTCON,TMR0IF
RETFIE

CASO_2 ;TIEMPO DE 2.5mS
INCF REG,F
CALL DESACTIVA_TMR1
MOVLW 0XB3 ;CARGAMOS EL VALOR B1 EN EL TIMER0
MOVWF TMR0
NOP
BSF PORTE,0 ; NOP COMPLETA EL TIEMPO FALTANTE(1uS)
CALL ACTIVA_TMR0
BCF PIR1,TMR1IF
RETFIE

CASO_3 ;TIEMPO DE 3.5mS
CALL DESACTIVA_TMR0
BCF PORTE,0
MOVLW 0XF2 ;CARGAMOS EL VALOR F253 EN EL TIMER1
MOVWF TMR1H
MOVLW 0X86
MOVWF TMR1L
CALL ACTIVA_TMR1
BCF INTCON,TMR0IF
RETFIE

CASO_4 ;TIEMPO DE 4mS
DECF REG,F
CALL DESACTIVA_TMR1

NOP ; LOS NOP, COMPENSAN EL TIEMPO FALTANTE (6uS)
NOP
NOP
NOP
NOP
NOP

BSF PORTE,0
MOVLW 0X84 ;CARGAMOS EL VALOR 82 EN EL TIMER0
MOVWF TMR0

CALL ACTIVA_TMR0
BCF PIR1,TMR1IF
RETFIE



ACTIVA_TMR0
MOVF STATUS,W
MOVWF S_STATUS_TMR0
BANKSEL OPTION_REG
MOVLW B'00010100'
; --0----- ACTIVA EN TIMER0 EL MODO TEMPORIZADOR
MOVWF OPTION_REG
BANKSEL INTCON ;CONFIGURACION TMR0 CON PRESCALER A 1:32
MOVLW B'11100000' ; LIMPIA EL FLAGDE INTERRUPCION
; --1----- ACTIVA LA INTRRUPCON DEL TMR0
MOVWF INTCON
MOVF S_STATUS_TMR0,W
MOVWF STATUS
RETURN

DESACTIVA_TMR0
MOVF STATUS,W
MOVWF S_STATUS_TMR0
BANKSEL INTCON ;CONFIGURACION TMR0 CON PRESCALER A 1:32
MOVLW B'11000000' ; LIMPIA EL FLAGDE INTERRUPCION
; --0----- DESACTIVA LA INTRRUPCON DEL TMR0
MOVWF INTCON

MOVF S_STATUS_TMR0,W
MOVWF STATUS
RETURN

ACTIVA_TMR1
MOVF STATUS,W
MOVWF S_STATUS_TMR1
BANKSEL PIR1
CLRF PIR1 ;LIMPIA EL FLAG DE INTERRUPCION
BANKSEL PIE1
MOVLW 0X01
MOVWF PIE1 ;ACTIVA LA INTERRUPCION
BANKSEL T1CON
MOVLW B'00000001' ;INICIA CONTEO EN TMR_1
MOVWF T1CON

MOVF S_STATUS_TMR1,W
MOVWF STATUS
RETURN

DESACTIVA_TMR1
MOVF STATUS,W
MOVWF S_STATUS_TMR1
BANKSEL PIE1
CLRF PIE1 ;DESACTIVA LA INTERRUPCION
BANKSEL T1CON
MOVLW B'00000000' ;APAGA EL CONTEO DEL TMR_1
MOVWF T1CON

MOVF S_STATUS_TMR1,W
MOVWF STATUS
RETURN




END



Ver el archivo adjunto PRACTICA_4_MARTES.rar

Gracias de antemano.
 
Última edición:
Mirá estoy oxidado con assembler y encima aplicado a una familia de uC que nunca usé, pero te puedo dar esta idea de como lo haría yo:

PHP:
....//Librerías necesarias y salto inicial

rutina_inicial:
  ... //Inicialización de los puertos  
  ... //Inicialización del timer a utilizar, ej Timer0
  ... //Inicialización de las interrupciones, registros necesarios para habilitar una determinada interrupción
  
  mov reg,0   //Inicializo un registro con el estado "0" 
  push reg     // Mediante el registro, guardo el estado en el stack

  Loop_principal:
    ... //Se recomiendaría dejar el uC en modo sleep, con alguna instrucción/registro
  jmp Loop_principal


timer_0_isr:
  ... //Limpio la interrupción si es necesario hacerlo
  
  pop reg //Usando el stack, obtengo el estado actual

  cmp reg,0 //Empiezo a comparar el registro con los estados posibles
  jz ESTADO_0
  
  cmp reg,1 //Empiezo a comparar el registro con los estados posibles
  jz ESTADO_1
  
  cmp reg,2 //Empiezo a comparar el registro con los estados posibles
  jz ESTADO_2

  cmp reg,3 //Empiezo a comparar el registro con los estados posibles
  jz ESTADO_3

  ESTADO_0:
    ...//Configuro el próximo tiempo del timer
    ...//Configuro la salida del puerto
    mov reg,1  //Valor del próximo estado
    push reg   //Dejo el valor del próximo estado en el stack
    jmp salir_timer0_isr 
  
  .... //repito la rutina para c/estado

 ESTADO_3:
    ...//Configuro el próximo tiempo del timer
    ...//Configuro la salida del puerto
    mov reg,0  //Listo para empiezar el ciclo de nuevo 
    push reg   //Dejo el valor del próximo estado en el stack
    jmp salir_timer0_isr 
  
  salir_timer0_isr:
    iret

Como no conozco bien el PIC, se me ocurrió usar el Stack para saber en que estado se encuentra la señal que necesitas enviar, pero podrías usar otras alternativas:

1- Usar directamente los registros, esto dependerá si el uC los limpia o no cuando entra en una rutina de interrupción, de no hacerlo, simplemente podés usar regsitros, la ejecución será más eficaz.

2- Usar una variable alojada en RAM, es la solución menos optimizada, pero es aplicable.
 
Última edición:
Atrás
Arriba