Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

11/09/2015 #1

Avatar de Gustavo.gmb

Se puede usar dos registros o variables de 8 bit en una variable de 16 bits?
Hola a todos
bueno si leen en el titulo mi duda es la siguiente, ¿se puede guardar dos variables o registros de 8 bits en una variable de 16 bits, uno en el nible bajo y otro en el nible alto?

asi como lo muestro en la imagen:



en este caso queria manipular directamente el registro PORTB y PORTD por medio de una variable de 16 bit, se que con el CCS para manipular directamente un registro por medio de una variable es declarandola como puntero, asi que supongo que seria mas sencillo mediante el PROTON BASIC, sea cual sea de estos dos lenguajes, hay alguna manera de manipular dos variables o registros directamente con una sola de 16 bit?, es decir si en mi variable de 16 bit cargo el siguiente valor:

Variable16bit = 1100110011111111

entonces que el valor de los registros sean los siguientes:

PORTB = 11111111 PORTD = 11001100

espero que alguien me pueda dar una mano
saludos
11/09/2015 #2

Avatar de Nuyel

Solo si las direcciones fuesen conjuntas creo que seria posible asignando la dirección directamente.
11/09/2015 #3

Avatar de cosmefulanito04

Usá desplazamientos, con la variable adecuada.

Ejemplo:

Código PHP:
uint16_t variable;

....
//Código
variable=PORTD;
variable=(variable<<8);
variable|=PORTB;
... 
12/09/2015 #4

Avatar de JoaquinFerrero

La forma más cómoda, en C, es usar uniones, para evitar el trabajo de hacer los desplazamientos:

Código PHP:
union {
    
uint8_t var8[2];
    
uint16_t var16;
variable16;

// ...

variable16.var8[0] = nuevo_valor_PORTD;
variable16.var8[1] = nuevo_valor_PORTD;

*((
uint16_t *)PORTD) = variable16.var16;    // depende del compilador si nos deja cambiar el tipo de PORTD 
Otra forma es la ya comentada, la de hacer desplazamientos.

El problema está en que no puedes asignar a PORTD un valor de 16 bit, porque el compilador espera solo uno de 8 bit. Lo que necesitas es un puntero a la misma dirección donde está apuntando PORTD, definirla como (uint16_t *) y a partir de ese momento ya puedes escribir en 16 bit.

Pero, además...

Los PIC tienen distintos tamaños en el mapa de memoria. Por ejemplo, en el PIC16F877A, la memoria se compone de 8 Kpalabras, cada una de ellas de 14 bit, por lo que no se puede almacenar 16 bit "de forma continua". El compilador manejará tu variable de 16 bit como dos de 8, siempre, por lo que no obtendrás muchos beneficios.
12/09/2015 #5

Avatar de cosmefulanito04

Ojo que la unión no funciona de esa forma, tiene que usar un vector. Ejemplo:

Código PHP:
#include <stdio.h>

union Prueba
{
    
uint8_t vector[2];
    
uint16_t var_16bits;
};

int main()
{
    
union Prueba aux;

    
aux.vector[1]=0xab;
    
aux.vector[0]=0xcd;
    
    
printf("El resultado es: %x",aux.var_16bits);
    return 
0;

Otra más sencilla todavía es usar punteros en la variable de 16 bits, pero no vale la pena marear al compañero, ya tiene dos opciones útiles.

Acá les dejo la otra opción si les interesa:

[Aporte] Tutorial ARM Cortex-M3 - LPC1768
12/09/2015 #6

Avatar de JoaquinFerrero

¡Oops, perdón! Es cierto... me colé.

La unión es justo eso: la unión de varios campos en el mismo espacio de memoria.

¡Editado!
12/09/2015 #7


Si la memoria no me falla lo más simple para realizar eso es lo siguiente:

#include <main.h>

void main()
{
#define _porta 0x006
#define _portb 0x005
int16 _word;
#byte _word_lb = _word
#byte _word_hb = _word + 1

while(TRUE)
{
_word_lb = _porta;
_word_hb = _portb;
}

}

Creo que una variable de 16bit tiene byte alto y byte bajo.
y una variable de 8bit tiene nibble alto y nibble bajo.

En Proton no se, pero en lenguaje Basic PSI es muy fácil porque el compilador puede manejar bit y byte de forma directa, también todos los registros del micro están integrados:

Dim _Word as Word 'Declara variable de 16bit (2Bytes).
_Word.HB = PORTA 'El byte alto de _Word se carga con el valor del puerto A
_Word.LB = PORTB 'El byte bajo de _Word se carga con el valor del puerto B
13/09/2015 #8

Avatar de Hellmut1956

No mas un poco de terminología! Un nibble son 4 bits, un byte son 8, un word son 16 bits. Así en tu pregunta correctamente debes reemplazar la palabra "nibble" contra "byte"!
13/09/2015 #9


En realidad el ejemplo de la unión para este caso quedaría así:

union Prueba
{
int8 vector[1];
int16 var_16bits;
};

void main()
{
while(TRUE){

{
union Prueba aux;

aux.vector[1]=0xab;
aux.vector[0]=0xcd;

printf("El resultado es: %Lx",aux.var_16bits);
putc(lf);
putc(cr);
delay_ms(1000);
}

}
13/09/2015 #10

Avatar de cosmefulanito04

Con el vector estás apuntando a una dirección no definida, es probable que en este caso en particular no tengas problemas porque implícitamente esa área de memoria está definida por la variable de 16 bits debido a la unión. Pero... es mala práctica usar mal los vectores.
14/09/2015 #11

Avatar de Gustavo.gmb

Gracias a todos por la ayuda.
Revisaré detalladamente sus recomendaciones, si hay algún problema se los comentare.

Por cierto, ¿esto funciona también en Basic, ya sea Proton Basic, o PICBasic Pro?

Saludos

EDIT:
Quisiera saber un poco más a profundidad esto de UNION.
¿Dónde puedo encontrar un buen documento que detallara este tema?
15/09/2015 #12

Avatar de cosmefulanito04

Acá tenés algo:

http://www.tutorialspoint.com/cprogramming/c_unions.htm

También ye recomiendo que "consigas" este libro:



Sobre el tema del basic, no creo que se pueda implementar este tipo de estructura de datos con memoria compartida, es algo bien de C.

Este sería el mapa de memoria compartida de este ejemplo, todo el bloque implican 16 bits (2 bytes) compartidos:

Imágenes Adjuntas
Tipo de Archivo: png Mapa de memoria.png (4,9 KB (Kilobytes), 56 visitas)
15/09/2015 #13

Avatar de papirrin

Por cierto, ¿esto funciona también en Basic, ya sea Proton Basic, o PICBasic Pro?
En basic no se puede la unión pero hacer eso no es tan rebuscado como en c.
Digamos en pbp solo se pone donde quieras así
Var=var1.highbyte
Var=var1.lowbyte y listo
En código maquina genera unos cuantos ciclos de instrucción.

eso es lo que no me gusta de C, es cierto que tiene mas funciones pero no significa que en codigo maquina se simplifique, en ocaciones termina generando mucho mas codigo XD.
15/09/2015 #14

Avatar de Scooter

Seguramente ese basic tendrá alguna función. Si no la tiene:

Vector= bajo+alto*256

O al revés:

Alto=int(vector/256)
Bajo=vector-alto*256
15/09/2015 #15

Avatar de papirrin

Seguramente ese basic tendrá alguna función.
Estuve revisando el codigo en esamblador que genera PBP y en realidad es el tipico corrimiento (o desplazamiento) "<<" como menciona cosmefulanito en su mensaje #3, que pienso es lo que menos codigo maquina generaria.

y si es basicamente lo que mencionas.
15/09/2015 #16

Avatar de cosmefulanito04

Sin dudas lo mejor es la union, el uP no tiene que hacer nada, solo apuntar bien en memoria, por lo tanto una union termina siendo una simple asignación.
15/09/2015 #17

Avatar de papirrin

Sin dudas lo mejor es la union, el uP no tiene que hacer nada, solo apuntar bien en memoria, por lo tanto una union termina siendo una simple asignación.
muy cierto

bueno una manera de hacer la "union" en basic (yo estoy hablando de basic porque pregunto, sino ni me meto xD) es leyendo o escribiendo directamente al registro con peek o poke. e igual hay que apuntar y tirar en el momento indicado pero sigue siendo diferente a lo que es la union de C.
15/09/2015 #18

Avatar de TRILO-BYTE

yo no multiplcaria por 255

lo que yo haria para unir todo seria con rotar n bits en este caso 8

asi :

int 16bits;

char byte1;
char byte2;

para unirlos es bien facil

16bits=byte1 | byte2<<8;

como se `puede ver se hace muy poco uso del CPU pues uso 1 instruccion logica OR para sumar
y una <<y un rotado de bits en este caso lo movi 8 veces a la izquierda

no use funciones de suma ni multiplicaciones que en ASM se hace largo el codigo robando vitales ciclos de CPU
16/09/2015 #19

Avatar de Nuyel

Oh, entendí mal la pregunta, creí que quería apuntar directamente la memoria.

En este caso el bitwise de corrimiento de carro y OR es lo ideal, son operaciones que tienen equivalentes en código máquina y es lo más optimo, además, son símbolos básicos que cualquier lenguaje y compilador interpretará adecuadamente.
16/09/2015 #20

Avatar de cosmefulanito04

Nuyel dijo: Ver Mensaje
Oh, entendí mal la pregunta, creí que quería apuntar directamente la memoria.
No está mal lo que planteaste, para mí es una buena solución, pero puede resultar más difícil de verlo en C, en assembler no tanto, ya que se supone que uno está acostumbrado a ese tipo de cosas.

De hecho la unión no es más que eso, pero que te ayuda a evitar el uso de punteros y tener que pensar en direcciones de memoria.
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.