TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: urielm80 en 28 de Abril de 2014, 01:59:42

Título: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 28 de Abril de 2014, 01:59:42
Hola, quisiera que me ayudaran a resolver un problema que tengo, resulta que tengo un problema con la funcion  delay_ms(1000);, el problema radica en que en lugar de esperarse 1 segundo se espera 4, realice un programa sencillo para averiguar si tenia algún problema de configuración, como información adicional he probado con un oscilador de 4 Mhz y uno de 20 Mhz, configurando su respectivo #use delay(clock=4000000), físicamente tengo el oscilador con capacitores de 22pF, a continuación les dejo mi código de ejemplo, espero me puedan ayudar, gracias

Código: [Seleccionar]
/////////////////////////////////////////////////////////////////
// programa para prender un led y apagarlo cada segundo        //
//                                                             //
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
///// Created by Uriel                             //////////////
/////                                              //////////////
/////////////////////////////////////////////////////////////////
#include <18F4550.h>


#Fuses HS, NOWDT, NOPROTECT, NOLVP, NODEBUG, USBDIV, PLL1, CPUDIV1, VREGEN

#use delay(clock=4000000)

void main()
{
   

   DO{
         // enciende led conectado a RB1
      output_high(PIN_A1);
      delay_ms(250);
      output_low(PIN_B5);   // enciende led conectado a RB1
      delay_ms(10);
      if(input(PIN_B4)==0){
         output_low(PIN_B1);
      }else{
         output_high(PIN_B1);
      }
      output_low(PIN_A1);
      delay_ms(250);
   }
   while (TRUE);
}

/////////////////////////////////////////////////////////////////



con el código anterior logro el retardo de 1 segundo, pero debería de ser solo de 250 mili-segundos, por cierto a excepción del tiempo todo funciona bien, un led parpadea y el otro enciende dependiendo de un botón que tengo conectado.
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: EdoNork en 28 de Abril de 2014, 05:48:33
¿Cómo es la función delay_ms() que utilizas?
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: Fulguitron en 28 de Abril de 2014, 08:21:27
Una aclaración, usas el B4 como entrada y el B1, B5 y A5 como salida? 
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: zivit en 28 de Abril de 2014, 09:16:16
Hola,

si te lees el Datasheet del Pic, podrás encontrar que internamente el micro no trabaja a la frecuencia real del oscilador, sino que trabaja a Fclk = Fosc/4 eso significa que realmente tienes un clock de 1Mhz cuando trabajas con el Osc de 4MHz.

Entonces donde defines la frecuencia del CLK debes poner 1000000; #use delay(clock=1000000). Así ahora el tiempo que buscas se ajustara al del retardo.

Espero que te sirva.

Un Saludo.

Zivit.
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: MGLSOFT en 28 de Abril de 2014, 09:35:23
Fuses HS le dice al compilador que es un cristal mayor a 4 Mhz, en tu caso deberas poner Fuses XT.

Por otro lado, debes declararle la velocidad de trabajo interno tambien, aqui tienes una nota de CCS al respecto:
https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=164 (https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=164)
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: RedPic en 28 de Abril de 2014, 09:52:30
¿Qué versión de CCS C usas? porque dependiendo de la versión puede ser que tengas que variar el contenido del #use delay()

Yo, por ejemplo, en un proyecto que estoy haciendo con un 18F46K22 y el CCS C V.5.023 haciendo uso del oscilador interno tuve que poner

Código: CSS
  1. #use delay(clock=16000000,internal=16000000)

Y en otro proyecto con la misma versión del CCS C pero con un 18F2550 pero con Cristal Externo de 20 Mhz tuve que utilizar esto para que me contase en condiciones

Código: CSS
  1. #use delay(clock=20000000,Crystal=20000000)

En caso contrario no me iban bien los Timers o el cálculo de los baudios de la USART.  :shock:

Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 28 de Abril de 2014, 13:48:16
Primero que nada gracias a todos por responder tan rapido, ahora, revisando cada comentario:

Fuses HS le dice al compilador que es un cristal mayor a 4 Mhz, en tu caso deberas poner Fuses XT.

Por otro lado, debes declararle la velocidad de trabajo interno tambien, aqui tienes una nota de CCS al respecto:
https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=164 (https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=164)

lo del HS lo deje ya que en realidad pretendo usar un cristal de 20Mhz pero probé con uno de 4Mhz ya que mi cristal de 20 Mhz en lugar de tener impreso 20 000 000 dice 200 000 000 y me hizo pensar que me vendieron mal el oscilador, ahora con respecto a la nota veo que debería usar algo así para el de 20 Mhz
#use delay(crystal=20MHz)
aunque mi duda es si al usar esta instrucción no me afectara para usar los módulos de radiofrecuencia??????, ya que mi aplicación final es un sistema que se comunica a mas pic por RF pero pues debido al problema con los delay realice este programa básico.


Hola,

si te lees el Datasheet del Pic, podrás encontrar que internamente el micro no trabaja a la frecuencia real del oscilador, sino que trabaja a Fclk = Fosc/4 eso significa que realmente tienes un clock de 1Mhz cuando trabajas con el Osc de 4MHz.

Entonces donde defines la frecuencia del CLK debes poner 1000000; #use delay(clock=1000000). Así ahora el tiempo que buscas se ajustara al del retardo.

Espero que te sirva.

Un Saludo.

Zivit.

hola, supongo que con la modificación que sugiere MGLSOFT se resuelve el problema de que el micro trabaja a  Fclk = Fosc/4 cierto?, o tendría aun asi que dividirlo entre 4??? y si es así, no me afecta con lo que comento de los módulos de RF??

Una aclaración, usas el B4 como entrada y el B1, B5 y A5 como salida? 


sip, uso el B4 de entrada y el B1, B5 y A5 como salida y como comentaba antes eso funciona sin problemas.



¿Cómo es la función delay_ms() que utilizas?


La función delay_ms() es la que ya trae el compilador en sus librerías, ahora mismo no la tengo a la mano pero en la noche que llegue la busco y la publico



¿Qué versión de CCS C usas? porque dependiendo de la versión puede ser que tengas que variar el contenido del #use delay()

Yo, por ejemplo, en un proyecto que estoy haciendo con un 18F46K22 y el CCS C V.5.023 haciendo uso del oscilador interno tuve que poner

Código: CSS
  1. #use delay(clock=16000000,internal=16000000)

Y en otro proyecto con la misma versión del CCS C pero con un 18F2550 pero con Cristal Externo de 20 Mhz tuve que utilizar esto para que me contase en condiciones

Código: CSS
  1. #use delay(clock=20000000,Crystal=20000000)

En caso contrario no me iban bien los Timers o el cálculo de los baudios de la USART.  :shock:




En este momento no recuerdo que version es, pero lo reviso y lo publico


Gracias a todos y espero que puedan ayudarme con las dudas que aun tengo, en la noche probare las modificaciones que me sugieren y les comento que pasó
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 29 de Abril de 2014, 00:47:55
Hola, tengo el compilador PCWHD versión 4.114

modifique el delay asi
#use delay(clock=20MHz, crystal)

y los delay_ms(250); duran 5 segundos, mi oscilador es de 20 Mhz y los fuse están así
#Fuses HS, NOWDT, NOPROTECT, NOLVP, NODEBUG, USBDIV, PLL1, CPUDIV1, VREGEN

hice la prueba de usar el oscilador interno poniendo esto
#use delay(clock=4MHz, internal)

y el delay de 1 segundo dura exactamente eso, que podrá ser, físicamente tengo conectado a los pines 13 y 14 el oscilador de 20Mhz (OSC1 y OSC2) posteriormente tengo capacitores de 22 pF a tierra

por cierto hay algo extraño, si lo programo por ejemplo a 4Mhz con reloj externo y le conecto el oscilador de 20 Mhz no veo ninguna diferencia en tiempo con el de 4 Mhz,  y en otro experimento que hice le quite el oscilador  los capacitores y sigue funcionando exactamente igual, porque???????
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: solapower en 29 de Abril de 2014, 05:06:04
Estás verificando el funcionamiento en un circuito montado realmente o en un simulador ?
Si utilizas Proteus pudiera ser que no tuvieras bien configurado el oscilador en las propiedades del micro,
me induce a pensar en ello el hecho que comentas de que quitándole el cristal también te funciona.
Saludos
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 29 de Abril de 2014, 13:08:29
Estás verificando el funcionamiento en un circuito montado realmente o en un simulador ?
Si utilizas Proteus pudiera ser que no tuvieras bien configurado el oscilador en las propiedades del micro,
me induce a pensar en ello el hecho que comentas de que quitándole el cristal también te funciona.
Saludos

lo estoy probando realmente, lo tengo en una protoboard, lo que hice fue desconectarlo de la pc, quitar oscilador y capacitores y volverlo a conectar al usb y para mi sorpresa seguia funcionando exactamente igual aun cuando lo programe con la configuracion de oscilador externo de 20 MHz y luego de 4 MHz
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: zivit en 29 de Abril de 2014, 21:01:18
El pic tiene una salida del clock interno, en la pata CLKO, prueba a configurarla para que saque el clock, pincha con un osciloscopio y mira que frecuencia te da. Así comprobaras si realmente funciona bien el oscilador. Luego respecto a la función delay(ms), si quieres te la puedes hacer tu mismo, si sabes la frecuencia del reloj, sabes cuanto dura una instrucción, simplemente tienes que hacer una espera de tantas instrucciones (calculas con la formulita). Luego la compruebas con un simulador y calibras el numero de instrucciones para que te clave los ms que le indiques.

También lo puedes calibrar en un timer. Al fin y al cabo un delay provoca la retención del hilo del programa y te puede traer complicaciones si usas WDT ademas de desperdiciar recursos.

No se que tanto afecta a los módulos RF, supongo que te tendrás que comunicar por USART o por otro método con estos, entonces influiría el clock sobre el baudrate, tendrías que saber exactamente a que frecuencia va el CLK.

Mi consejo es que todas las librerías que te puedas ahorrar, ahorratelas picando código a mano, así luego cuando sigas el programa en depuración sabes exactamente que querías hacer, que esta haciendo y si se ajusta a lo que quieres.

Un saludo.

Zivit
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 30 de Abril de 2014, 01:11:33
El pic tiene una salida del clock interno, en la pata CLKO, prueba a configurarla para que saque el clock, pincha con un osciloscopio y mira que frecuencia te da. Así comprobaras si realmente funciona bien el oscilador. Luego respecto a la función delay(ms), si quieres te la puedes hacer tu mismo, si sabes la frecuencia del reloj, sabes cuanto dura una instrucción, simplemente tienes que hacer una espera de tantas instrucciones (calculas con la formulita). Luego la compruebas con un simulador y calibras el numero de instrucciones para que te clave los ms que le indiques.

También lo puedes calibrar en un timer. Al fin y al cabo un delay provoca la retención del hilo del programa y te puede traer complicaciones si usas WDT ademas de desperdiciar recursos.

No se que tanto afecta a los módulos RF, supongo que te tendrás que comunicar por USART o por otro método con estos, entonces influiría el clock sobre el baudrate, tendrías que saber exactamente a que frecuencia va el CLK.

Mi consejo es que todas las librerías que te puedas ahorrar, ahorratelas picando código a mano, así luego cuando sigas el programa en depuración sabes exactamente que querías hacer, que esta haciendo y si se ajusta a lo que quieres.

Un saludo.

Zivit

gracias por tu respuesta, creo que tienes razon sobre el delay, aunqeu ahora mismo lo que mas me preocua es la comunicacion, tendre que comprarme lso modulitos para probar y ver que tanto me afecta el hecho de que funcione igual con  sin oscilador.

Si alguien tiene alguna explicacion sobre porque me funciona el programa aun sin ocilador y con la configuración de crystal les agradeceria que me lo explicaran
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: BrunoF en 02 de Mayo de 2014, 15:13:52
Funciona igualmente aún sin oscilador porque evidentemente está habilitado el FUSE IESO, que al no detectar cristal externo o detectar un error en el mísmo, cambia al oscilador interno automáticamente.

Saludosl
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 02 de Mayo de 2014, 17:11:10
Funciona igualmente aún sin oscilador porque evidentemente está habilitado el FUSE IESO, que al no detectar cristal externo o detectar un error en el mísmo, cambia al oscilador interno automáticamente.

Saludosl

Hola BrunoF, gracias por tu respuesta, no sabia de la existencia de ese registro, ya revise el datasheet y pude comprobar su utilidad, aunque no logre encontrar si esta activado por default, en todo caso, como podría hacer para desactivarlo, simplemente con poner FUSE IESO =off ??? o de que manera??

gracias
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 02 de Mayo de 2014, 17:40:43
ya encontre como deshabilitarlo 
Código: [Seleccionar]
#FUSES NOIESO

en la noche probare hacer esto haber si se resuelve la interrogante de que funciona sin oscilador, mm pero aun sigo sin entender porque mis delay no duran lo que deberian, BrunoF sabras por que sucede esto????
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: BrunoF en 10 de Mayo de 2014, 21:37:55
Creería que es porque el microcontrolador está oscilando a una frecuencia distinta a la deseada.

Pudiste probar el fuse NOIESO?

Saludos
Título: Re: problema con delay_ms(1000); no da la espera de 1 seg.
Publicado por: urielm80 en 11 de Mayo de 2014, 01:50:07
Creería que es porque el microcontrolador está oscilando a una frecuencia distinta a la deseada.

Pudiste probar el fuse NOIESO?

Saludos

Hola BrunoF, si pude probar con el fuse NOIESO y se resolvió el problema, el delay ahora si dura 1 segundo y si le quito el oscilar ahi es cuando el delay dura mas de lo debido, asi que tenias razón y debido a que no tenia ese fuse estaba teniendo un comportamiento no deseado al modificar la frecuencia de trabajo, muchísimas gracias BrunoF y a todos los que me ayudaron, aprende mucho y podre seguir con mi proyecto, y como había comentado en otro post, cuando termine subiré todo el proyecto para que lo puedan aprovechar, saludos