TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: KALLITOS en 22 de Mayo de 2009, 00:33:02

Título: Obtener el byte alto y byte bajo de un Int16
Publicado por: KALLITOS en 22 de Mayo de 2009, 00:33:02
Hola amigos, buscando en el foro encontre como pasar de int8 a int16 e int32, pero ahora me surge la duda de como obtener los dos bytes de un Int16.

Lo que pretendo hacer es por ejemplo hacer sumas sucesivas de un int16 y mostrar el byte alto en el puerto B y el byte bajo en el puerto D

Existe esta funcion en el CCS o hay que hacerla mnualmente, alguien sabe como?

Saludos.
Título: Re: Obtener los dos byte de Int16
Publicado por: Suky en 22 de Mayo de 2009, 00:42:34
Código: C
  1. int8 Data_h, Data_L;
  2. int16 DataLong;
  3.  
  4. Data_H=make8(DataLong,1);
  5. Data_L=make8(DataLong,0);
Título: Re: Obtener los dos byte de Int16
Publicado por: BrunoF en 22 de Mayo de 2009, 00:45:31
O por truncado:

Código: C
  1. int8 Data_h, Data_L;
  2. int16 DataLong;
  3.  
  4. Data_H=make8(DataLong,1);
  5. Data_L=DataLong;
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: ASTROCAR en 22 de Mayo de 2009, 07:42:12
Hola buenos dias en este post tambien hay informacion referente a lo tratado aca, si gusta puedes revisarlo.
http://www.todopic.com.ar/foros/index.php?topic=26043.0

Saludos.
Atten.
Alexander Santana.
Barcelona-Venezuela.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Nocturno en 22 de Mayo de 2009, 08:47:17
El make8 sólo funciona con CCS. A mí me gusta más hacerlo de esta manera que es ANSI C:

Código: C
  1. int8 Data_H, Data_L;
  2. int16 DataLong;
  3.  
  4. Data_H=DataLong>>8;
  5. Data_L=DataLong & 0xFF;

Aunque si el truncado funciona como dice Bruno el programa es más sencillo, pero ojo, luego te puedes volver loco para entenderlo.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: migsantiago en 22 de Mayo de 2009, 12:16:04
El make8 sólo funciona con CCS. A mí me gusta más hacerlo de esta manera que es ANSI C:

Código: [Seleccionar]
int8 Data_H, Data_L;
int16 DataLong;
 
Data_H=DataLong>>8;
Data_L=DataLong & 0xFF;

Aunque si el truncado funciona como dice Bruno el programa es más sencillo, pero ojo, luego te puedes volver loco para entenderlo.


Cuidado Nocturno, acuérdate que ese tipo de instrucciones son lentas y en estos días de mini-concursos no nos podemos dar el lujo de gastar más microsegundos.  :mrgreen:

Cada rotación de bit implica más de una instrucción en ensamblador y MAKE8 solo usa 2 instrucciones máximo. Pero hice un descubrimiento, CCS optimizó el código e ignoró las 8 rotaciones e incluso ignoró la AND que aplicas:

Código: [Seleccionar]
.................... DataLong=0x0000;
0010:  BCF    03.5
0011:  CLRF   22
0012:  CLRF   21
.................... Data_H=0x01;
0013:  MOVLW  01
0014:  MOVWF  23
.................... Data_L=0x02;
0015:  MOVLW  02
0016:  MOVWF  24
.................... 
.................... //Proceso lento
.................... Data_H=DataLong>>8;
0017:  MOVF   22,W
0018:  MOVWF  23
.................... Data_L=DataLong & 0xFF;
0019:  MOVF   21,W
001A:  MOVWF  24
.................... 
.................... //Optimizado en ensamblador
.................... Data_H=make8(DataLong,1);
001B:  MOVF   22,W
001C:  MOVWF  23
.................... Data_L=DataLong; //casting implícito
001D:  MOVF   21,W
001E:  MOVWF  24

Por lo que el código MAKE8 y el código de rotaciones de Nocturno son exactamente lo mismo... después de ser optimizados.

Pero si el compilador no es optimizado habrá que buscar una instrucción integrada del compilador que haga el trabajo rudo más rápido como MAKE8.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Suky en 22 de Mayo de 2009, 12:27:15
Muy buena data Migsantiago! Les hace bien los concursos  :D  :D  :D
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Nocturno en 22 de Mayo de 2009, 12:35:08
Pues si no me lo llegas a decir, yo habría pensado que la rotación >>8 se comportaba como el make8. Lo he visto muchas veces en CCS y he visto que es muy eficiente, pero claro, no sabía que el resto de los compiladores lo compilaba de otra manera. Gracias por el dato.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: BrunoF en 22 de Mayo de 2009, 13:58:25
El make8 sólo funciona con CCS. A mí me gusta más hacerlo de esta manera que es ANSI C:

Código: [Seleccionar]
int8 Data_H, Data_L;
int16 DataLong;
 
Data_H=DataLong>>8;
Data_L=DataLong & 0xFF;

Aunque si el truncado funciona como dice Bruno el programa es más sencillo, pero ojo, luego te puedes volver loco para entenderlo.


Cuidado Nocturno, acuérdate que ese tipo de instrucciones son lentas y en estos días de mini-concursos no nos podemos dar el lujo de gastar más microsegundos.  :mrgreen:

Cada rotación de bit implica más de una instrucción en ensamblador y MAKE8 solo usa 2 instrucciones máximo. Pero hice un descubrimiento, CCS optimizó el código e ignoró las 8 rotaciones e incluso ignoró la AND que aplicas:

Código: [Seleccionar]
.................... DataLong=0x0000;
0010:  BCF    03.5
0011:  CLRF   22
0012:  CLRF   21
.................... Data_H=0x01;
0013:  MOVLW  01
0014:  MOVWF  23
.................... Data_L=0x02;
0015:  MOVLW  02
0016:  MOVWF  24
.................... 
.................... //Proceso lento
.................... Data_H=DataLong>>8;
0017:  MOVF   22,W
0018:  MOVWF  23
.................... Data_L=DataLong & 0xFF;
0019:  MOVF   21,W
001A:  MOVWF  24
.................... 
.................... //Optimizado en ensamblador
.................... Data_H=make8(DataLong,1);
001B:  MOVF   22,W
001C:  MOVWF  23
.................... Data_L=DataLong; //casting implícito
001D:  MOVF   21,W
001E:  MOVWF  24

Por lo que el código MAKE8 y el código de rotaciones de Nocturno son exactamente lo mismo... después de ser optimizados.

Pero si el compilador no es optimizado habrá que buscar una instrucción integrada del compilador que haga el trabajo rudo más rápido como MAKE8.

Yo considero que si bien puede ser visto positivamente como una optimización, me parece completamente negativo por otro lado que el CCS optimice de ese modo el código. Técnicamente debería respetar a rajatabla al ANSI C y realizar las rotaciones(lo mísmo con la AND). Entiendo que nosotros estemos contentos por la optimización, pero desde el punto de vista de la estandarización, no me parece correcto. Lo digo porque, por ejemplo, tal vez alguien está migrando código C al uC y espera que dicha operación(rotación>>8) demore cierta cantidad de instrucciones o, tal vez, afecte a ciertos flags(como el STATUS,C).

Un saludo.

Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: migsantiago en 23 de Mayo de 2009, 11:36:15
Buscando en la ayuda de CCS encontré la forma de modificar el nivel de optimización:

Citar
#OPT
--------------------------------------------------------------------------------
Syntax:
 #OPT n
 
Elements:
 All Devices:  n is the optimization level 0-9
PIC18XXX:    n is the optimization level 0-11
 
Purpose:
 The optimization level is set with this directive.  This setting applies to the entire program and may appear anywhere in the file.  The PCW default is 9 for full optimization.  PIC18XXX devices may utilize levels 10 and 11 for extended optimization.  Level 9 may be used to set a PCW compile to look exactly like a PCM compile for example.  It may also be used if an optimization error is suspected to reduce optimization. 
 
Examples:
 #opt 5

Así que pidiéndole una optimización nula (#opt 0) y compilando el mismo ejemplo yo pensaba que haría las 8 rotaciones... pero no, no las hizo, optimizó el código de todas formas quedando el ensamblador como en el primer ejemplo.

Desconozco si ANSI C incluye optimizaciones obligatorias como la rotación de múltiplos de 8 bits que equivale a un byte fácilmente movible de memoria ram, pero como comenta Bruno, tal vez uno quiere que se haga la rotación para consumir más tiempo o levantar banderas.

Por otro lado, existen funciones de generación de tiempos bien definidas (delay_xx), y el acceso a banderas de estado es innecesario en el lenguaje C por lo que todavía veo útil la optimización obligatoria.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: KALLITOS en 23 de Mayo de 2009, 22:54:50
Ok amigos, gracias a tooooodos  :mrgreen:

Muchas gracias por responder, es justo lo que buscaba, además parece que va a servirle a muchos.

Saludos!!
Título: Primero read luego write
Publicado por: Berto en 18 de Septiembre de 2015, 13:46:24
Hola a todos Necesito mandar un INT16 a otro micro madiante protocolo SPI El problema es que nisiquiera logro partirlo en 2 INT8 Las instrucciones en este
o cualquier otro foro parecen simples pero llevo ya 3 dias con lo mismo y nada funciona Esto es lo que e probado entre otras cosas:

//DECLARACIONES
int16 pru1=1320;                   
int8 v8,v16;   
int8 posicion;

//......................................

v8=make8(pru1,0);
v16=make8(pru1,1);

//FRACASO 2.................................

posicion=&pru1
v8=make8(posicion,0);
v16=make8(posicion,1);

//FRACASO 3................................

v8=make8(*(&pru1),0);
v16=make8(*(&pru1),1);

//FRACASO 4................................

v8=pru1>>8;
v16=pru1 & 0xff;

//En todos los casos el RESULTADO ES V8=40  V16=5

Me gustaria saber que es lo que hago mal ¿make8 necesita alguna libreria? E oido ablar de macros en referencia a make16
desde luego el que yo e hecho en make8 no es valido      #define make8(Variable,Bit)  *(&Variable+Bit)
Si fuese por esto cual es el macro adecuado para lo que yo necesito

saludos
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: RALF2 en 18 de Septiembre de 2015, 14:01:50
Yo probe esto y funciona en CCS.

Citar
#include <18F252.h>
#device adc=10

#fuses XT, nowdt,
#use delay(clock= 4000000)     //Ajusta las rutinas de retardo para operar a 32Mhz( 4 x 8Mhz), con el pll activado

#use RS232(baud=9600,xmit=pin_c6,rcv=pin_c7)

void main()
{
   int16 dato= 0x3479;
   int low_long, high_long;
   
   low_long= make8(dato,0);
   high_long= make8(dato,1);
   
   printf("%X %X", high_long, low_long);
   
   while(true);
}

Espero te sea util.

Saludos
Título: Re: Primero read luego write
Publicado por: MGLSOFT en 18 de Septiembre de 2015, 14:06:32
Hola a todos Necesito mandar un INT16 a otro micro madiante protocolo SPI El problema es que nisiquiera logro partirlo en 2 INT8 Las instrucciones en este
o cualquier otro foro parecen simples pero llevo ya 3 dias con lo mismo y nada funciona Esto es lo que e probado entre otras cosas:

//DECLARACIONES
int16 pru1=1320;                   
int8 v8,v16;   
int8 posicion;

//......................................

v8=make8(pru1,0);
v16=make8(pru1,1);

//FRACASO 2.................................

posicion=&pru1
v8=make8(posicion,0);
v16=make8(posicion,1);

//FRACASO 3................................

v8=make8(*(&pru1),0);
v16=make8(*(&pru1),1);

//FRACASO 4................................

v8=pru1>>8;
v16=pru1 & 0xff;

//En todos los casos el RESULTADO ES V8=40  V16=5

Me gustaria saber que es lo que hago mal ¿make8 necesita alguna libreria? E oido ablar de macros en referencia a make16
desde luego el que yo e hecho en make8 no es valido      #define make8(Variable,Bit)  *(&Variable+Bit)
Si fuese por esto cual es el macro adecuado para lo que yo necesito

saludos

Hay un modo e SPI de CCS en que puedes enviar hasta 16 bits e un solo mensaje, buscalo...
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: elgarbe en 18 de Septiembre de 2015, 14:10:47
v8 = (pru1 & 0xFF00) >> 8;
v16= (pru1 & 0x00FF);

en v8 te queda la parte alta y en v16 la parte baja. Eso no funciona?

sds.
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: elgarbe en 18 de Septiembre de 2015, 14:13:19
pero el resultado está bien!!!

1320 = 0x0528
en v8 te queda 0x05 = decimal 5
en v16 te queda 0x28 = decimal 40

saludos!
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: KILLERJC en 18 de Septiembre de 2015, 16:00:25
Si asi es, esta bien. Una ves que lo tenga en el otro integrado lo junta y tiene le mismo numero.

La funcion que dice MGLSOFT creo que es

spi_write_16();

Lo raro que se lo nombra apenas en el manual
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: RALF2 en 18 de Septiembre de 2015, 17:38:59
La funcion que comenta el amigo MGLSOFT es spi_xfer(), para ser mas exacto y por medio de # USE SPI() configuras el modo y el numero de bits a transmitir, entre otros.  :mrgreen:

Saludos
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 18 de Septiembre de 2015, 18:22:42
Si e visto que le pasa la posicion en dos partes desde el principio pero a esto le veo dos pegas

De que me sirve pasarle una posicion de memoria cuando lo que necesito es pasarle un contenido de esta (sus 2 punteros) una vec que llege a la 0x0528 del otro de que me va a servir me veo en las mismas lo que necesito es meterle el dato

y la otra es si pru1=1320 deja de ser puntero y lo que hace es combertirse en una posicion mediante make8 o lo que sea Como se yo que la 0x0528 No esta ocupada por el contenido de otra variable y asi acabar falseando datos O lo que es peor sea una zona reservada al micro. Esta ultima duda se me pasa tambien cuando veo "write_eeprom(posicion,pru1);"

Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 18 de Septiembre de 2015, 18:34:48
Ok spi_xfer(pru1); Me lo a compilado dime que pongo ahora een el slave, damelo todo hecho porfa. Hoy me e pasado desallunando no e dejado los bares asta las 16:00 y estoy algo afectado
Hay algo para int32 La comunicacion siempre es de un bit ¿no? ¿Tendre que poner mas delays()?
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: RALF2 en 18 de Septiembre de 2015, 18:48:32
Berto, en los ejemplos que te hemos pasado trabajamos solo con datos (valores) en ningun caso son posiciones de memoria, tu querias dividir una varible de 16bits en dos de 8 bits y eso es precisamente lo que hacen los ejemplos dados. Tienes una confucion me parece o que es lo que quieres hacer?  :?

Saludos
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: elgarbe en 18 de Septiembre de 2015, 19:25:27
Si e visto que le pasa la posicion en dos partes desde el principio pero a esto le veo dos pegas

De que me sirve pasarle una posicion de memoria cuando lo que necesito es pasarle un contenido de esta (sus 2 punteros) una vec que llege a la 0x0528 del otro de que me va a servir me veo en las mismas lo que necesito es meterle el dato

y la otra es si pru1=1320 deja de ser puntero y lo que hace es combertirse en una posicion mediante make8 o lo que sea Como se yo que la 0x0528 No esta ocupada por el contenido de otra variable y asi acabar falseando datos O lo que es peor sea una zona reservada al micro. Esta ultima duda se me pasa tambien cuando veo "write_eeprom(posicion,pru1);"



nonononoononoo, 0x0528 = 1320, es el hexadecimal de 1320, no la posicion de memoria en que esta el 1320!

si quieres enviar 1320 decimal en 2 byte entonces la conversion es 40 decimal la parte baja y 5 decimal la parte alta. 5 * 256 + 40 =1320!!!

saludos!
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 18 de Septiembre de 2015, 19:32:44
Si la palabra exacta es una confusion monunmental pero yo no recojo contenido Elgarbe tiene razon lo que leo mediante %d es 2 decimales.....
Claro no tiene porque ser una posicion de memoria El problema es que me esta dando el hexadecimal de 1320 (el dato en si) y el metodo
que abeis espusto vosotros 2 desde luego debe ser mas comodo si es mas lento internamente no lo se, pero si que te ahorra trabajo  Lo miro mañana mejor.

Saludos
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 18 de Septiembre de 2015, 19:52:09
 Ok Elgarve    5 * 256 + 40 =1320!!! Gracias

pero en my caso va a ser   v16*256 + v8

v16 = (pru1 & 0xFF00) >> 8;  //v16 lo nombre con intencion de referirme a la parte alta lo que otros definen como Data_H
v8= (pru1 & 0x00FF);             //Data_L

Saludos

Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 19 de Septiembre de 2015, 17:30:28
Hola de nuevo e variado un poco mas para el int32. Me e acomodado a hacer esto
---master
v4=make8(pru1,0);////....4
spi_write(v4);
.........
v8=make8(pru1,1);/////.....8
spi_write(v8);
......///pru1...int16

v4=make8(max1,0);///INT32.....4
spi_write(v4);
...........
v8=make8(max1,1);///.....8
spi_write(v8);
...........
v12=make8(max1,2);////....12
spi_write(v12);
.........
v16=make8(max1,3);////....16
spi_write(v16);
..........////...INT32_max1

----slave--------------
v4=spi_read();///...int16
.......
v8=spi_read();
......
v8=v8*256;+v4;///...int16

v4=spi_read();///....INT32
.......
v8=spi_read();
......
v12=spi_read();
.......
v16=spi_read();
.......
max1=(v16*16777216)+(v12*65536)+(v8*256)+v4;///....INT32

Pero esto no sirve con fload recivo los mismos hexadecimales si float es 62974.75 los datos son 'de vajo a alto 8E-75-FE-C0' son los mismos coinciden
pero no se montarlos dentro de una variable float para que me de 62974.75 Lo que hago solo sirve para enteros Estoy viendo tambien que esto lo deberia hacer
make16 v8=v8*256;+v4;
¿pero porque no me funciona esto?
pru1=make(v8,v4)//si utilizo esto el resultado no es correcto (aunque los pase a decimales)
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: KILLERJC en 19 de Septiembre de 2015, 17:43:31
Yo quisiera saber si se puede hacer algo, Y de paso te olvidas del "tipo" de variable, algo como esto:

Código: C
  1. float   datoFloat
  2. int     dato16int
  3. long int dato32int
  4. short int dato8int
  5.  
  6.  
  7. void main()
  8. {
  9.         //Envio
  10.         EnviarSPI((shor int *)&datoFloat,sizeof(datoFloat));
  11.         EnviarSPI((shor int *)&dato16int,sizeof(dato16int));
  12.         EnviarSPI((shor int *)&dato32int,sizeof(dato32int));
  13.         EnviarSPI((shor int *)&dato8int,sizeof(dato8int));
  14.         //Recepcion
  15.         RecibirSPI((shor int *)&datoFloat,sizeof(datoFloat));
  16.         RecibirSPI((shor int *)&dato16int,sizeof(dato16int));
  17.         RecibirSPI((shor int *)&dato32int,sizeof(dato32int));
  18.         RecibirSPI((shor int *)&dato8int,sizeof(dato8int));
  19. }
  20.  
  21.  
  22.  
  23. void EnviarSPI(short int *ptr,short int largo)
  24. {
  25.         short int i;
  26.         for(i=0;i<largo;i++)
  27.                 spi_write(*ptr++);
  28. }
  29.  
  30. void RecibirSPI(short int *ptr,short int largo)
  31. {
  32.         short int i;
  33.         for(i=0;i<largo;i++)
  34.                 *ptr++ = spi_read();
  35. }

int = int16
short int = int8
long int = int32

Y los sizeof se pueden reemplazar directamente por la cantidad de bytes que posee el dato. Si es uno de 32 bits, entonces iria un 4. Si es de 16, iria un 2

Sino proba hacer esto en el esclavo

Código: C
  1. int8 *ptr;
  2.  
  3. // Cada ves que necesites escribir o leer
  4.  
  5. ///...int16
  6. ptr = (int8 *)&dato16int; //Aca el nombre de tu variable de 16 bits
  7. *ptr++ =spi_read();
  8. *ptr=spi_read();
  9.  
  10. ///....INT32
  11. ptr = (int8 *)&dato32int
  12. *ptr++=spi_read();
  13. *ptr++=spi_read();
  14. *ptr++=spi_read();
  15. *ptr=spi_read();
  16.  
  17. /// Si es float es igual que el de int32 para el caso de CCS.

Y deberia andar, si no estoy tan errado, ademas produciria un codigo mucho mas corto que hacer multiplicaciones y rotaciones. A no ser que se de cuenta el compilador que las rotaciones esas no debe realizarlas.

EDIT:

Usar union

Código: C
  1. union FloatData {
  2.         float data;
  3.         int8 bytes[4];
  4. }
  5.  
  6. void main()
  7. {
  8.         union FloatData datoFloat;
  9.         datoFloat.data = 1.23456;
  10.         int8 i;
  11.         // Envio
  12.         for(i=0;i<4;i++)
  13.                 spi_write(datoFloat.bytes[i]);
  14.  
  15.         //Recepcion
  16.         for(i=0;i<4;i++)
  17.                 datoFloat.bytes[i] = spi_read();
  18.        
  19. }
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: elgarbe en 19 de Septiembre de 2015, 20:12:21
EDIT:

Usar union

Código: C
  1. union FloatData {
  2.         float data;
  3.         int8 bytes[4];
  4. }
  5.  
  6. void main()
  7. {
  8.         union FloatData datoFloat;
  9.         datoFloat.data = 1.23456;
  10.         int8 i;
  11.         // Envio
  12.         for(i=0;i<4;i++)
  13.                 spi_write(datoFloat.bytes[i]);
  14.  
  15.         //Recepcion
  16.         for(i=0;i<4;i++)
  17.                 datoFloat.bytes[i] = spi_read();
  18.        
  19. }

 ((:-)) ((:-))
Esa, creo yo, es la mejor manera, o por lo menos la mas entendible/eficiente!
muy buena!

sds
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 20 de Septiembre de 2015, 05:29:04
Si a por lo ultimo es a por lo que e ido acavo de probarlo pero le falta ago o me falta algo amy Cuando declaro la estructura (eso a mi me parece lo que es) El compilador me da un monton de errores en lineas que no tienen nada que ver con ella Si cambio 'struct' por 'union' pasa lo mismo.
No puedo olvidarme del "tipo" de variable, cuando justo lo que necesito es este "tipo" es imprescindible Aunque ahora me dedique a hacer pruebas a lo bestia pasando datos descomunales a intencion de hacerlo lo mas rapido posible (Esto no es necesario en proyecto original, pero si el float)

Volviendo al principio que es EnviarSPI((shor int *)&datoFloat,sizeof(datoFloat)); ¿fucion,macro,define?  EnviarSPI No esta declarado en ningun sitio
¿que es lo que hace darte el tamaño de float?

Gracias por vuestra atencion
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: KILLERJC en 20 de Septiembre de 2015, 07:59:08
No se si son validas las declaraciones de los tipos, yo normalmente me manejo con uint8_t, uint16_t, uint32_t, float. Pero bueno por eso aclare en el primer post sobre la converson de las unidades, si es que es eso.

Citar
Si a por lo ultimo es a por lo que e ido acavo de probarlo pero le falta ago o me falta algo amy Cuando declaro la estructura (eso a mi me parece lo que es) El compilador me da un monton de errores en lineas que no tienen nada que ver con ella Si cambio 'struct' por 'union' pasa lo mismo.
No puedo olvidarme del "tipo" de variable, cuando justo lo que necesito es este "tipo" es imprescindible Aunque ahora me dedique a hacer pruebas a lo bestia pasando datos descomunales a intencion de hacerlo lo mas rapido posible (Esto no es necesario en proyecto original, pero si el float)

No es una estructura. En una estructura los datos no comparten el mismo espacio de datos, Si fuera una estructura tendrias en memoria algo asi:

Float ( ocupa 4 byte, y supongamos que tiene los valores 0x11223344 ) + el array de 4 que supongo que tiene 0xAA,0xBB,0xCC,0xDD

0x11 22 33 44 AA BB CC DD

Conla union se ocupa el espacio de lo mas grande declarado adentro, PERO comparten la misma memoria Tuvieramos el caso de que el float fuera 0x11 0x22 0x33 0x44

0x11 (igual a bytes[0]) , 0x22 (byets[1]) , 0x33 (bytes[2]) , 0x44(bytes[3])

Por lo demas es igual que una estructura, como definirlo etc. Lo que veo que me falt es un " ; " al final de la declaracion de la union, esta seria la correcta para que compares:

Código: C
  1. union FloatData {
  2.         float data;
  3.         int8 bytes[4];
  4. };

Citar
Volviendo al principio que es EnviarSPI((shor int *)&datoFloat,sizeof(datoFloat)); ¿fucion,macro,define?  EnviarSPI No esta declarado en ningun sitio
¿que es lo que hace darte el tamaño de float?

La funcion Enviar SPI esta escrita justo abajo del main(), incluso agregue la de Enviar y Recibir que son casi lo mismo, lo mas seguro es que le falta el prototipo al comienzo:

void EnviarSPI(short int *ptr,short int largo);

Es lo unico que puede decirte por lo que no esta esta declarado.

Para que se entienda lo que intente hacer con esa funcion. Normalmente un puntero aumenta segun el tipo que sea. Supongamos que tengo un puntero a un int8 y un int16

int8 *ptr8 = &variable8bits;   // Supone que la direccion es de 16 bits, pero puedo acceder a la misma hasta en bytes y esta en 0x11223344
int16 *ptr16 = &variable16bits; // y este en 0x22334455

Entonces le asigno la direccion de cada variable asi con *ptr8 , *ptr16 accedo al contenido de esa variable. Pero que ocurre cuando uno hace un

ptr8++;
ptr16++;

Los valores de las direcciones van a quedar:

ptr8 esto es igual a 0x11223345
ptr16 esto es igual a 0x22334457

ptr8 aumento 1 byte, y ptr16 aumento 2 bytes, si hubiera tenido un puntero a un float o un int 32, aumentarian de a 4 bytes.
Entonces lo que hago es:

EnviarSPI((shor int *)&datoFloat,sizeof(datoFloat));

Pasarle la direccion de inicio pero forzar a que el puntero sea de 1 byte (y no de 4 como es un float), entonces al aumentar lo hago de a 1 solo byte por ves y no 4 como seria un float, Y como ya perdi el "tamaño" es decir no se exactamente de cuantos bytes es lo que meti dentro ( 16,24,32) entonces envio un sizeof() que basicamente me dice la cantidad de bytes que ocupa ese dato. Finalmente:

Código: C
  1. short int i;
  2.         for(i=0;i<largo;i++)
  3.                 spi_write(*ptr++);

Procedo a enviarlo, suponete que el float tiene por bytes 0x11 0x22 0x33 0x44 y en la direccion 0x123456
Entonces el primer *ptr++ es 0x11 ubicado en 0x123456 , por el ++ aumenta a 0x12357
Lo cual el segudo *ptr++ es 0x22 y asi en adelante, hasta que se completen los 4 bytes pasados por el sizeof()


Fue lo que se me ocurrio en el momento, todo lo hice desde el gedit de Ubuntu, por decirlo asi el Bloc de notas de Windows, asi que no habia una correccion de sintaxis, ni pruebas, ni nada por el estilo.
Tambien pense en hacer uno con un void pointer para evitar el cast (short int *) fuera de la funcion de recepcion/envio, pero estaba seguro que iba a ser mas problemas.

PD: Deberias probar la solucion de RALF de hacerlo con spi_xfer() tambien
Título: Re: Obtener el byte alto y byte bajo de un Int16
Publicado por: Berto en 21 de Septiembre de 2015, 16:20:06
Por fin Valido creo que tengo todo.
NOTA Practica 10, Teoria 3 (Lo digo por mi claro).