TODOPIC
Microcontroladores PIC => Almacén del Assembler => Mensaje iniciado por: MAT en 22 de Junio de 2006, 12:14:56
-
Hola amigos le comento que estoy ahciendo un frecuencimetro y ya tengo en marcha el contador de 6 digito que estoy usando para visualisar la frecuencia con el micro y tengo timer externo que manda un pulsoen alto para habilitar la cuenta del pic duarante 100 mseg ahora mi pregunta esto se puede hacer dentrodel mismo micro para evita en timer externo
agradeceria su ayuda garacia marcos 73
-
Hola marcos. El 16F84 trae un timer interno, que puede facilitar tu tarea de crear pasos de 100ms.A la info de como utilizar este timer la puedes encontrar o bien en el datasheet de este PIC o bien en este foro en el cual se ha hablado infinidad de veces del 16F84 y del timer0. Proba con el buscador del foro.
Saludos.
-
Hola Bruno F
Bueno te comento que ya encontre la falla es que estaba declarando el preselector en el wdt y no en el tmr0 para usarlo como contador de pulsos externos, bueno ahora me faltaria saber como calcular el tiempo para logra que cuente en 100 mseg, y otra cosa veo que cuando le inyecto frecuencia me cuenta y eso esta bien perolo que no entiendo es que al subir la frecuencia me decrementa la cuenta en ves de incrementarla no se si estoy haciendo algo mal o trabaja asi el tmr0, bueno aca te paso algo del codigo para que lo veas
bcf status, 5
movlw b'10100111'
movwf tmr0
............
bsf status, 5
.
.....
.....
....
.....
clrf trm0
inc:
call subir ; rutana de incremento en digito para visualisar el display
btfss intcon, 2
goto inc
bsf intcon, 2
....
....
Rutina de visualizacíon
Bueno eso es lo que tengo echo y esta funcionado mal pero en fin funca ahora me queda eso de ver asi que si me puedes dar una mano con el tema te lo agradeceria mucho saludos
Marcos 73
-
Hola. Bueno, el tiempo que tarda el timer en desbordar depende de la frecuencia de oscilacion en la cual estes haciendo trabajar al PIC. Supongo que utilizas 4 Mhz.
La formula de maxima duracion del Timer seria: (4/FOSC)* 256(tmr0)*256(prescaler rate)
Suponiendo que trabajas a 4mhz, entonces nos quedaria: (4/4000000) * 256 *256 = 0,000001s*256*256 = 1us * 256*256= 0.001ms * 256*256 = 65,536ms
Este es el maximo tiempo que el modulo Timer0 puede contar @4Mhz.
Ahora, para lograr valores de tiempo mayores(como en tu caso 100ms) hay que utilizar registros auxiliares, que debes crear tu para que vayan contando cada vez que se desborde el timer, y que generen la rutina correspondiente cuando el timer se ha desbordado X cantidad de veces.
Bien, como 100ms no es un multiplo entero de 65,536ms, nos convendria acomodar el tiempo que tarda en desbordar a tiempos multiplos de 100ms. Por lo que podemos aprovechar la opcion que nos brinda el PIC, de modificar el valor inicial del registro TMR0.
Voy a buscar un divisor perfecto de 100ms: que el timer cuente 50ms. Como 50ms es bastante cercano a 65,536, es facil darse cuenta que debemos setear el prescaler a su valor maximo( 256).Ahora buscaremos el valor que debemos escribir en el registro TMR0 para obtener los 50ms.
De esta forma, la misma formula anterior toma la siguiente forma: (4/FOSC)* (256-TMR0)*256
Reemplazando obtenemos: (4/4000000)* (256-TMR0)*256 = 0,001ms*(256-TMR0)*256= 50ms
Haciendo pasaje de terminos:
(256-TMR0)*256= 50ms/0,001ms
(256-TMR0)= 50ms/(0.001ms*256)
-TMR0 = (50ms/(0.001ms*256))-256
TMR0= -(50ms/(0.001ms*256))+256
TMR0= 60,68
Hemos encontrado el valor que debemos escribir en el registro TMR0 para obtener un timer de 50ms.
Como no podemos poner un valor decimal en el registro TMR0, debemos redondear a un valor entero el numero encontrado.
Yo voy a redondear hacia arriba el 60,68, obteniendo 61.
Podemos comprobar que nuestros calculos han sido correctos volviendo a plantear la formula con el valor encontrado:
(4/4000000)* (256-TMR0)*256 = 0,001ms*(256-TMR0)*256 = 0.001ms*(256-61)*256 = 0.001ms*195*256=49.92ms
El valor obtenido es suficiente, muy cercano a los 50ms.
Ahora solo debemos utilizar una variable auxiliar que cuente 2 veces que se desborde el Timer(2 veces * 49.92ms = 99.84ms(practicamente 100ms))
En el programa podes setear el timer asi:
bsf STATUS,5
movlw b'11010111'
movwf OPTION_REG
bcf STATUS,5
movlw .61
movwf TMR0
clrf CONTADOR ;defini esta variable para que cuente la cantidad de desbordamientos del timer.
....
inc:
call subir ; rutana de incremento en digito para visualisar el display
btfss intcon, 2
goto inc
bcf intcon, 2 <-Ojo! hay que limpiar el flag de interrupcion! no volver a setearlo
movlw .61
movwf TMR0 ;volver a setear valor inicial del registro TMR0
incf CONTADOR,F
movf CONTADOR,W
xorlw .2 ;se ha desbordado por segunda vez? 2 veces = 2*50 ms = 100ms
btfss STATUS,Z
goto inc ;todavia no se ha desbordado dos veces, volver a esperar.
clrf CONTADOR ;reiniciar contador de desbordamientos
....
....
Rutina de visualizacíon
goto inc
El timer se desborda cuando el registro TMR0 pasa de valer 0xFF a 0x00. Es decir que el registro TMR se incrementa, y al producirse del desbordamiento, produce el seteo del flag correspondiente. Por lo tanto, el registro timer cero se incrementa, nunca se decrementa automaticamente.
Espero haya quedado claro.
Exitos!
-
Bueno, me he fijado en tu programa, y como no se que es lo que queres hacer, puede que el programa se comporte erroneamente. Es cuestion de acomodar las rutinas. Si queres que el el valor mostrado en los displays se incremente cada 100ms y mientras tanto que se refresquen los displays(que seguramente tenes multiplexados) tenes que intercambiar de lugar las rutinas "subir" y la rutina de visualizacion.
Saludos
-
Hola, gracias por ayudarme con los calculos de tiempo para el TMR0
Bueno mira el proyecto se trata de un frecuencimetro para medir hasta 40 mhz con el 16F84 y esta funcionado pero me cuenta al reves es decir yo inyecto en el pin RA4 una frecuencia de 4 Mhz , me visualisa 3 Mhz y si yo subo la frecuencia de entrada en el pin RA4 la que me visualisa va bajando por ej 5 Mhz, muestra 2 Mhz y haci sucesivamente y no puedo sacar la falla, si bien en este foro mas abajo pregunte por el frecuencimetro y me ayudaron , ahora me queda eso por terminar para que funciones bien, bueno aca te mando el programa para que lo veas y me puedas ayudar desde ya te comento que se trata de un contador de 6 digitos en el cual necesito mostrar los pulsos contador durante 100 mseg
List P = 16f84
Include <P16f84.inc>
__config _XT_OSC & _PWRTE_ON & _WDT_OFF & _CP_OFF
indo equ 00h ;registro de indireccion
pc equ 02h ;contador de programa
status equ 03h ;registro de estado
fsr equ 04h ;registro de seleccion
intcon equ 0bh
tmr0 equ 01h
ptoa equ 05h ;puerto a
ptob equ 06h ;puerto b
rota equ 2fh ;variable para desplazamiento de display
trisa equ 85h ;configuracion puerto a
trisb equ 86h ;configuracion puerto b
dig2 equ d'12' ;acumulador cent. mil
dig3 equ d'13' ;acumulador dec. mil
dig4 equ d'14' ;acumulador unid. mil
dig5 equ d'15' ;acumulador centenas
dig6 equ d'16' ;acumulador decenas
dig7 equ d'17' ;acumulador unidades
loops equ 1dh ;variables usadas en retardos
loops2 equ 1eh
ciclo equ 1fh
z equ 02h ;flag de cero
ram equ 05h ;bit de seleccion de pagina de memoria
c equ 00h ;flag de acarreo
w equ 00h ;bit de destino a variable de trabajo
reset org 00
goto inicio
org 05h
retardo ;subrutina de retardo
movwf loops ;la variable de trabajo contiene la cant.
top2 movlw d'110' ;de ms a demorar
movwf loops2
top nop
decfsz loops2 ;controla si termina 1mS
goto top
decfsz loops ;controla si termina el retardo completo
goto top2
retlw 0
x100 ;rutina de incremento x 100000
clrf dig3 ;pone a cero las decena de miles
incf dig2 ;incrementa el contador de centenas de miles
movf dig2, w ;carga en work el conteo de las centenas de miles
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
clrf dig2 ;inicializa lascentenas de miles
return
x10 ;rutina de incremento x 10000
clrf dig4 ;pone a cero las unidades de mil
incf dig3 ;incrementa el contador de decenas de mil
movf dig3, w ;carga en work el conteo de las decenas miles
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
call x100 ;incrementa las centenas de mil
return
x1 ;rutina de incremento x 1000
clrf dig5 ;pone a cero las centena
incf dig4 ;incrementa el contador de unidad miles
movf dig4, w ;carga en work el conteo de las unidades miles
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
call x10 ;incrementa los decenas miles
return
s100 ;rutina de incremento x 100
clrf dig6 ;pone a cero las decenas
incf dig5 ;incrementa el contador centenas
movf dig5, w ;carga en work el conteo de las centenas
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
call x1 ;incrementa los unidades mil
return
s10 ;rutina de incremento x 10
clrf dig7 ;pone a cero las unidades
incf dig6 ;incrementa el contador de decenas
movf dig6, w ;carga en work el conteo de las decenas
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
call s100 ;incrementa las centenas
return
subir ;rutina de incremento
incf dig7 ;incrementa el contador de unidades
movf dig7, w ;carga en work el conteo de las unidades
xorlw 0ah ;si work era 10, entonces quedara en cero
btfsc status, z ;si es cero, el flag z queda alto
call s10 ;incrementa las decenas
return
tabla ;genera los numeros sobre el display
addwf pc ;agrega al cont. programa el valor de work
retlw b'0000' ;genera el 0
retlw b'0001' ;genera el 1
retlw b'0010' ;genera el 2
retlw b'0011' ;genera el 3
retlw b'0100' ;genera el 4
retlw b'0101' ;genera el 5
retlw b'0110' ;genera el 6
retlw b'0111' ;genera el 7
retlw b'1000' ;genera el 8
retlw b'1001' ;genera el 9
inicio ;programa principal
bsf status, ram ;selecciona el banco de memoria alto
movlw b'10100111'
movwf tmr0
movlw b'00010000' ;configura el puerto a
movwf trisa ;bit 4 entrada, demas bits salidas.
movlw b'11000000' ;configura el puerto b
movwf trisb ;como salidas
bcf status, ram ;selecciona el banco de memoria bajo
empe
clrf dig2
clrf dig3
clrf dig4
clrf dig5
clrf dig6
clrf dig7
movlw 00 ;envia ceros a los transistores para apagar
movwf ptob ;todos los displays
movlw 02h
movwf ciclo
con movlw d'61'
movwf tmr0
inc call subir ;llama la rutina de incremento
btfss intcon, 2
goto inc
bcf intcon, 2
decfsz ciclo
goto con
movlw 0x01 ;iniciar un 1 en el registro de rotacion
movwf rota ;inicializa el display
movlw d'12' ;con el registro selector (fsr) se apunta
movwf fsr ;al primer dato que se va a mostrar
disp movf indo, w ;lee el dato del registro apuntado por fsr
call tabla
movwf ptoa ;envia el digito al puerto b
btfsc rota, 0
bsf ptob, 0
btfsc rota, 1
bsf ptob, 1
btfsc rota, 2
bsf ptob, 2
btfsc rota, 3
bsf ptob, 3
btfsc rota, 4
bsf ptob, 4
btfsc rota, 5
bsf ptob, 5
movlw d'03'
call retardo
clrf ptob
btfsc rota, 5
goto empe ;si termino, vuelve desde el comienzo
bcf status, c ;carry en cero para no afectar las rotaciones
rlf rota ;desplaza el 1 que enciende los displays
incf fsr, 1 ;incrementa el puntero. Apunta el proximo
goto disp ;digito a mostrar ;digito a mostrar
end
bueno saludos 73
-
hola. Aca me cambiaste mucho las pautas.
Entonces vos lo que queres es que el Timer0 en modo CONTADOR, no en MODO TIMER.
Todo lo que yo te explique era para modo timer.En modo timer, el Timer0 solamente cuenta tiempo,pero no pulsos en el pin RA4...
El datasheet aclara que el pulso enviado a RA4 posee ademas un retardo(es decir, que no es perfectamente preciso).
Por eso seguramente lea 3mhz en lugar de 4mhz.
Explicame bien si vos lo que queres es contar la cantidad de pulsos recibidos por el pin RA4 para determinar la frecuencia porque no me queda claro.
Saludos.
-
Hola , bueno si yo quiero contar la cantidad de pulsos para determinar la frecuencia es decir hacer un frecuencimetro
Y ok que lo de tmr0 es para timer no para contador
Bueno espero que me entiendas ahora lo que quiero hacer, te comento que asi funciona pero con el detalle que te comente que a mayor frecuencia es decir pulsos en la entrada menor es la cuenta y a menor pulsos en la entrada mayor es la cuenta ¿por que?.
Bueno espero que me ayas entendido
Saludo 73
-
Hola MAT. Bueno, lo que esta pasando es que cuanto mayor sea la frecuencia que ingreses por el pin RA4, menor va a ser el tiempo que tarda en desbordarse el TIMER. Por eso a > frecuencia < cuenta y viceversa.
Vos necesitas comparar la cantidad de pulsos recibidos durante X cantidad de tiempo. Te hace falta un tiempo de referencia para poder determinar la frecuencia ingresada por el pin RA4.
Esta X cantidad de tiempo dependera del refresh que queres que tenga el frecuenciometro, y de la precision del mismo.
Espero haber entendido tu idea. Saludos.
-
Bueno Bruno, entendido lo que me pasa pero conrespecto a mayor frecuencia menor visaulisacion.
y si esa es mi idea, ahora yo soy el que no entiende como hacer para comparar los pulsos no me doy cuenta, por que hace poco que empese con esto de los pic y bueno de apoco voy aprendiendo , si me podes decir mo arrancar porlomenos te agradeceria , por que no enteindo como hacelo ; esto se puede hacer sobre el mismo programa o no y como te agradeceria si me dices como o me muestras un ejemplo para verlo y entenderlo desde ya muchas gracias Bruno por ayudarme con este tema
Saludo MArcos