TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: LABmouse en 15 de Octubre de 2007, 16:26:50
-
Hola amigos, una pregunta a ver si hay alguna forma mas corta de realizar este trabajo. Lo que intento hacer es manipular solo el nible mas bajo o mas alto de un INT8 de forma independiente, o manipular el byte mas bajo o mas alto de un INT16 de forma independiente.
Ejemplo:
INT16 VARIABLE1;
INT8 VALOR1;
INT8 VALOR2;
VARIABLE1=0X0000;
VALOR1=0X12;
VALOR2=0X34;
Ahora como le hago para que VARIABLE1 tome los valores 0x1234: es decir el contenido de VALOR1 en el Byte mas alto y el contenido de VALOR2 en el Byte mas bajo.
Bueno encontré esto, aunque es lo contrario que quiero hacer, pero es una LUZ
VALOR1= (VARIABLE1>>4);
De esa forma VALOR1 toma el valor del Byte mas bajo de VARIABLE1. pero yo quiero invertido, de una forma así rápida.
Hasta ahora se me ocurre de esta forma:
VARIABLE1=VALOR2;
VARIABLE1=SWAP(VARIABLE1);
VARIABLE1=VARIABLE1 || VALOR2;
SALUDOS!!
-
VARIABLE1 = make16(VALOR1,VALOR2);
o bien
VARIABLE1 = VALOR1<<8 + VALOR2;
-
Yo soy partidario de las estructuras, aqui tienes un ejemplo de uso:
http://www.todopic.com.ar/foros/index.php?topic=4867.msg36512#msg36512
Un saludo
-
VARIABLE1 = make16(VALOR1,VALOR2);
o bien
VARIABLE1 = VALOR1<<8 + VALOR2;
:shock: :shock: :shock:
Grande amigo!!!!!! Esta sorprendente esa forma... GRACIAS!!! :-/ :-/
Yo soy partidario de las estructuras, aqui tienes un ejemplo de uso:
http://www.todopic.com.ar/foros/index.php?topic=4867.msg36512#msg36512
Un saludo
Pero con una estructura... Como le hago operaciones matemáticas usando el Byte completo??
-
otra pregunta de esas que se podrían denominar trucos de CCS, porque eso de Nocturno me dejo sorprendido.
Tengo esta variable:
char ID_SISTEMA[8];
La quiero imprimir por RS232, y la única opción que conozco es usando un for que recorra todas las 8 posiciones del vecto.
for(i=0;i<8;i++){
printf("%C",ID_SISTEMA[i]);
}
hay algún truco para imprimir si usar FOR??
-
Para manejar los nibles:
struct sNible
{
bit bit0;
bit bit1;
bit bit2;
bit bit3;
}
struct sByte
{
struct sNible usNible1;
struct sNible usNible2;
}
union
{
struct sByte usByte;
int nByte;
} uByte;
Para escribir o leer en uno de los nibles:
uByte.usByte.usNible1 = 5;
printf("Valor: %u", uByte.usByte.usNible2);
Para escribir o leer en el byte:
uByte.nByte = 10;
printf("Valor: %u", uByte.nByte);
Un saludo
-
Yo acostumbro a extraer los dos nibles de un byte sobre variables de 8 bits ...
int8 X, nibleBajo, nibleAlto;
X =0xAB;
nibleBajo = X & 0x0F;
nibleAlto = X >> 4;
Y en otro orden de cosas ...
char ID_SISTEMA[8];
Si el contenido de ID_SISTEMA termina con el valor 0x00, o sea que el último char que contenga sea '\0' entonces puedes enviarlo simplemente como
printf("%s",ID_SISTEMA);
-
Y en otro orden de cosas ...
char ID_SISTEMA[8];
Si el contenido de ID_SISTEMA termina con el valor 0x00, o sea que el último char que contenga sea '\0' entonces puedes enviarlo simplemente como
printf("%s",ID_SISTEMA);
GRANDIOSO!!!!! :-/
-
Efectivamente querido Diego podemos llegar al mismo punto por varios caminos. Ahora bien en efectividad son mucho mejores las estructuras dado que trabajas directamente en memoria y en tu caso implica utilizar registros intermedios (mas intrucciones y mas lento). Por lo demas el resultado es el mismo.
Un saludo.
-
Creo que ambos metodos son validos, las estructuras con seguridad le dan elegancia al programa, mientras el metodo del string esta muy original.
Cada uno podra ser utilizado mejor cuando dispongamos de poca ROM o RAM, aunque con los micros de hoy dia eso creo no es un problema... :mrgreen:
-
Efectivamente querido Diego podemos llegar al mismo punto por varios caminos. Ahora bien en efectividad son mucho mejores las estructuras dado que trabajas directamente en memoria y en tu caso implica utilizar registros intermedios (mas intrucciones y mas lento). Por lo demas el resultado es el mismo.
Un saludo.
¿Has visto cómo se compila esa operación con estructuras?. Muchas veces me he llevado la sorpresa que el compilador al final utiliza las mismas instrucciones de una manera o de otra.
-
Y no solo eso (que compile igual con distinto código) sino que las conclusiones a las que llegues, que tal o cual forma de escribir tu código genera mas o menos código máquina, va a depender muy mucho de la versión del compilador que uses, y quizás lo aprendido para una 4.239 no tiene nada que ver con una 4.240 ya que los amables señores creadores del compilador han cambiado la forma de compilar ésta o aquella instrucción.
-
Y no solo eso (que compile igual con distinto código) sino que las conclusiones a las que llegues, que tal o cual forma de escribir tu código genera mas o menos código máquina, va a depender muy mucho de la versión del compilador que uses, y quizás lo aprendido para una 4.239 no tiene nada que ver con una 4.240 ya que los amables señores creadores del compilador han cambiado la forma de compilar ésta o aquella instrucción.
Heyy Diego!!
Quien tiene esas versiones del software???
Vas mas adelantado que los fabricantes del software!!! :D :D
-
Y no solo eso (que compile igual con distinto código) sino que las conclusiones a las que llegues, que tal o cual forma de escribir tu código genera mas o menos código máquina, va a depender muy mucho de la versión del compilador que uses, y quizás lo aprendido para una 4.239 no tiene nada que ver con una 4.240 ya que los amables señores creadores del compilador han cambiado la forma de compilar ésta o aquella instrucción.
Efectivamente en ciertos compiladores (y no quiero hacer referencia a ninguno, jejejejeje) se puede esperar cuanlquier cosa dado la cantidad de bug's que aparecen en funciones que iban bien y de repente fallan. Pero una de los principios de las estructuras es que estas se crean en memoria y se trabaja directamente sobre ellas, en definitiva no es mas ni menos que poner etiquetas a las posiciones de memoria. Si algún compilador no trabaja así con las estructuras mejor tirarle.
Y como una imagen vale más que mil palabras, aquí va la simulación y los correspondientes asm para ver la diferencia:
#include <16F84A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#use delay(clock=4000000)
#use rs232(baud=9600)
typedef int1 bit;
struct sNible
{
bit bit0;
bit bit1;
bit bit2;
bit bit3;
};
struct sByte
{
struct sNible usNible1;
struct sNible usNible2;
};
union
{
struct sByte usByte;
int nByte;
} uByte;
void main()
{
int numero;
int8 X, nibleBajo, nibleAlto;
uByte.usByte.usNible1 = 5;
numero = uByte.usByte.usNible2;
uByte.nByte = 10;
printf("Valor: %u", uByte.nByte);
X =0xAB;
nibleBajo = X & 0x0F;
nibleAlto = X >> 4;
}
Y el listado en ASM:
.................... void main()
.................... {
*
007E: CLRF 04
007F: BCF 03.7
0080: MOVLW 1F
0081: ANDWF 03,F
0082: BSF 03.5
0083: BCF 05.0
0084: BCF 03.5
0085: BSF 05.0
.................... int numero;
.................... int8 X, nibleBajo, nibleAlto;
....................
.................... uByte.usByte.usNible1 = 5;
0086: MOVLW 05
0087: MOVWF 11
.................... numero = uByte.usByte.usNible2;
0088: MOVF 12,W
0089: MOVWF 13
....................
.................... uByte.nByte = 10;
008A: MOVLW 0A
008B: MOVWF 11
.................... printf("Valor: %u", uByte.nByte);
008C: CLRF 17
008D: MOVF 17,W
008E: CALL 004
008F: INCF 17,F
0090: MOVWF 0C
0091: MOVWF 1A
0092: CALL 012
0093: MOVLW 07
0094: SUBWF 17,W
0095: BTFSS 03.2
0096: GOTO 08D
0097: MOVF 11,W
0098: MOVWF 18
0099: MOVLW 1B
009A: MOVWF 19
009B: GOTO 049
....................
.................... X =0xAB;
009C: MOVLW AB
009D: MOVWF 14
.................... nibleBajo = X & 0x0F;
009E: MOVF 14,W
009F: ANDLW 0F
00A0: MOVWF 15
.................... nibleAlto = X >> 4;
00A1: SWAPF 14,W
00A2: MOVWF 16
00A3: MOVLW 0F
00A4: ANDWF 16,F
.................... }
00A5: SLEEP
Como se puede apreciar cuando trabajamos con estructuras, trabajamos directamente con posiciones de memoria sin utilizar registros intermedios.
Un saludo
-
Jesús, tengo que discrepar.
Las direcciones de memoria apuntan a bytes, no a nibbles. Cualquier cosa que hagas con nibbles requerirá de alguna argucia para diseccionar un byte.
Fíjate cómo compila tu ejemplo esta instrucción:
.................... uByte.usByte.usNible1 = 5;
0086: MOVLW 05
0087: MOVWF 11
El valor que hubiera en el nibble alto de uByte estaría machacado.
-
Heyy Diego!!
Quien tiene esas versiones del software???
Que es un ejmplo, hombreeeeee ja, ja, ja :D :D :D
-
Jesús, tengo que discrepar.
Las direcciones de memoria apuntan a bytes, no a nibbles. Cualquier cosa que hagas con nibbles requerirá de alguna argucia para diseccionar un byte.
Fíjate cómo compila tu ejemplo esta instrucción:
.................... uByte.usByte.usNible1 = 5;
0086: MOVLW 05
0087: MOVWF 11
El valor que hubiera en el nibble alto de uByte estaría machacado.
Pues o el compilador o trata mal las estructuras o no son soportadas para nibbles, ya que los dos nibbles los ha separado como dos bytes. El caso es que no da ningún error ni advierte de nada. Bueno, esto da idea de como funciona CCS.
La prueba definitiva es:
uByte.usByte.usNible1 = A;
uByte.usByte.usNible2 = B;
printf("Valor: %X", uByte.nByte);
Deberia devolver en el LCD: "AB"
Un saludo
-
¿Puedes compilar ese ejemplo y pegar el resultado?, seguramente compilará bien, pero operando con los bytes para separar sus nibbles.
Mi experiencia con CCS es que es bastante "listo". Si antes no ha tenido cuidado de no machacar el byte, será porque ha visto que no había un valor establecido con anterioridad.
-
Compila tambien con las instrucciones puestas al contrario, para ver si trata un solapamiento de medios bytes
uByte.usByte.usNible2 = B;
uByte.usByte.usNible1 = A;
printf("Valor: %X", uByte.nByte);