TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: jezus en 27 de Agosto de 2009, 21:33:08

Título: Funciones
Publicado por: jezus en 27 de Agosto de 2009, 21:33:08
Tengo una duda....¿en C,es correcto llamar a una función desde otra función?
Título: Re: Funciones
Publicado por: MLO__ en 27 de Agosto de 2009, 22:01:27
Si claro que se puede.

De hecho, en ANSI C se puede llamar la funcion desde la misma funcion -recursividad- ... pero en CCS naaaa -o ya se puede?-

Saludos
Título: Re: Funciones
Publicado por: fabianjsm en 27 de Agosto de 2009, 22:22:29
Claro! Si llamas a una funcion que se define después (más abajo pero en el mismo archivo) es necesario declararla antes especificando su prototipo, y si la funcion se define externamente (en otro fuente C o ya compilado en una libreria que pudo ser escrita en C, pascal, asm o cualquier lenguaje) debes anteponer la palabra reservada 'extern' al prototipo (todo esto si el compilador es ANSI C, los demas tienen sus reglas). En cuanto a la recursividad, hay que tener en cuenta que la pila del PIC solo tiene seis niveles y muchos compiladores no te permiten o te permiten advirtiendote con un warning que debes tener cuidado.
Título: Re: Funciones
Publicado por: MLO__ en 27 de Agosto de 2009, 22:40:40
Hola Fabian.

Respecto a lo que mencionas, me causa mucha curiosidad lo que dices acerca de que puede llamar a una función que ha sido compilada desde otro archivo fuente. Como sería el manejo de ese tipo de funciones?
Título: Re: Funciones
Publicado por: pajaro en 28 de Agosto de 2009, 10:56:30
Hola amigos

El compañero dijo llamar a una funcion, desde otra, creo que hay una diferencia con respecto a la recursividad que consiste en que una funcion se llama a si misma.

int suma(int a, int b)
{
int c;
c=a+b;
retun(c);
}

////una funcion llama a otra
void resultado()
{
suma1(5,4);
}

//la funcion se llama a si misma.

suma1(suma1(2,3),5);

para la recursividad creo que habia una forma, porque se trabajaba con la pila, la recursivada la mirare un dia de estos mas a fondo.  


de todas formas yo tambien tuve problemas con con esto de las funciones en CCS.

tengo una pregunta?.

como le pasas a una una funcion mas de un valor desde otra funcion, si cuando termina la ejecucion de la primera las varibles parciales desaparecen.

y me reservo dos preguntas más si contestan a esta.

Un saludo.
Título: Re: Funciones
Publicado por: Suky en 28 de Agosto de 2009, 11:31:35
No se si entendí la pregunta, pero una forma de devolver mas de un resultado sería:

Código: C
  1. int Lee_dispositivo(char& Valor1, long& Valor2, int32& Valor3);
  2. void Funcion_x(void);
  3.  
  4.  
  5. void Funcion_x(void){
  6. char A;
  7. long B,
  8. int32 C;
  9.     .
  10.     .
  11.     .
  12.     if(Lee_Dispositivo(A,B,C)==0){
  13.         return(0); //Error.-
  14.     }
  15. }
  16. int Lee_dispositivo(char& Valor1, long& Valor2, int32& Valor3){
  17.     .
  18.     .
  19.     .
  20.      Valor1=read_disp();
  21.     .
  22.     .
  23.     .
  24.  
  25. }

Título: Re: Funciones
Publicado por: pajaro en 28 de Agosto de 2009, 12:15:11
No se si entendí la pregunta, pero una forma de devolver mas de un resultado sería:

Código: C
  1. /////declaro cabecera funcion
  2. int Lee_dispositivo(char& Valor1, long& Valor2, int32& Valor3);     //le pasas y te devuelve
  3. void Funcion_x(void);                    //no le pasas ni te devuelve, nada solo llamas a la otra función
  4.  
  5. /////funcion principal o de llamada
  6. void Funcion_x(void)
  7.   {
  8.       char A; //
  9.       long B,
  10.       int32 C;
  11.     .
  12.     .
  13.     .
  14.     if(Lee_Dispositivo(A,B,C)==0)      //si no le pasaste nada, es decir a=0,b=0,c=0  te devuelve 0
  15.        {
  16.           return(0);   //Error.-
  17.        }
  18.   }
  19.  
  20. /////////////funciones
  21. int Lee_dispositivo(char& Valor1, long& Valor2, int32& Valor3)
  22.  {
  23.     .
  24.     .
  25.     .
  26.      Valor1=read_disp();
  27.     .
  28.     .
  29.     .
  30.  
  31. }



Hola suky

Deduzco que para que las variables parcieles no se pierdan lo que haces es anidar funciones.
Entonces para poder conectar la salida multiple de una funcion (su retorno) a la entrada de otra necesitariamos una tercera.
se puede retornar mas de un valor?

pero si se deja de estar en ejecucion la funcion y no exportas dato, que es lo que recibira la otra funcion, no se perdera por el camino.
voy a probar unas ideas..


Un saludo,

nota: las otras dos preguntas no las olvide jejeje... cachito a cachito.


Título: Re: Funciones
Publicado por: Suky en 28 de Agosto de 2009, 12:28:23
Si mejor proba, porque no te entendí  :mrgreen:  :D
Título: Re: Funciones
Publicado por: cerebro en 28 de Agosto de 2009, 12:37:17
Hola Fabian.

Respecto a lo que mencionas, me causa mucha curiosidad lo que dices acerca de que puede llamar a una función que ha sido compilada desde otro archivo fuente. Como sería el manejo de ese tipo de funciones?

Como una DLL, que las funciones se linkean en tiempo de ejecución.... (creo que a eso se hace referencia).... la directiva extern  se utiliza por ejemplo si planteamos una libreria de funciones en c++ y vamos  a utilizarlas en C por lo general se suelen poner mas de una directiva para aumentar la compatibilidad entre compiladores.
Título: Re: Funciones
Publicado por: pajaro en 28 de Agosto de 2009, 13:55:01
hola cerebro

Una cosa, extern solo lo vi antes en los script de linux, y desconozco si el uso en c y en ccs es el mismo.

En linux si tememos un script "pepito" este será el padre y este llama a otro script "juanito",
 si pepito tenía una variable c=5, cuando llamas desde "pepito" a "juanito" y "juanito" trabaja también con la misma variable de "pepito", cuando usa la variable   c   , con extern, la variable c , conserva el valor de "pepito" (proceso padre) si no se usa extern cuando llamamaos al proceso hijo, "juanito", su valor sera de c=0 o el que tenga scrip hijo.

Alguien sabe si el EXTERN en c y en ccs el uso es el mismo.
En compracion con linux.


Un saludo
 
Título: Re: Funciones
Publicado por: cerebro en 28 de Agosto de 2009, 14:10:46
hola cerebro

Una cosa, extern solo lo vi antes en los script de linux, y desconozco si el uso en c y en ccs es el mismo.

En linux si tememos un script "pepito" este será el padre y este llama a otro script "juanito",
 si pepito tenía una variable c=5, cuando llamas desde "pepito" a "juanito" y "juanito" trabaja también con la misma variable de "pepito", cuando usa la variable   c   , con extern, la variable c , conserva el valor de "pepito" (proceso padre) si no se usa extern cuando llamamaos al proceso hijo, "juanito", su valor sera de c=0 o el que tenga scrip hijo.

Alguien sabe si el EXTERN en c y en ccs el uso es el mismo.


Un saludo
 

estoy de acuerdo pero no era a lo que me estaba refiriendo..... yo estaba hablando de DLL y extern se utiliza, lo que no se si es a eso lo que hacia referencia fabian "o me fui por la tangente"...
Título: Re: Funciones
Publicado por: fabianjsm en 28 de Agosto de 2009, 16:44:07
Hola MLO__, parece que siempre nos encontramos en el foro.
La forma de trabajar con varios lenguajes es esta:
Compilas todos los codigos fuentes, obteniendo un codigo objeto por cada uno y luego enlazas a todos.
Obviamente, el enlazador debe reconocer el formato de cada objeto!
Los formatos más empleados para objetos son COFF y ELF. C30 por ejemlo soporta estos formatos.
Te paso un ejemplo utilizando C30.

Esta demás este comentario, pero pude ser de ayuda a alguien:

Con el compilador pic30-coff-as genero el OBJ con formato COFF a partir del fuente en ASM.
Con el compilador pic30-gcc genero el OBJ con formato COFF a partir del fuente en C.
Con el enlazador pic30-coff-ld enlazo a todos los anteriores en un solo binario.
Con el pic30-bin2hex cambio el formato del binario (para a ser hex).

Para trabajar con formato ELF las herramientas serian pic30-elf-as, etc (ver directorio BIN de C30).
Todo esto para C30, pero con otros lenguajes es lo mismo: compilar todo en el mismo formato OBJ y despues enlazar. También existen herramientas para convertir un formato OBJ en otro.

En realidad todos estos pasos siempre ocurren de forma transparente, incluso cuando solo tenemos un archivo escrito en C: finalmente todo es enlazado con crt0.o y alguna libreria que hubieramos empleado.

Las carpetas 01, 02 y 03 contienen lo mismo: primero los tres fuente, despues agregue un bat, y en el ultima ejecuta el bat.

A esta altura podemos concluir esto sobre el especificador extern: Sirve para indicar al compilador que toda referencia a dicha funcion deve resolverse durante el enlazado, porque la definición de la función talvez se encuentra en otro fichero (pero si se define en el mismo no esta mal, hice esto en la funcion llamada 'recursiva' en el ejemplo adjunto).

yo estaba hablando de DLL y extern se utiliza...

extern se utiliza para enlace estatico, no dinámico (DLL, Dynamic Link Library, biblioteca de enlace dinámico), y del enlace dinamico al micro pic hay un largo trecho compañero...

el EXTERN en c y en ccs el uso es el mismo.

Si bien CCS no es el ANSI C, extern se utliza de igual modo.

Esperamos poder ayudarte con todo esto jezus, tu iniciaste el hilo :-/
Título: Re: Funciones
Publicado por: Suky en 28 de Agosto de 2009, 17:10:19
mmm  :? Me parece que eso no es posible hacerlo con CCS.
Título: Re: Funciones
Publicado por: RICHI777 en 28 de Agosto de 2009, 17:51:45
Hola Fabian, esta todo perfecto lo que pusiste ! a mi entender solo falto aclarar algo. Cuando se trabaja en multiples lenguajes, aparte de las cosas que describiste, es necesario tener en cuenta cual es la convención de llamada o invocación de las funciones para que podamos usar funciones escritas en otro lenguaje, las mas conocidas aunque no todos los compiladores la soportan son estas:


Las mismas tratan de como el compilador coloca los parametros en el stack, puede ser de derecha a izquierda, a la inversa y el fastcall se intenta pasar parametros ( los que se puedan ) en los registros. Otra cosa tambien es quien se encarga de limpiar el stack a la salida de la funcion ( variables locales ) en C se encarga el llamador y en Pascal se encarga la propia función.

Saludos !
Título: Re: Funciones
Publicado por: fabianjsm en 28 de Agosto de 2009, 19:10:02
Gracias RICHI777, tenes razón, era uno de los detalles mas importante y ni lo mensione  :oops:

parece que eso no es posible hacerlo con CCS.
Para que el objeto generado tenga formato COFF se utiliza la opcion +DF (página 17 de ccs_c_maual.pdf).
Esto dice el manual de CCS sobre extern(página 50 de ccs_c_maual.pdf): External variable used with multiple compilation units.  No storage is allocated.  Is used to make otherwise out of scope data accessible.  there must be a non-extern definition at the global level in some compilation unit.
Desde la linea de comandos no es coplicado, y si son muchos archivos un script no viene mal.
Sobre como llamar al compilador desde la linea de comandos, tenes un ejemplo en la página 18 del manual. Nose como se configura el IDE porque no lo ocupo, deberias hacer la pruba y despues contarnos ;-)

En cuanto a las convensiones, en el caso particular de C30, se explica en la página 71 de MPLAB_C30user.pdf (4.13, function call conventions). La idea descrita es una pila implementada por software, ya que no esta disponible la tradicional pareja PUSH-POP para acceder directamente a la pila del hardware, almacenando los arguemntos en registros, asi como el valor de retorno. Algo similar se emplea en los micros pic pequeños, pero en vez del registro W se empleea los de proposito general. Existe ademas una convension de nombres: la funcion declarada como funcionx en C, es definida como _funcionx en ASM (algunos compiladores C suele agregar un guion bajo a todos los símbolos con liga externa).

Ahora si, creo que nos fuimos del hilo no?
Título: Re: Funciones
Publicado por: Suky en 28 de Agosto de 2009, 19:51:43
Gracias fabianjm por la aclaración  :-/ Como por ahora no lo necesito no voy hacer ninguna prueba  :D


Saludos!
Título: Re: Funciones
Publicado por: RICHI777 en 28 de Agosto de 2009, 21:25:57
Excelemte post Fabian ! con respecto a los scripts, mejor usar el make, yo soy un viejo que le gusta la linea de comandos mas que los IDE y configurar a full. Con respecto a la pila por software algo similar usan los compiladores para los 8051 como el manejo de stack es casi nulo, el compilador arma un arbol de ejecución y todas las variables locales y parametros son metidos ahi, en este tipo de arquitectura laburo padre para los que hacen compiladores.

Saludos !
Título: Re: Funciones
Publicado por: MLO__ en 29 de Agosto de 2009, 00:47:39
Bien Fabian, gracias por la aclaracion.

Para compilar los codigos fuente, normalmente se debe poner todo un conjunto de sentencias como los #include<xxxxx.h> de los micros y esas cosas. Debo hacerlo para cada uno de los .c que necesite, es que si se hace asi no mas, va tirar muchos errores no?

Segun el CCS si se pude hacer este tipo de cosas, con la directiva #IMPORT y en sus opciones mencionan los compiladores de C18, C30 y ASM. Según lo que me explicas -o mejor, según lo que entendí- el CCS si sirve para enlazar las funciones que vienen compiladas del C18, C30 o ASM no? Ojenado el directorio del CCS, hay un archivo ejecutable: ccscoff.exe:

(http://img55.imageshack.us/img55/8814/coff.png)

Es ese el enlazador?

Saludos
Título: Re: Funciones
Publicado por: fabianjsm en 30 de Agosto de 2009, 09:52:36
Los archivos que subi compilan sin ningun error o warning, en el directorio 03 esta el resultado.
Trabajando de igual modo en CCS si habrian varios errores como mensionas, hay que especificar el dispositivo con la directiva DEVICE, los arhchivos de cabecera nos dan una mano en eso.
Para compilar con ccs (generar el objeto):
    ccsc +EXPORT archivo.c
El objeto generado de este modo posee formato 'CCS Object File', creo que solo ccs los reconoce (no pueden ser enlazados con mplink por ejemplo).
Para enlazar varios objetos 'CCS Object File':
    ccsc LINK="salida.hex=uno.o,dos.o,tres.o"
Para utilizar objetos COFF en CCS, se los importa directamente en el codigo fuente con la directiva IMPORT

No se para que sirve ccscoff.exe  :(
Título: Re: Funciones
Publicado por: pajaro en 06 de Septiembre de 2009, 20:52:44
hola fabiamjm

Si mal no recuerdo, el ccsCof.exe te genera los ficheros de salida para la simulación en el Proteus, en modo debug,
ya que con el *.hex, no te deja simular en este modo.

Un saludo.
Título: Re: Funciones
Publicado por: MLO__ en 06 de Septiembre de 2009, 21:14:43
No, eso se hace con: +DF

Lo que creo que hace el .exe, es hacer que el .coff que viene del C18 sea compatible con el CCS.

Saludos
Título: Re: Funciones
Publicado por: fabianjsm en 07 de Septiembre de 2009, 01:28:59
Gracias pajaro, gugleando un poco verifique que estas en lo correcto.
Estoy siguiendo tu hilo 'DEV C++ desde cero', estare por cerca para opinar y colaborar en lo que pueda :-/