TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: cucu en 30 de Abril de 2009, 06:03:08

Título: dudas con punteros
Publicado por: cucu en 30 de Abril de 2009, 06:03:08
hola, quería preguntar que hace esta instrucción, sé que tiene algo que ver con los punteros... pero por más que miro no lo entiendo:

Código: [Seleccionar]

    TxBuffer[TxData++] = estructura.direccion[0]->entrada1;
    TxBuffer[TxData++] = estructura.direccion[0]->entrada2;

estructura.direccion[0] tiene almacenado 0x0119, que tiene un 0x00, pero... ¿eso no es memoria RAM? de todos modos, ambos parámetros apuntarían al mismo valor, pero en TxBuffer los valores son los correctos.


Programo en C18 y tengo un pic 18f4620

Gracias. saludos

 

 

Título: Re: dudas con punteros
Publicado por: gera en 30 de Abril de 2009, 09:58:21
Este es un caso de estructura de una estructura. Vos tenes una estructura q se llama "estructura", y a la vez un elemento de esa estructura es direccion[0] es otra estructura. Dentro de esta ultima, hay un puntero "entrada1" y otro "entrada2", que apuntan a distintos lugares. El operador -> significa q estamos accediendo al valor q apunta un elemento de la estructura. Osea q el valor q estas cargando en TxBuffer[TxData++] en la primera linea, es el valor al q esta apuntando entrada1.
Espero q se haya entendido, cualquier cosa pregunta.
Saludos!
Título: Re: dudas con punteros
Publicado por: MLO__ en 01 de Mayo de 2009, 01:26:13
 :z) changos
Título: Re: dudas con punteros
Publicado por: gera en 01 de Mayo de 2009, 11:08:34
Si no se entendio avisenme y les doy un ejemplo o algo.. bah, se los doy de todos modos jeje.
Supongamos q tenemos las siguientes estructuras
Código: C
  1. struct punto {
  2.    int x;
  3.    int y;
  4. };
  5.  
  6. struct {
  7.   int x;
  8.   char * string;
  9.   struct punto pto;
  10. } str, *ptr = &str;

Vemos que punto es una estructura comun y corriente que contiene dos enteros. Y str es una estructura que contiene un entero, un puntero a char, y una estructura de tipo punto. Al final de la definicion de str, creamos una estructura de este tipo, y un puntero a esta.
Entonces, si queremos acceder a los elementos de la estructura directamente, podemos hacer esto:
Código: C
  1. str.x = 30;
  2. str.string = "Hola mundo";
  3. str.pto.x = 2;
  4. str.pto.y = 3;

Hasta aca no he dicho nada nuevo supongo. Ahora vamos a ver como accedemos a los elementos de la estructura a traves del puntero a apunta a esta:
Código: C
  1. ptr->x = 30;
  2. ptr->str = "Hola mundo";
  3. ptr->pto.x = 2;
  4. ptr->pto.y = 3;

Vemos que en este caso, tenemos q usar el operador ->, que significa q vamos a acceder al contenido de la estructura a la cual apunta el puntero. Seria parecido al * cuando usamos punteros a variables.
Esto es muy util cuando tenemos q pasar a una funcion una estructura como parametro, simplemente pasamos un puntero a esta :wink:
Bueno, espero q se haya entendido mejor. Cualquier duda pregunten :)
Título: Re: dudas con punteros
Publicado por: migsantiago en 01 de Mayo de 2009, 11:59:55
Hey Gera. ¿Se puede hacer esto en C?

str.string = "Hola mundo";
Título: Re: dudas con punteros
Publicado por: MLO__ en 01 de Mayo de 2009, 12:43:25
Mucho mas claro ... como se aprende ... cooomo se aprende.

Vamos a ver si el CC$ deja hacer tantas bellezas

Saludos y gracias GERA
Título: Re: dudas con punteros
Publicado por: gera en 01 de Mayo de 2009, 12:56:36
Hey Gera. ¿Se puede hacer esto en C?

str.string = "Hola mundo";

Santi, si se puede. La cadena "hola mundo" esta cargada en memoria, ya que es una constante q usa nuestro programa, al hacer esa igualacion, decimos q el puntero string apunte a ese lugar de memoria.
Lo q no se puede hacer es lo siguiente:
Código: [Seleccionar]
char string[16];
string="hola";
Ya que en este caso string es un puntero estatico. No podemos hacer q apunte a otro lugar q no sea el q le fue asignado. Por lo tanto, si queremos q apunte a un "hola", tenemos q copiar esa cadena a su espacio de memoria.
Saludos!!
Título: Re: dudas con punteros
Publicado por: pajaro en 02 de Mayo de 2009, 16:47:31
Hola Gera

¿puedes explicar un poco mas detallado esto de las estructuras en ccs?.

Gracias.
Un Saludo
Título: Re: dudas con punteros
Publicado por: gera en 02 de Mayo de 2009, 17:32:46
Hola pajaro,
cual es especificamente tu duda? Las estructuras en CCS son iguales a las estructuras de cualquier otro compilador. Si no tenes claro el tema de estructuras, en internet podes encontrar infinidad de cursos de programacion donde dedican capitulos enteros a las estructuras. Cualquier duda puntual q te surja pregunta.
suerte!
Título: Re: dudas con punteros
Publicado por: cucu en 04 de Mayo de 2009, 03:32:27
Genial! gracias, me he enterado por fin de lo que significa ->.

Ahora otra dudilla relacionada aunque igual es más de uso de la memoria... si es así decirme y lo pongo en otro sitio...

Yo con punteros normales en MPLAB puedo ver lo que contiene, veo a que posición de memoria apunta, la busco en el mapa de memoria y ya está.

¿Con este tipo de estructuras, se haría igual? Eso es lo que supongo pero después todas me apuntan a la dirección 0.

De nuevo gracias por la ayuda. Saludos
Título: Re: dudas con punteros
Publicado por: gera en 04 de Mayo de 2009, 11:05:10
Hola cucu,
me alegro haber aclarado tu duda. Cuando un puntero contiene 0, se dice q es un puntero a NULL y no apunta a ningun lado. Cuando se declara un puntero se lo suele inicializar con este valor para evitar tocar posiciones de memoria basura. Supongo q MPLAB por defecto los inicializa asi. Cuando le asignas una posicion de memoria al puntero, sigue siendo nulo?
Título: Re: dudas con punteros a constantes
Publicado por: Suky en 24 de Enero de 2010, 22:47:23
Tengo el siguiente problema con los punteros. Hago este ejemplo en C18 y funciona sin inconvenientes:

Código: C
  1. const rom char Buffer[30]="Hola mundo cruel...:(";
  2.  
  3.  
  4. void funcion(const rom char *ptr){
  5.         ....
  6. }
  7.  
  8. void main(){
  9.    funcion(Buffer);

Pero lo hago en CCS y no me deja compilarlo  :5]

Código: C
  1. const char Buffer[30]="Hola mundo cruel...:(";
  2.  
  3.  
  4. void funcion(const char *ptr){
  5.  
  6.         ....
  7. }
  8.  
  9.  
  10. void main(){
  11.  
  12.    funcion(Buffer);

La idea era tener varios buffer constantes, y que la función trabaje con alguno de ellos dependiendo del caso, pero el CC$ no me deja  :? Como se podría hacer ?


Saludos!
Título: Re: dudas con punteros
Publicado por: migsantiago en 24 de Enero de 2010, 22:58:08
Hola, ¿qué error te arroja ccs? Creo que es el típico de "no se permiten apuntadores a rom".
Título: Re: dudas con punteros
Publicado por: BrunoF en 24 de Enero de 2010, 23:03:52
Seguramente es porque en la mayoria de las versiones(anteriores) del CCS, los arrays constantes son ubicados en la ROM.

Lamentablemente los punteros solo pueden apuntar a la RAM. Falla porque estas intentando guardar en un puntero RAM, una posicion ROM.

En las versiones nuevas del CCS, se ha agregado la opcion de poder cargar en RAM los arrays constantes automaticamente, de manera "transparente" para el programador.

Cuando yo en CCS tengo que trabajar con varias cadenas constantes, hago un solo array y ubico alli dentro todos juntos. Como por lo general suelen ser de tamaño distinto, genero otro array que contiene las posiciones inicial y final de cada uno dentro del array que contiene a todos.

Ejemplo:

Código: C
  1. #DEFINE str_emergencia      0
  2. #DEFINE str_confirma          1
  3. #DEFINE str_modo_grafico   2
  4.  
  5. const unsigned int16 indice_strings[] = {0,93,168,180};
  6.  
  7. const char strings[] = {"\"Modo Recuperacion de emergencia\" Presione la tecla A para Cancelar o la tecla B para Aceptar¿Esta seguro? Presione la tecla A para Cancelar o la tecla B para ConfirmarModo grafico"};
  8.  
  9. void imprimeString(char nroString){
  10.       unsigned int16 i;
  11.      char c;
  12.  
  13.       for(i=indice_strings[nroString];i<indice_strings[nroString+1];i++){
  14.           c=strings[i];
  15.           printf("%c",c);
  16.      }
  17.          printf("\r\n");
  18.        //....
  19. }
  20.  
  21. //ejemplo de uso:
  22. imprimeString(str_confirma);

Hay otras posibilidades también. Desde más sencillas hasta mas complejas.

Un saludo.
Título: Re: dudas con punteros
Publicado por: Suky en 24 de Enero de 2010, 23:11:53
Osea que no puedo utilizar punteros a variables que están en la ROM en CCS, ouch! pequeño gran problema  :D Bueno, lo voy hacer en C18 que no da problemas  :mrgreen:

Es buena la idea que das Bruno, pero se le dan muchas vueltas para algo tan sencillo.


Saludos!
Título: Re: dudas con punteros
Publicado por: BrunoF en 24 de Enero de 2010, 23:17:32
Osea que no puedo utilizar punteros a variables que están en la ROM en CCS, ouch! pequeño gran problema  :D

Nop. Al menos no que yo conozca. Obviamente podrias trabajarlo en ASM y esquivar las restricciones del CCS, aunque creo que hacer esa combinacion con el ya inestable CCS, no es recomendable...


Es buena la idea que das Bruno, pero se le dan muchas vueltas para algo tan sencillo.

:D Uno hace lo que puede, dentro de lo que el lenguaje le permite! Si tenes la posibilidad de hacerlo con C18 y te parece mejor, ni lo dudes! :D
Título: Re: dudas con punteros
Publicado por: Suky en 24 de Enero de 2010, 23:23:26
Es buena la idea que das Bruno, pero se le dan muchas vueltas para algo tan sencillo.

:D Uno hace lo que puede, dentro de lo que el lenguaje le permite! Si tenes la posibilidad de hacerlo con C18 y te parece mejor, ni lo dudes! :D

 :D :D Muchas gracias Bruno!! Voy a ver que hago, siempre apunto a usar  CCS porque lo que se comparte le sirve a mas usuarios, C18 se usa poco.  :?


Saludos!

Título: Re: dudas con punteros
Publicado por: Suky en 12 de Agosto de 2010, 13:14:49
Tengo un problemita trabajando con punteros en C18  :? Defino, por ejemplo, el siguiente tipo de estructura:
Código: C
  1. typedef struct{
  2.     UINT8       OUTPUT;
  3.     float       OUTPUT_VALOR;
  4.     UINT8       STATUS;
  5. }OBJECTS_ANALOG_OUTPUT;

En una función creo un array de estructuras, cargo sus valores y la entrego por referencia a otra función declarada de la siguiente forma:
Código: C
  1. void vFuncion(....,OBJECTS_ANALOG_OUTPUT *ObjectsParameters);

El problema surge cuando intento, en esta última función, dividir la variable float en sus bytes:

Código: C
  1. LB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR);
  2. HB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+1);
  3. UB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+2);
  4. MB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+3);

Pensé que era lo adecuando pero el compilador me dice:
Citar
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
:D :D

Y yo, ya me perdí!  :D

Saludos!




Título: Re: dudas con punteros
Publicado por: migsantiago en 12 de Agosto de 2010, 13:30:47
Hola Suky

Probá así... (jaja ahora soné como argentino  :D )

Código: [Seleccionar]
void vFuncion(....,OBJECTS_ANALOG_OUTPUT *ObjectsParameters, ...)
{
UINT8 byte3, byte2, byte1, byte0; //MSB a LSB
UINT8 *apuntador;

...

apuntador = (UINT8 *)&ObjectsParameters[k].OUTPUT_VALOR;
byte0=*(apuntador); //little endian
byte1=*(apuntador + 1);
byte2=*(apuntador + 2);
byte3=*(apuntador + 3);
}
Título: Re: dudas con punteros
Publicado por: Suky en 12 de Agosto de 2010, 13:38:09
Naaa! No vale, creaste otra variable  :D Así ya lo había arreglado, pero no queria dar el brazo a torcer  :mrgreen:


Gracias Santiago!  ;-)
Título: Re: dudas con punteros
Publicado por: migsantiago en 12 de Agosto de 2010, 13:51:32
Bueno, C internamente también creará otra variable para almacenar el apuntador temporal usando tu pseudo-código. Además, un apuntador en un PIC18 sólo emplea 2 bytes de RAM. ;)

En tu código veo dos problemas.

Código: [Seleccionar]
   1.
      LB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR);
   2.
      HB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+1);
   3.
      UB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+2);
   4.
      MB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+3);

Al poner OUTPUT_VALOR+1 o OUTPUT_VALOR+2 no estás modificando la dirección RAM de OUTPUT_VALOR, estás modificando su valor Flotante.

Si luego haces un casting (UINT8 *) entonces estás copiando exactamente la misma dirección RAM de OUTPUT_VALOR pero en cada línea te dará un resultado diferente por lo que te comento arriba.

Suerte  :mrgreen:
Título: Re: dudas con punteros
Publicado por: Suky en 12 de Agosto de 2010, 13:58:09
Bueno, C internamente también creará otra variable para almacenar el apuntador temporal usando tu pseudo-código. Además, un apuntador en un PIC18 sólo emplea 2 bytes de RAM. ;)


Es cierto  :? Entonces da lo mismo!  :oops:
En tu código veo dos problemas.
Código: [Seleccionar]
   1.
      LB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR);
   2.
      HB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+1);
   3.
      UB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+2);
   4.
      MB=*((UINT8*)ObjectsParameters[k].OUTPUT_VALOR+3);

Al poner OUTPUT_VALOR+1 o OUTPUT_VALOR+2 no estás modificando la dirección RAM de OUTPUT_VALOR, estás modificando su valor Flotante.

Si luego haces un casting (UINT8 *) entonces estás copiando exactamente la misma dirección RAM de OUTPUT_VALOR pero en cada línea te dará un resultado diferente por lo que te comento arriba.

Nop! fíjate los parentesis  :mrgreen: Y acuérdate que es un puntero  ;-)

Saludos!

Título: Re: dudas con punteros
Publicado por: migsantiago en 12 de Agosto de 2010, 14:06:42
Sí, sí, tenés razón ( :mrgreen: )

Entonces si quieres imaginar que estás ahorrándote una variable, corrijamos tu código...

Código: [Seleccionar]

      LB=*((UINT8*)&ObjectsParameters[k].OUTPUT_VALOR);

      HB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 1);

      UB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 2);

      MB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 3);

Para la segunda línea, una interpretación sería:

- Extrae la dirección RAM de OUTPUT_VALOR.
- Interpreta la dirección RAM como un apuntador a un entero de 1 byte (casting).
- Le suma 1, pero como es apuntador entonces le suma el número de bytes que ocupa la variable. En este caso al ser un byte, pues la suma es dirección RAM + 1.
- El * pide que el contenido de la dirección RAM sea leído y asignado a HB.

Creo que sólo faltaban los ampersands.
Título: Re: dudas con punteros
Publicado por: Suky en 12 de Agosto de 2010, 14:16:03
Sí, sí, tenés razón ( :mrgreen: )

Entonces si quieres imaginar que estás ahorrándote una variable, corrijamos tu código...

Código: [Seleccionar]

      LB=*((UINT8*)&ObjectsParameters[k].OUTPUT_VALOR);

      HB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 1);

      UB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 2);

      MB=*( (UINT8*)&ObjectsParameters[k].OUTPUT_VALOR + 3);

Para la segunda línea, una interpretación sería:

- Extrae la dirección RAM de OUTPUT_VALOR.
- Interpreta la dirección RAM como un apuntador a un entero de 1 byte (casting).
- Le suma 1, pero como es apuntador entonces le suma el número de bytes que ocupa la variable. En este caso al ser un byte, pues la suma es dirección RAM + 1.
- El * pide que el contenido de la dirección RAM sea leído y asignado a HB.

Creo que sólo faltaban los ampersands.


 :-/  :-/ Exactamente, había creado otro proyecto más sencillo para poder hacer un debug  :mrgreen:

Código: C
  1. void vFuncion(OBJECTS_ANALOG_OUTPUT *Ptr){
  2. char LB, HB, UB, MB;
  3.  
  4.     LB=*((char *)&Ptr->OUTPUT_VALOR);
  5.     HB=*((char *)&Ptr->OUTPUT_VALOR+1);
  6.     UB=*((char *)&Ptr->OUTPUT_VALOR+2);
  7.     MB=*((char *)&Ptr->OUTPUT_VALOR+3);
  8.         Nop();
  9.  
  10. }


Así funciona! (Va el operador -> y no el ., eso lo indicó el compilador  :mrgreen: ) Estoy feliz, ahorro una variable en la RAM  :D :D :D Mejor me pongo a trabajar en algo en serio  :D

Gracias Mig  ;-)


Saludos!
Título: Re: dudas con punteros
Publicado por: gera en 12 de Agosto de 2010, 21:14:03
Claro, cuando queres acceder a un elemento de una estructura apuntada se usa ->. Nunca entendi por q la complicaron asi jeje.
suerte!!