TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: echo_ordie en 07 de Octubre de 2018, 23:27:13
-
Hola , estoy trabajando con un PIC18F4550 y necesito usar el TMR1 como un temporizador , ademas necesito poder medir 1 us . Estoy usando un cristal de 4Mhz externo y un FOSC de 48Mhz .Segun lo que he leido con un preescalador de 1:1 deberia ser capaz de medir el us sin embargo. Aqui mi configuracion:
void timer1config(void){
//TMR1 Config Registros
T1CONbits.RD16 = 1;
T1RUN = 0;//Usar reloj interno
TMR1CS = 0; // FOSC / 4
T1CKPS1:T1CKPS0 = 00;
T1OSCEN = 0;
}
void wait_in_us(long time){
long segundos = 0;
TMR1H = 0xff;
TMR1L = 0xf4;
TMR1IF = 0;
TMR1ON = 1;
while(segundos < time){
if(TMR1IF){
TMR1H = 0xff;
TMR1L = 0xf4;
TMR1IF = 0;
segundos ++;
}
}
}
Y aqui mi main :
void main(void) {
configPIC();
timer1config();
while(1){
LED = _ON;
wait_in_us(1000000);
LED = _OFF;
wait_in_us(1000000);
}
}
Mi idea es decirle a la funcion que espere 1000000 de micro segundos es decir 1 segundo , pero cuando mido el tiempo que el Led se enciende estoy midiendo 2.80 s casi 3 s. Si me pueden ayudar con el calculo o si saben si es posible medir micro segundos seria de mucha ayuda.Aclaro que quiero micro segundos porque necesito usar el CCP1 para medir la frecuencia de una señal externa y considero que entre mas presicion tenga el TMR1 , mayores frecuencias podre medir.
-
Hola, es necesario para garantizar la correcta definición de _XTAL_FREQ, para que no tenga problema con la macro de retardos . Asegura también los guiones bajos adecuados, por ejemplo:
#define _XTAL_FREQ 20000000
#include <xc.h>
#include <p18f4550.h>
...
void main(void) {
__delay_us(10);
__delay_ms(10);
}
-
Si te entiendo pero son 2 cosas distintas lo tuyo..
Primero que aca tenes una buena cantidad de instrucciones antes de entrar al while, que no estas contando:
void wait_in_us
(long time){ long segundos = 0;
TMR1H = 0xff;
TMR1L = 0xf4;
TMR1IF = 0;
TMR1ON = 1;
if(TMR1IF){
TMR1H = 0xff;
TMR1L = 0xf4;
TMR1IF = 0;
segundos ++;
}
}
}
Luego en cada overflow tenes otra cantidad. Encima despues de todo lo cargas con 0xFFF4 por lo que los overflow ocurren BASTANTE seguido. Y ese error se multiplica por 1.000.000 de veces que ocurre.
Para lo que estas haciendo te conviene mas usar un delay, que va a ser lo mismo, ya que es bloqueante la funcion.
Aclaro que quiero micro segundos porque necesito usar el CCP1 para medir la frecuencia de una señal externa y considero que entre mas presicion tenga el TMR1 , mayores frecuencias podre medir
Y para este caso lo estarias usando mal... En realidad lo estas encarando mal al problema.
Si quisiera medir la frecuencia, me quedan 2 opciones, la primera es medir cuantos pulsos tengo en cierto tiempo. Y la otra es medir el periodo de la señal. Hace poco se hable sobre un frecuencimetro en el foro, y se concluyo que mejor era la ultima. ¿Entonces como procedes?
Configuras el CCP para CAPTURAR flancos ascendentes, y dejas tu Timer1 corriendo libre. La primera ves que entre a la interrupcion del CCP guardas el valor, y aca te quedan varias posibilidades.
- La segunda ves que entra, tomas el valor del TMR1 ( recorda que necesitas tomar el valor de TMR1L primero asi el TMR1H se actualiza) lo restas con el anterior y de alli calculas
o
- Esperas mas ciclos, ejemplo 2 ciclos, 4, 8, recien ahi tomas el valor del TMR1 y calcuclas tu frecuencia.
¿Como calcular la frecuencia?
Sabes que cada uno que suma el TMR1 es : 4/Fosc
El tiempo que paso entre ciclos va a depender de cuantos ciclos tomaste, por ejemplo si tomas te un ciclo es directo. Pero si tomaste 2,4 u 8, vas a tener que dividir el resultado por esa cantidad (Resultado de la resta de TMR1)/4 (por ejemplo con 4 )
De alli es multiplicar para obtener el periodo:
4/Fosc * Resta TMR1 / 4 = (Resta TMR1) / Fosc = Tseñal
Si quisiera la frecuencia
1 / Tseñal = Fosc / (Resta TMR1)
Y lo tenes.
-
Gracias por la ayuda ,ya tengo el TMR1 funcionando pero creo que aun no comprendo del todo el uso del CCP1.Asi tengo configurado el CCP1 :
void ccp1_config(void){
TRISCbits.RC2 = INPUT;
T3CCP2:T3CCP1 = 01; //TMR1 para CCP1
CCP1M0 = 0; //Captura flancos de subida
CCP1M1 = 1;
CCP1M2 = 0;
CCP1M3= 1;
CCP1IF = 0 ; //Bandera de Captura CCP1*/
}
Tengo mi rutina de interrupcion asi:
void __interrupt() isr(void){
//Medir periodo de la señar
if(CCP1IF){
count++;
frec = count;
}
}
frec es una variable que uso para imprimir el valor en un LCD. La idea es que cada flanco que reciba el CCP cause una interrupcion y asi con un contador yo puedo medir la frecuencias.No tengo el generador de funciones a la mano , pero no estoy seguro de la logica de mi programa
-
Necesitas ponerlo como CAPTURE.
El CAPTURE hace que al producirse el flanco ( o 4 flancos ) dispara la interrupcion, y guarda en los registros CCPRxH:CCPRxL el valor del Timer1.
Para configurarlo como capture cambias el registro CCP1CON, para 4 ciclos por ejemplo en caso de que tu frecuencia sea grande. Deberias poner CCP1CON = 0b0110
Y como te escribi antes... La idea es que cuando entre a la interrupcion, guardes en una variable el valor de los CCPRx, y luego en la proxima interrupcion restas el valor de CCPRx con lo que habias guardado. Ese resultado te va a indicar tu frecuencia.
PD: Para configurar los registros usas el nombre del registro, si queres modificar 1 bit, usas el nombre del registro + bits. + nombre del bit. Asi como tenes el TRISC
-
Gracias de nuevo , estoy teniendo problemas al entrar en la interrupcion del por CCP :
Asi tengo configurado el CCP1 :
void ccp1_config(void){
TRISCbits.RC2 = INPUT;
T3CCP2:T3CCP1 = 01; //TMR1 para CCP1
CCP1M3:CCP1M0 = 0101;//Captura Flancos de subida
CCP1IF = 1 ; //Bandera de Captura CCP1*/
}
GIE y PEIE estan ambos en 1
Y mi rutina de interrupcion :
void __interrupt() isr(void){
//Medir periodo de la señar
if(CCP1IF){
dato1= CCPR1;
LED = ~LED;
CCP1IF = 0;
}
}
Aun no estoy calculando la frecuencia , quiero saber si efectivamente esta entrando en la rutina de interrupcion . Para eso le estoy diciendo que cambie el estado de un Led cada vez que entra. El TMR1 funciona bien y estoy metiendo una señal cuadrada de 2Hz por CCP1 pero no veo el cambio del Led