TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: xerex en 23 de Diciembre de 2008, 07:41:15
-
Buenas, despues de tirarme unas cuantas horas depurando el programa que estoy haciendo para meterlo en un 12f683 y modificar los tipos de variable por espacio de memoria de programa, me encuentro en un punto algo singular: la resta de dos numeros int16 la ejecuta mal el PIC.... suena cachondo ¿no?
basicamente tengo la siguiente estructura:
int16 ejex1,ejex2 // ejex1 es siempre mayor a ejex2 por programa
int16 aux;
.....
aux = ejex1 - ejex2;
....
Pues comprobado que el PIC realiza incorrectamente la resta, el segundo octeto lo deja a 00 siempre cuando el resultado es mayor a 0x00ff. Mi pregunta es ¿porque? ¿que se me esta escapando? Los datos los obtengo de la eeprom interna del pic, no lo he simulado, y grabo los 2 bytes correctamente en la eeprom al igual que otros datos para debbug con identica longitud o superior.
He comprobado que el resto de operaciones que se realizan despues con la variabla aux la hacen con el numero que sale de la resta (que no es correcto, como comento), tambien he probado a utilizar aux como int32 con el mismo resultado (esto ya es a la desesperada).
Y solo me queda la resta para terminar el programita.... a no ser que salga alguna otra cosa que se me haya pasado.
¿alguna sugerencia?
Muchas gracias por vuestro tiempo.
Saludos.
-
Creo que por defecto, los int16 son equivalentes a "signed int16" pero podrías forzarlo en la declaración de variables por si acaso fuera esa la causa.
-
He echo operaciones con un 12f683 y en CCS sin problemas, justo AQUI (http://www.todopic.com.ar/foros/index.php?topic=14434.msg146096#msg146096). Espero t sirva de algo.
Suerte.
-
Hola
Hay que tener cuidado al armar un int16 a partir de dos int8. El orden de los 2 bytes de un int16 en la memoria ram es invertido.
Se me ocurre que ése es el problema. Para corregirlo...
int8 byteeeprombajo;
int8 byteeepromalto;
...
ejex1=(int16)(byteeepromalto<<8)|(byteeeprombajo);
Así se armaría el int16 correctamente.
-
Hola!
Bueno pues revisando nuevamente el codigo, teneis razon, la funcion que estaba usando para leer en la eeprom estaba incorrecta. La asignacion la hacia mal....
Esto me ha enseñado una cosa: Si alguna vez me bajo mas codigo de algun sitio, tengo que revisarlo concienzudamente :)
dejo las funciones que he vuelto a picar y que me funcionan para int16:
void escribe_int16_eeprom(Int address, int16 data)
{
int aux;
aux = data;
write_eeprom(address, aux);
aux= data >>8;
write_eeprom(address+1, aux);
}
int16 lee_int16_eeprom(Int address)
{
int data;
data= read_eeprom(address + 1);
data = data <<8;
data= data + read_eeprom(address);
return(data);
}
Muchas gracias a todos, es asi como cuando uno no ve lo obbio, se da cuenta de que debe hacer un alto en el camino y recapacitar, no ocecarse.
Saludos y feliz navidad. :-/
-
Hay una funcion en CCS que ya hace eso, te puede ahorrar codigo y memoria:
MAKE16( )
--------------------------------------------------------------------------------
Syntax:
i16 = MAKE16(varhigh, varlow)
Parameters:
varhigh and varlow are 8 bit integers.
Returns:
A 16 bit integer
Function:
Makes a 16 bit number out of two 8 bit numbers. If either parameter is 16 or 32 bits only the lsb is used. Same as: i16 = (int16)(varhigh&0xff)*0x100+(varlow&0xff) except it is done with two byte moves.
Availability:
All devices
Requires:
Nothing
Examples:
long x;
int hi,lo;
x = make16(hi,lo);