Medir período de una señal cuadrada con un pic18f4620 y Compilador C18

Hola amigos!!Estoy realizando mi proyecto y trabajo con el PIC18f4620.
Utilizo MPlab con el compilador C18.
He encontrado mucha información en CCS pero en C18 no he encontrado lo que necesito...a ver si alguno de vosotros puede ayudarme...

Necesito medir con el PIC el período, o la frecuencia, lo mismo me da, de una señal cuadrada.

He leido que puedo utilizar la interrupción externa por flanco en RB0, con la cual detectaría que me ha entrado un flanco de subida.

A la vez la debo combinarlo con un timer, que calcule cuanto tiempo ha pasado desde que llegó mi flanco de subida hasta el próximo que me llegue...
Aquí está mi problema...cómo configuro el timer en c18??existe alguna sentencia que me capture directamente el dato temporal??hay una equivalencia de "get_timer" de ccs en c18???get_timer es utilizado en el código que copio a continuación.

Este es el código que he encontrado en CCS...a ver si alguien tuviera algo parecido en C18 o me pudiera dar algunas indicaciones..muchas gracias!un saludo!

PHP:
#include <18f4550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN, NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use delay(clock=20000000)

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)


////////////////////////////////////////////////////////////////////////////////////
//
// Defines y Constantes
//
////////////////////////////////////////////////////////////////////////////////////

#define LED PIN_E0 // Defino el Pin del Led
#define FLASH Output_Toggle(LED) // Defino la funcion Flash de monitor

float const uSxTick = 0.2; // Microsegundos por Tick de TMR1 a 20 Mhz


////////////////////////////////////////////////////////////////////////////////////
//
// Variables en RAM
//
////////////////////////////////////////////////////////////////////////////////////

char cRec=0x00; // Último caracter recibido via serie
char Command=0x00; // Comando a procesar
int8 numFlancoQueLlega=0; // Número de Flanco que llega
int1 flagToggleFlanco=0; // Flag para cambiar de flanco
int16 t1=0x00,t2=0x00,t3=0x00; // Variables para guardar estados de ...
int16 tth=0x00,ttl=0x00,tt=0x00; // Timers y pulsos.
float sth=0.0,stl=0.0,st=0.0,f=0.00; // Para hacer las restas oportunas en uS
int1 flagHayDatos=0; // Flag para indicar que ya hay datos de ..
// dos flancos (de subida y bajada)
int1 flagHayTransmitir=0; // Flag para indicar que hay datos para ...
// Transmitir al PC.

////////////////////////////////////////////////////////////////////////////////////
//
// Interrupción por Recepción Serie RS232
//
////////////////////////////////////////////////////////////////////////////////////


#int_rda
void handle_rda_int(){

if(kbhit()){ // Si hay algo pdte de recibir ...
cRec=getc(); // lo recibo sobre cRec ...
if(cRec!=0x00){ // Si es distinto de \0 ...
Command=ToUpper(cRec); // cargo cRec sobre Command para procesarlo
} // pasándolo a Mayúsculas para no confundir.
}
}

////////////////////////////////////////////////////////////////////////////////////
//
// Interrupción por Externa por Cambio de Flanco en RB0
//
////////////////////////////////////////////////////////////////////////////////////


#int_ext
void handle_ext_int(){

++numFlancoQueLlega; // Cuento flanco que nos llega

if(flagToggleFlanco==0){ // He recibido Flanco de Subida

if(numFlancoQueLlega==1){
set_timer1(0); // Reinicio TMR1
t1=[COLOR="Red"]get_timer1[/COLOR](); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
}
if(numFlancoQueLlega==3){
t3=get_timer1(); // Guardo en t1 el valor de TMR1 al primer Flanco de Subida
if(flagHayDatos==0){ // Si los datos anteriores han sido procesados ...
flagHayDatos=1; // Indico que ya hay nuevos datos de flancos para calcular
}
}
ext_int_edge(0,H_TO_L); // Configuro para capturar siguiente flanco de Bajada
flagToggleFlanco=1; // Indico que el siguiente flanco será de Bajada

} else { // He recibido Flanco de Bajada

t2=get_timer1(); // Guardo en t2 el valor de TMR1 al Flanco de Bajada
ext_int_edge(0,L_TO_H); // Configuro para capturar siguiente flanco de subida
flagToggleFlanco=0; // Indico que el siguiente flanco será de Subida
}

FLASH; // Reproduzco la entrada mediante un LEd en E0;

if(numFlancoQueLlega==3){
numFlancoQueLlega=0;
}

}
void main() {


////////////////////////////////////////// INICIALIZACIONES GENERALES

delay_ms(333); // Espero a que todo se estabilice e ...
disable_interrupts(global); // Inicializo el Micro y ...
disable_interrupts(int_timer1); // deshabilitando todo lo no necesario ...
disable_interrupts(int_rda);
disable_interrupts(int_ext);
disable_interrupts(int_ext1);
disable_interrupts(int_ext2);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(FALSE);
delay_ms(333);

/////////////////////////////////////////// INICIALIZACIONES PERTINENTES A LA APLICACION

set_tris_c(0b10000000); // Habilito como entrada RC7 para canal RS232

ext_int_edge(0,L_TO_H); // Configuro captura de 1er flanco de subida
flagToggleFlanco = 0; // inicializo el Flag para cambiar de flanco

enable_interrupts(int_rda); // Habilito las interrupciones necesarias
enable_interrupts(int_ext);
enable_interrupts(global);

printf("\r\nMidiendo un pulso : Periodo\r\n");
printf("By Redpic para Foro TODOPIC\r\n\n");

do {

if(flagHayDatos==1){ // Detecto que ya hay datos de flancos ...
if((t3>t2)&&(t2>t1)){ // Compruebo que estoy en la misma vuelta de TMR1
tth = t2 - t1; // Calculo en Tick's de TMR1 el tiempo en Alto
ttl = t3 - t2; // Calculo en Tick's de TMR1 el tiempo en Bajo
tt = tth + ttl; // Calculo en Tick's de TMR1 el Periodo del Pulso
sth = uSxTick * tth; // Calculo en uS el tiempo.
stl = uSxTick * ttl; // Calculo en uS el tiempo.
st = uSxTick * tt; // Calculo en uS el tiempo.
f = 1 / (st / 1000000); // Calculo la Frecuencia

flagHayTransmitir=1; // Indico que tengo nuevo valor para transmitir
}
flagHayDatos=0; // Indico que ya han sido procesados los datos.
}
if(Command!=0x00){ // Si he recibido un comando vía Serie ...
if(Command=='T'){ // Si el comando es 'T' (Transmite) ...
if(flagHayTransmitir==1){ // Si hay algo pendiente de transmitir ...

printf("Ticks ....... H %4Lu + L %4Lu = %4Lu\r\n",tth,ttl,tt);
printf("uSegundos ... H %3.1f + L %3.1f = %3.1f F = %4.2f Hz\r\n\n",sth,stl,st,f);

flagHayTransmitir=0; // Indico que ya he transmitido lo pendiente.
}
}
Command=0x00; // Indico que ya he procesado el comando.
}


} while (TRUE);
}


PD: yo no necesito la tx por R232 que utilizan en est código..gracias!
 
Última edición por un moderador:
Lo que intentas hacer ya esta inventado y se llama modulo CCP/ECCP, que por lo que he visto brilla por su ausencia en el codigo que has encontrado. Estos modulos (Compare/ Capture/ PWM) hacen lo que quieres hacer por hardware, y en el codigo tan solo tienes que configurarlos. Si miras el datasheet de tu micro te vienen los registros que se utilizan para configurar los modulos como captura, comparacion o pwm. Estos modulos funcionan junto a uno o dos timer. En concreto el modulo CCP (el ECCP es el ccp mejorado), para utilizar el modo captura puedes utilizar o el timer 1 o el timer 3, (pagina 140 del datasheet). Hazmelo saber si tienes alguna duda.
Un saludo
 
Lo que intentas hacer ya esta inventado y se llama modulo CCP/ECCP, que por lo que he visto brilla por su ausencia en el codigo que has encontrado. Estos modulos (Compare/ Capture/ PWM) hacen lo que quieres hacer por hardware, y en el codigo tan solo tienes que configurarlos. Si miras el datasheet de tu micro te vienen los registros que se utilizan para configurar los modulos como captura, comparacion o pwm. Estos modulos funcionan junto a uno o dos timer. En concreto el modulo CCP (el ECCP es el ccp mejorado), para utilizar el modo captura puedes utilizar o el timer 1 o el timer 3, (pagina 140 del datasheet). Hazmelo saber si tienes alguna duda.
Un saludo

Muchas gracias por la respuesta!Pero...me podrías ayudar dandome unos cuantos más datos..
Nunca he utilizado en módulo CCP...así que no se exactamente qué hace...ni cómo utilizarlo..ni cómo configurarlo en C18 así como las líneas que debo escribir para que realice lo que yo quiero...

tendrías algún código de ejemplo en el que se utilice CCP o que haga algo parecido a lo que yo necesito...??

Muchas gracias!Un saludo!;)
 
pues la verdad es que nunca he utilizado el modulo ccp para hacer capturas, tan solo lo he utilizado para crear señales pwm, pero bueno a ver si te lo explico bien.
El modo captura puede funcionar de diversas maneras, que detecte flanco de bajada, flancos de subida, cada 4 flancos de subida o cada 16 flancos de subida, eso se configura en el registro CCP2CON, con los bits CCP2M3:CCP2M0. En el momento se detecta lo que hayas configurado, salta una interrupcion, y en ese momento el valor del temporizador pasa al registro CCP2RH y CCP2RL, si tomas dos flancos de bajada por ejemplo, y en el primero pones en marcha el temporizador y en el otro lees el timer tandras el valor del periodo. los timers que asociados a el modulo ccp son el 1 y el 3, sea cual sea el que elijas deberas configyrarlo con su correspondiente registro TxCON.
De tdas formas ya te digo que yo nunca lo he hecho, busca por el datasheet de tu PIC informacion sobre el modulo y te vienen todos los registros que debes configurar ok?
Un saludo
 
Hola a todos!

Alguien tiene algún ejemplo con el compilador C18 en el que utilice el módulo CCP en modo captura??

Necesito utilizarlo para medir el período de una señal con el pic18f4620, pero no encuentro mucha información para poder realizar esto con C18.

Espero vuestras respuestas!!1saludo!muhas gracias!
 
He encontrado como se hace con CCS...igual que me pasó con el tema de las interrupciones.
Me he dado cuenta de que hay muchísima más información para trabajar con CCS que con C18, así que...cuál es la diferencia de trabajar con el compilador CCS en vez de con el compilador C18???
Porque si no hay muchas diferencias...voy a pensarme lo de instalarme CCS y trabajar con él...

Un saludo!
 
pues la verdad es que nunca he utilizado el modulo ccp para hacer capturas, tan solo lo he utilizado para crear señales pwm, pero bueno a ver si te lo explico bien.
El modo captura puede funcionar de diversas maneras, que detecte flanco de bajada, flancos de subida, cada 4 flancos de subida o cada 16 flancos de subida, eso se configura en el registro CCP2CON, con los bits CCP2M3:CCP2M0. En el momento se detecta lo que hayas configurado, salta una interrupcion, y en ese momento el valor del temporizador pasa al registro CCP2RH y CCP2RL, si tomas dos flancos de bajada por ejemplo, y en el primero pones en marcha el temporizador y en el otro lees el timer tandras el valor del periodo. los timers que asociados a el modulo ccp son el 1 y el 3, sea cual sea el que elijas deberas configyrarlo con su correspondiente registro TxCON.
De tdas formas ya te digo que yo nunca lo he hecho, busca por el datasheet de tu PIC informacion sobre el modulo y te vienen todos los registros que debes configurar ok?
Un saludo

Hola!!!He estado informandome de como hacerlo con el ccp en modo captura, y he escrito el siguiente código:

PHP:
#include <P18f4620.h>
#include <capture.h>
#include <timers.h>
#include <math.h>
#include <stdio.h>

#pragma config DEBUG=ON
#pragma config OSC=XT
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config PWRT=OFF
#pragma config MCLRE=ON
#pragma config CCP2MX = PORTBE

int nuevopulso=0; //Entra otro pulso
int TFB=0; //Tiempo flancos
int TFS=0;
int TF=0;
float AP; //Valor final del ancho de pulso
float APFIN; //Periodo completo
float FRECUENCIA;
int cambio=0; //Cambio de flanco de disparo


/******************************************************************************************************* 
/*	Interrupcion con direccion 0x18
/***************************************************************************************************** */
void InterruptServiceLow(void);
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow (void)
{
  _asm
    goto InterruptServiceLow //Salta a la direccion de interrupcion BAJA
  _endasm
}

#pragma interruptlow InterruptServiceLow// Directiva pragma "interruptlow" para interrupcion de baja prioridad
void InterruptServiceLow(void)
{
  if(cambio==0){ //Flanco de subida
TFS= ReadCapture2(); //Carga del valor del registro CCPR2 en flanco subida
LATA=0x01;
cambio=1;
OpenCapture2( C2_EVERY_FALL_EDGE &
CAPTURE_INT_ON ); //Configuración modo Captura en flanco de bajada
 //Control de cambio de flanco
} else { //Flanco de Bajada
TFB= ReadCapture2(); //Carga del valor del registro CCPR2 en flanco bajada
LATA=0x00;
cambio=0; 
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_ON ); //Configuración modo Captura en flanco de subida
//Control de cambio de flanco

if(nuevopulso==0){ //Fin de pulso...
nuevopulso=1; //pulso a medir
}
}
}


void main() {

TRISAbits.TRISA0=0;
TRISBbits.TRISB3=1;

INTCONbits.GIE=0 ;//disable_interrupts(global);
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_ON );
OpenTimer3( TIMER_INT_OFF &
T3_SOURCE_INT );
cambio = 0; //Control de cambio a 0
PIR2bits.CCP2IF=0;
INTCONbits.GIE=1;

while (1){
if(nuevopulso==1){ //¿Pulso nuevo?
TF=(TFB-TFS); //Ancho de pulso.
AP = TF*1.0; //Ancho de pulso en microsegundos (a 4MHz:1us)
APFIN = AP*2;
FRECUENCIA = 1/APFIN;
nuevopulso=0; //Pulso ya medido, espera nuevo
}
} 
}

No me funciona...y pienso que es porque no entra en la interrupción cuando recibe el flanco de subida...

Me falta alguna configuración más??tengo que llamar a la interrupción desde alguna otra parte del código???

Estaría muy agradecida si alguien supiera donde está mi fallo...

Muchas gracias!Un saludo!!
 
Última edición por un moderador:
donde activas el sistema de prioridades de las interrupciones¿?¿? es que si no lo activas, todas las interrupciones tienen prioridad alta. en vez de utilizar la direccion 0x18 utiliza la 0x08 que es la de las interrupciones de alta prioridad.
Un saludo

ah y otra cosa, cada vez que entres en la interrupcion, no estoy seguro si el flag de la interrupcion se pone solo a 0, o tienes que ponerlo tu por software. prueba tambien a ponerlo tu manualmente a 0.
un saludo
 
Última edición:
Hola Pablet!!Gracias por tu respuesta.
En referencia a
donde activas el sistema de prioridades de las interrupciones¿?¿? es que si no lo activas, todas las interrupciones tienen prioridad alta
...te pongo aquí el código modificado..aver si te referías a eso con lo de activar el sistema de prioridades de las interrupciones...

Pero sigue sin funcionarme...y no encuentro el fallo..pero yo creo q no me entra a la interrupción...si pudieras echarle un vistazo al código a ver si ves algún fallo me serías de gran ayuda..

Ahí va el código:

Código:
#include <P18f4620.h>
#include <capture.h>
#include <timers.h>
#include <math.h>
#include <stdio.h>

#pragma config DEBUG=ON
#pragma config OSC=XT
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config PWRT=OFF
#pragma config MCLRE=ON
#pragma config CCP2MX = PORTBE

int nuevopulso=0; //Entra otro pulso
int TFB=0; //Tiempo flancos
int TFS=0;
int TF=0;
float AP; //Valor final del ancho de pulso
float APFIN; //Periodo completo
float FRECUENCIA;
int cambio=0; //Cambio de flanco de disparo


/******************************************************************************************************* 
/*	Interrupcion con direccion 0x08
/***************************************************************************************************** */
void InterruptServiceHigh(void);
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
  _asm
    goto InterruptServiceHigh //Salta a la direccion de interrupcion ALTA
  _endasm
}

/******************************************************************************************************* 
/*	Interrupcion con direccion 0x18
/***************************************************************************************************** */
void InterruptServiceLow(void);
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow (void)
{
  _asm
    goto InterruptServiceLow //Salta a la direccion de interrupcion BAJA
  _endasm
}


void ccp2_int(void){

  if(cambio==0){ //Flanco de subida
TFS= ReadCapture2(); //Carga del valor del registro CCPR2 en flanco subida
LATA=0x01;
cambio=1;
PIR2bits.CCP2IF=0;
OpenCapture2( C2_EVERY_FALL_EDGE &
CAPTURE_INT_ON ); //Configuración modo Captura en flanco de bajada
 //Control de cambio de flanco
} else { //Flanco de Bajada
TFB= ReadCapture2(); //Carga del valor del registro CCPR2 en flanco bajada
LATA=0x00;
cambio=0; 
PIR2bits.CCP2IF=0;
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_ON ); //Configuración modo Captura en flanco de subida
//Control de cambio de flanco

if(nuevopulso==0){ //Fin de pulso...
nuevopulso=1; //pulso a medir
}
}
}


void main() {

TRISAbits.TRISA0=0;
TRISBbits.TRISB3=1;

INTCONbits.GIE=0 ;//disable_interrupts(global);
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_ON );
OpenTimer3( TIMER_INT_OFF &
T3_SOURCE_INT );
cambio = 0; //Control de cambio a 0
PIR2bits.CCP2IF=0;
INTCONbits.GIE=1;

while (1){
if (nuevopulso==1){ //¿Pulso nuevo?
TF=(TFB-TFS); //Ancho de pulso.
AP = TF*1.0; //Ancho de pulso en microsegundos (a 4MHz:1us)
APFIN = AP*2;
FRECUENCIA = 1/APFIN;
TMR1L=0x00;
TMR1H=0x00;
nuevopulso=0; //Pulso ya medido, espera nuevo
}
} 
}

/******************************************************************************************************* 
/*	Interrupcion con direccion 0x08
/***************************************************************************************************** */
#pragma interrupt InterruptServiceHigh  // Directiva pragma "interrupt" para interrupcion de alta prioridad
void InterruptServiceHigh(void)
{
	if(PIR2bits.CCP2IF)
	{	
		ccp2_int();
	}
}
/*******************************************************************************************************
******************************************************************************************************** 
/*	Interrupcion con direccion 0x18
/***************************************************************************************************** */
#pragma interruptlow InterruptServiceLow// Directiva pragma "interruptlow" para interrupcion de baja prioridad
void InterruptServiceLow(void)
{
  /**********************
    /* aqui va el programa que corresponde a la interrupcion de baja prioridad
    ***********************/
}

Muchas gracias!!Un saludo!
 
hola!! una cosa, estas simulando el circuito o lo has montado?, para ver si entra en la interrupcion lo mejor es hacer un debug, y si es con el proteus mejor que mejor, estas utilizando proteus para la simulación? si es asi, en vez de cargar el archivo .hex en el pic, carga el .cof, y asi si lo pones en marcha y le das a pause te sale el codigo y puedes poner break points en el circuito, y ver el estado de cualquier variable. otra cosa, que velocidad tiene el oscilador que has puesto? si es mayor a 4MHz, debes poner esto #pragma config OSC=HS. dime cosas!!
Un saludo
 
Última edición:
hola!! una cosa, estas simulando el circuito o lo has montado?, para ver si entra en la interrupcion lo mejor es hacer un debug, y si es con el proteus mejor que mejor, estas utilizando proteus para la simulación? si es asi, en vez de cargar el archivo .hex en el pic, carga el .cof, y asi si lo pones en marcha y le das a pause te sale el codigo y puedes poner break points en el circuito, y ver el estado de cualquier variable. otra cosa, que velocidad tiene el oscilador que has puesto? si es mayor a 4MHz, debes poner esto #pragma config OSC=HS. dime cosas!!
Un saludo

Hola Pablet!!Muchas gracias por tu interés...la verdad que cuando estás un poco perdida se agradece bastante...

Pues tengo una placa montada con el PIC18f4620, trabajando con un cristal de 4MHz, e introduzco una señal cuadrada que genero con un generador de onda por RB3...que se supone que es donde lee el CCP2 con la configuración que le he puesto...Pero nada...no me funciona nada...

Por ahí encontré un código mucho mas corto...que puede ser que sea mejor que el que yo he hecho:

I'm using CCP1 to capture a signal and measure it frequency, which works just fine.

Now I need to capture other signal (B signal from a encoder) so I'm trying to use CCP2 for this. The problem is CCP2 does not work, using the same code of CCP1.

I'm using PIC 18F452, 20 MHz Crystal, ICD2 and MCC18.

My code is the following:

"...
unsigned int initial = 0x00;
unsigned int final = 0x00;
unsigned int elapsed = 0x00;

// Configure High-Frequency Timer3, no Interrupts, Internal clock, prescale 1 (20MHz / 4 = 0,2 us)
OpenTimer3(TIMER_INT_OFF & T3_SOURCE_INT & T3_PS_1_1 );

// Configure Capture2
OpenCapture2(C2_EVERY_RISE_EDGE & CAPTURE_INT_OFF);

TRISCbits.RC1 = 0x01; //set CCP2 as input

PIR2bits.CCP2IF = 0x00; // make sure flag is 0

while(!PIR2bits.CCP2IF); //wait for first event
initial = ReadCapture2 (); //get first time stamp
PIR2bits.CCP2IF = 0x00; // make sure flag is 0

while(!PIR2bits.CCP2IF); //wait for second event
final = ReadCapture2 (); //get second time stamp

CloseCapture2 ();
CloseTimer3 ();

elapsed = final - initial; // compute elapsed time
..."

This code works fine in CCP1, but in CCP2 using the same signal nothing happen. I have already set a breakpoint in the OpenTimer3 line and it does not gets there. Is there any problem with my code ???

I have already read datasheet chapter 17 (CCP) and find no difference between CCP1 and CCP2. C18 libraries manual says nothing about this subject also, so the problem must be in my code.

Every help is welcome !!!
thanks

Lo encontré en el foro de microchip: http://www.microchip.com/forums/tm.aspx?m=129672.

Lo único es que son sentencias sueltas, sin main ni interrupciones ni nada de nada...

Yo lo he intentado con ese código pero sigue sin salirme...así que ya no se si trabajo mal con las interrupciones o no se...

Bueno si se te ocurre algo me sería de gran ayuda tu opinión!!

Muchas gracias...un saludo!
 
vale eso cambia las cosas, si es una placa montada tienes que cambiar esto
Código:
#pragma config DEBUG=OFF
y esto tambien lo pongo yo siempre
Código:
#pragma config MCLRE=OFF
con lo segundo te evitas tener que poner la patilla 1 a vcc para evitar que el micro este siempre en reset, es completamente opcional, si lo pones a on debes poner la patilla MCLRE a VCC y lo del debug es que si esta en on, el microcontrolador esta configurado para depurar el programa, si quieres que corra normal tienes que ponerlo a OFF.
 
vale eso cambia las cosas, si es una placa montada tienes que cambiar esto
Código:
#pragma config DEBUG=OFF
y esto tambien lo pongo yo siempre
Código:
#pragma config MCLRE=OFF
con lo segundo te evitas tener que poner la patilla 1 a vcc para evitar que el micro este siempre en reset, es completamente opcional, si lo pones a on debes poner la patilla MCLRE a VCC y lo del debug es que si esta en on, el microcontrolador esta configurado para depurar el programa, si quieres que corra normal tienes que ponerlo a OFF.


Hola Pablet!!Ya he conseguido que me funcione el CCP...ahora el problema lo tengo con el timer..que no se cómo hacer para que me capture bien el tiempo..cada vez me mide un tiempo diferente aunq le entre la misma señal con el mismo período.

Te pego el código para ver si tu ves el fallo que cometo con los timers..

PHP:
#include <p18f4620.h>
#include <delays.h>
#include <capture.h>
#include <stdio.h>
#include <timers.h>
#include <stdlib.h>

#pragma config DEBUG=OFF
#pragma config OSC=XT
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config PWRT=OFF
#pragma config MCLRE=OFF
#pragma config CCP2MX = PORTBE

#define	LED	LATEbits.LATE0

void main(){

unsigned int cambio;
unsigned int tiempo;
float uSxTick = 1.0;
float f=0.00; 
float st=0.0;


ADCON1=0XFF;
TRISBbits.TRISB3=1;
TRISEbits.TRISE0=0;



// Configure Timer1
OpenTimer3( TIMER_INT_OFF &
T3_SOURCE_INT);

// Configure Capture2
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_OFF );

while(PIR2bits.CCP2IF==1){
	WriteTimer3(0);
	//LED=1;
	PIR2bits.CCP2IF=0;
	cambio=1;	
	}
while(cambio==1){
	while(PIR2bits.CCP2IF==1){
		tiempo=ReadTimer3();
		st = uSxTick * tiempo;
		f   = 1 / (st/1000000);
		//LED=0;
		PIR2bits.CCP2IF=0;
		cambio=0;	
	}

}

}

Muchisimas gracias!!Un saludo!!
 
Última edición por un moderador:
hola!! de cuanta variacion estamos hablaando? en el codigo creo que hay un error:
Código:
while(PIR2bits.CCP2IF==1){
WriteTimer3(0);  <-- aqui pones a 0 el temporizador y machacas lo que haya
//LED=1;
PIR2bits.CCP2IF=0; <---- aqui lo pones a 0
cambio=1;	
}
while(cambio==1){
while(PIR2bits.CCP2IF==1){ <-- aqui solo entra si es igual a 1
tiempo=ReadTimer3(); <-- aqui lees el temporizador que previamente has machacado
st = uSxTick * tiempo;
f = 1 / (st/1000000);
//LED=0;
PIR2bits.CCP2IF=0; <-- aqui vuelves a poner a 0 el flag
cambio=0;	
}

}
si pones a 0 el flag de la interrupción y luego haces un while en el que solo entra si es igual a 1 ahí nunca entrará, igual que con el temporizador, cuando salta la interrupción lo pones a 0 y luego lo lees. . lo de ponerlo a 0 deberías hacerlo al final, una vez lo hayas leído. espero que sea es el fallo!
Un saludo
 
Hola!!Gracias por tu respuesta..En cuanto a lo que me comentas...A ver te explico POR q he hecho eso...
si pones a 0 el flag de la interrupción y luego haces un while en el que solo entra si es igual a 1 ahí nunca entrará, igual que con el temporizador, cuando salta la interrupción lo pones a 0 y luego lo lees. . lo de ponerlo a 0 deberías hacerlo al final, una vez lo hayas leído. espero que sea es el fallo!
Un saludo

Según lo que yo he entendido...el CCP cada vez que se produce un flanco de subida pone el flag de interrupción a 1, por eso cuando se produce el primer flanco yo pongo el flag a 0..para que cuando se vuelva a poner el flag a 1 con el 2º flanco...entre en el while y así yo lea con el timer cuanto tiempo ha pasado...por eso mismo tambien inicializo a 0 el timer en el primer flanco de subida...

El problema lo tengo en que cuando leo ese timer..cada vez me da algo distinto y no se POR q..

Me he explicado bien??

Un saludo!
 
Última edición por un moderador:
ok, ya lo entendi, pero asi estas leyendo el tiempo de 2 periodos, y luego solo coges el del segundo que es igual que el del primero, asi que haces dos veces lo mismo pero bueno, otra cosa, que segun el datasheet: "In Capture mode, the CCPRxH:CCPRxL register pair captures the 16-bit value of the TMR1 or TMR3 registers when an event occurs on the corresponding CCPx pin." osea que el tiempo no se almacena en el registro de timer, sino en CCPRxH:CCPRxL, quiza el pic mueva el registro ese una vez ha pasado los datos a los registros CCPRxH:CCPRxL por eso cada vez leed una cosa diferente. Intentalo leyendo el valor de esos registros.
Un saludo
 
Hola Pablet!!He dado con el código que consigue medirme la frecuencia...pero sólo me la mide más o menos bien en un rango (2kHz-18kHz). Fuera de aquí...o me la mide con mucha diferencia ( sin son 500 Hz me pone 390) o a partir de 20Khz siempre me da el mismo resultado..

Trabajo con un cristal de 4Mhz...así que voy a intentar conseguir uno de 20 Mhz a ver si logro mayor exactitud en la medida.

Tu sabrías otra de las causas cual puede ser??

Bueno muchas gracias por tu ayuda...gracias a ti he logrado ver un poco más la luz!!

Aquí te dejo el par de códigos con los que he conseguido obtener resultados.

O bien con el CCP:

PHP:
#include <p18f4620.h>
#include <delays.h>
#include <capture.h>
#include <stdio.h>
#include <timers.h>
#include <stdlib.h>

#pragma config DEBUG=OFF
#pragma config OSC=XT
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config PWRT=OFF
#pragma config MCLRE=ON
#pragma config CCP2MX = PORTBE

#define	LED	LATEbits.LATE0

void main(){

unsigned int tiempo;
unsigned float uSxTick = 1.0;
unsigned float f; 
unsigned float st=0.0;


ADCON1=0XFF;
TRISBbits.TRISB3=1;
TRISEbits.TRISE0=0;


// Configure Timer1
OpenTimer3( TIMER_INT_OFF &
T3_SOURCE_INT &
T3_SOURCE_CCP);

// Configure Capture2
OpenCapture2( C2_EVERY_RISE_EDGE &
CAPTURE_INT_OFF );

PIR2bits.CCP2IF=0;

while(PIR2bits.CCP2IF==0);
WriteTimer3(0);
//LED=1;
PIR2bits.CCP2IF=0;

while(PIR2bits.CCP2IF==0);
tiempo=ReadTimer3();
st = uSxTick * tiempo;
f   = 1 / (st/1000000);
//LED=0;
PIR2bits.CCP2IF=0;	

CloseCapture2;

	
}

O bien testeando el PIN de entrada RB3:

PHP:
#include <p18f4620.h>
#include <delays.h>
#include <capture.h>
#include <stdio.h>
#include <timers.h>
#include <stdlib.h>

#pragma config DEBUG=OFF
#pragma config OSC=XT
#pragma config WDT=OFF
#pragma config LVP=OFF
#pragma config PWRT=OFF
#pragma config MCLRE=ON
#pragma config CCP2MX = PORTBE

#define LED LATEbits.LATE0

void main(){

unsigned int time;
unsigned float uSxTick = 1.0;
unsigned float f; 
unsigned float st=0.0;


ADCON1=0XFF;
TRISBbits.TRISB3=1;
TRISEbits.TRISE0=0;


// Configure Timer1
OpenTimer3( TIMER_INT_OFF &
T3_16BIT_RW &
T3_SOURCE_INT &
T3_PS_1_8);

while(PORTBbits.RB3==1); //Wait for end of previous pulse
while(PORTBbits.RB3==0); //Wait for start of new pulse
WriteTimer3(0); //Clear Timer
while(PORTBbits.RB3==1); //Wait for end of new pulse
while(PORTBbits.RB3==0); //Wait for start of next pulse
time=ReadTimer3(); //read timer
st = uSxTick * time;
f = 1 / (st/100000);
//while(1);


}

Un saludo!!Y de nuevo gracias :)
 
Última edición por un moderador:
Atrás
Arriba