2. Arreglos y Punteros

  • Upload
    marc-ll

  • View
    214

  • Download
    0

Embed Size (px)

Citation preview

  • 7/29/2019 2. Arreglos y Punteros

    1/17

    8.7. ARREGLOS Y PUNTEROS

    Los arreglos son uno de los pilares del lenguaje ANSI C ya que permiten la manipulacin de

    mltiples valores numricos asociados a una sola variable denominada vector. Los arreglos y

    punteros hacen uso intensivo de la memoria de datos ya que normalmente se requiere el

    almacenamiento de ms de un valor.

    Es as que los arreglos interactan con el dato y su direccin. El uso de arreglos es vital

    para la implementacin de algoritmos avanzados, tales como los usados en procesamiento de

    seales digitales. Adems que facilita la creacin de mensajes y tablas de datos que pueden ser

    muy fcilmente accedidas en el programa.

    Un arreglo de datos se declara como una variable, indicando entre corchetes ([ ]) la

    cantidad de elementos que la componen. Por ejemplo, para definir un arreglo se pueden utilizar

    los siguientes formatos:

    unsigned char vector[10];

    char mensaje[] = Programando el PIC18F4550;

    unsigned int valores[] = {0x9040,0x1234,0x6798,0x1A2B,0xF761};

    En el primer caso, el arreglo vector se declara de tipo unsignedchar (8 bits sin signo) y de

    un tamao de 10 elementos. Esto implica que el arreglo vector ocupar 10 espacios de memoria

    donde cada espacio es de 1 bytes de capacidad, en total seran 10 bytes de memoria reservados

    para la variable vector. En el segundo caso, el vector mensaje no tiene indicado el nmero de

    elementos. Pero, en su inicializacin se le asigna la cadena de caracteres ASCII Programando el

    PIC18F4550, la cual se encuentra comprendida por 25 bytes, lo cual implica que mensaje es un

    vector de 25 posiciones de memoria. Finalmente, el arreglo valores est compuesto de 5

    elementos donde cada elemento es de 2 bytes y ocupa dos direcciones de memoria. Cuando un

    arreglo se inicializa con valores no ASCII, todos los valores se deben colocar entre llaves yseparados por una coma.

    Los arreglos pueden declararse tanto en la memoria de datos como en la memoria de

    programa. Observe la siguiente declaracin.Aqu se crean dos vectores uno de cinco elementos y 8

    bits por elemento y otro de cuatro elementos y 16 bits por elemento. En la Figura 8.2 se muestran

  • 7/29/2019 2. Arreglos y Punteros

    2/17

    como los datos de inicializacin estaran almacenados en la memoria de datos o SRAM. Obsrvese

    que el formato para los datos de 16 bits es endianness en donde el byte de ms peso ocupa la

    direccin ms alta.

    #pragma idata VECTORES = 0x100

    char mensaje[] = "PIC18";

    int vector[] = {0xA091,0x1234,0xB751,0x45F1};

    #pragma idata

    De la misma manera, si un arreglo se quiere declarar en la memoria de programa (por lo

    cual ninguno de sus elementos podra ser modificado) se puede hacer uso de la siguiente

    declaratoria:

    #pragma rom data TABLA = 0x5000

    const rom char tabla[]= "Hola Mundo";

    #pragma rom data

  • 7/29/2019 2. Arreglos y Punteros

    3/17

    Figura 8.2. Alojamiento de los datos de los arreglos mensaje y vector en la memoria de datos

    En este caso, el arreglo tabla se compone de 10 bytes y estos se encuentran almacenados

    en la memoria de programa entre las direcciones 0x5000 y 0x5009. Cada carcter de tabla puede

    ser accedido en el programa principal, pero, solo para el proceso de lectura ms no escritura. El

    compilador arrojara un error si se tratara de realizar el ltimo caso.

    Otra variante de los arreglos es la declaracin en forma de matrices. Aqu el arreglo

    presenta dos ndices: el nmero de filas y el nmero de columnas. Para declarar un arreglo de

    forma matricial se sigue el siguiente formato:

    unsigned char matriz[3][4];

  • 7/29/2019 2. Arreglos y Punteros

    4/17

    En este ejemplo, la variable matriz presenta tres filas y 4 columnas, donde cada elemento

    de esta matriz es de un byte sin signo. En total este arreglo ocupa 12 bytes de la memoria de

    programa. No es recomendable el uso intensivo de este tipo de arreglo ya que el consumo de

    memoria se multiplicara.

    El acceso a la informacin de los arreglos se realiza mediante su ndice. El ndice

    representa la posicin de cada elemento del arreglo y siempre debe estar representado por una

    cifra entera positiva. El primer valor del ndice es el 0 y el ltimo es el tamao del arreglo menos

    uno. Por ejemplo, en el Programa 8.21 se muestra un ejemplo de acceso a un arreglo declarado en

    la memoria de datos.

    Programa 8.21. Ejemplo de acceso a la informacin contenida en un arreglo de datos

    #pragma idata VECTORES = 0x100

    unsigned char vector[]="Hola Mundo";

    #pragma idata

    unsigned char a,b;

    void main()

    {

    a = vector[0];

    b = 'k';

    vector[5] = b;

    while(1);

    }

    En el ejemplo mostrado, la variable a toma el valor ASCII H que es el primer elemento del

    arreglo vector (ndice = 0). Luego, la variable b toma el valor ASCII k y este valor se asigna al sexto

    elemento del arreglo (ndice = 5), el cual reemplaza el valor M por k.

    Por otro lado, los punteros son ms verstiles que los arreglos ya que permiten reasignar

    las direcciones en las cuales van a almacenar sus datos. La utilidad de los punteros reside en la

    capacidad para apuntar a determinada direccin de memoria y extraer o guardar un dato en dicha

    posicin. Con los punteros se pueden reutilizar las direcciones de memoria que han sido asignadas

    previamente a otras variables.

    La declaracin de un puntero sigue el siguiente formato:

  • 7/29/2019 2. Arreglos y Punteros

    5/17

    Tipo *nombre del puntero;

    El tipo implica el tamao del dato al cual va a apuntar el puntero, por ejemplo, puede

    apuntar a valores de 8 bits o de 16 bits el nombre del puntero debe ir precedido por un *. El

    acceso a un puntero tambin se puede hacer mediante ndices al igual que un arreglo o medianteel acceso al contenido precediendo * a la variable puntero. Por defecto, un puntero apunta a un

    dato de 16 bits.

    Para asignar la direccin a un puntero se debe hacer uso del operador &. Por ejemplo,

    suponga que una variable a es declarada de la siguiente manera:

    unsigned char a=9;

    Entonces, suponga que la variable a ocupa la direccin 0x60 de la memoria SRAM. Dicha

    direccin contiene el valor 9 ya que se est asignando esta cifra a la variable en su declaracin. Si

    posteriormente, se declara un puntero de nombre p de la siguiente manera y se hace la siguiente

    asignacin:

    unsigned char *p;

    void main()

    {

    p = &a;

    *p=10;

    }

    En este ejemplo, p es un puntero que apunta a registros de 8 bits. El puntero tiene

    asignada la direccin de la variable a (p = &a) por lo cual apuntar a la direccin

    0x60.Posteriormente, se carga el valor de 10 al contenido apuntado porp (instruccin *p = 10), el

    cual reemplaza al valor de 9 que tena la variable a. En otras palabras se ha cambiado el contenido

    de la variable a usando el punterop.

    Por ejemplo, en el Programa 8.22 se muestra la declaracin de un puntero y como este

    interacta con el arreglo de nombre vector previamente declarado.

  • 7/29/2019 2. Arreglos y Punteros

    6/17

    Programa 8.22. Ejemplo de manejo de punteros

    #pragma idata VECTORES = 0x100

    unsigned char vector[]="Hola Mundo";

    #pragma idata

    unsigned char *p;

    void main()

    {

    p = &vector[5];

    *p = 'R';

    p++;

    *p = 'e';

    p[2]='g';

    while(1);

    }

    El programa crea el vector de 10 elementos inicializado con el mensaje Hola Mundo a

    partir de la direccin 0x100 de la SRAM. Posteriormente se crea el punterop que apunta a valores

    de 8 bits. Cuando se asigna la direccin del sexto elemento de vector a p, este apunta a la

    direccin 0x105. Inmediatamente, al contenido de esta direccin se le asigna el cdigo ASCII R,

    reemplazando al ASCII M que estaba all. Luego, el puntero se auto incrementa en 1 dgito,

    apuntando a la direccin 0x106. Cuando se asigna el valor ASCII al contenido apuntado en p(instruccin *p = e), este reemplaza al valor ASCII u que se encontraba en esa posicin.

    Finalmente, el tercer elemento de p es asignado con el valor g, lo cual implica que la direccin

    0x106+0x02 = 0x108 toma el valor ASCII j reemplazando al valor ASCII d. De esta manera, el

    mensaje inicial cargado en vector cambia a ser Hola Rengo.

    8.8. ESTRUCTURAS Y UNIONES

    Las estructuras son arreglos de datos que se pueden invocar desde una sola variable al

    igual que los punteros. La diferencia principal con estos ltimos radica en que los tipos de datos

    asociados a la variablepueden ser diferentes. Por ejemplo, suponga que queremos crear una

    variable de nombre Persona, la cual tieneasociados los siguientes datos: edad, peso, talla, DNI,

    nombre. Cada dato de la variable presenta diferentes caractersticas:

    1. La edad de la persona es un valor de 8 bits, ya que puede oscilar entre 0 y 255 aos.

  • 7/29/2019 2. Arreglos y Punteros

    7/17

    2. El peso de la persona tambin es un valor de 8 bits y puede alternar entre 0 y 255 kg.

    3. La talla de la persona tambin es un valor de 8 bits y puede alternar entre 0 y 255 centmetros.

    4. El DNI de la persona es un valor de 32 bits sin signo ya que se consideran 7 cifras numricas.

    5. El nombre de la persona es una cadena de caracteres de N dgitos.

    Queda claro que se tienen tres tipos diferentes de variable. Los tres primeros son del tipo

    unsigned char, el cuarto es unsigned long y el ltimo un puntero a una cadena de caracteres tipo

    char. Cmo crear una variable que englobe estos tres tipos de datos distintos?

    Una estructura es la solucin a este problema. Basta con declararla de la siguiente manera:

    struct{

    unsigned char edad;

    unsigned char peso;

    unsigned char talla;

    unsigned long DNI;

    char *nombre;

    }Persona;

    La variable Persona es una estructura y contiene cinco campos. Los tres primeros ocupan 1

    byte cada uno, mientras que el cuarto ocupa 4 bytes y el ltimo campo, al ser un puntero a 8 bits

    ocupa solo dos bytes. En total, la estructura Persona requiere de 9 bytes de la memoria SRAM.

    Para hacer uso de la variable Persona solo basta declarar la estructura e invocar cada uno

    de sus campos. En una estructura el campo se especifica colocando el nombre de la variable, un

    punto y luego el nombre del campo. Por ejemplo, para actualizar la altura de la variable Persona se

    ejecuta la instruccin: Persona.talla = 170. En el Programa 8.23 se muestra un ejemplo de creacin

    de una estructura y la actualizacin de sus campos.

  • 7/29/2019 2. Arreglos y Punteros

    8/17

    Programa 8.23. Ejemplo de declaracin y actualizacin de datos de una estructura

    struct{

    unsigned char edad;

    unsigned char peso;

    unsigned char talla;

    unsigned long DNI;

    char *nombre;

    }Persona;

    char name[] = "Sergio Salas A.";

    void main()

    {

    Persona.edad= 31;

    Persona.peso= 80;

    Persona.talla= 180;

    Persona.DNI = 40765319;

    Persona.nombre = &name[0];

    while(1);

    }

    Una de las ventajas que ofrece la estructura es la posibilidad de declarar campos de

    longitudes variables. Es decir, se pueden crear campos de un bit, dos bits, tres bits o cualquier

    tamao a definir hasta un mximo de 8 bits. El formato para determinar el tamao del campo es

    colocar el nombre de este seguido de dos puntos ( : ) y el valor en bits. Cabe mencionar que este

    procedimiento solo es vlido en el mbito de una estructura. Por ejemplo, se tiene la siguiente

    declaracin de estructura:

    struct{

    char bit0: 1;

    char bit1: 1;

    char bit2: 1;

    char bit3: 1;

    char bit4: 1;

  • 7/29/2019 2. Arreglos y Punteros

    9/17

    char bit5: 1;

    char bit6: 1;

    char bit7: 1;

    }_bits;

    La variable _bits posee 8 campos internos, cada campo tiene un bit de tamao. Esto es

    interesante ya que la estructura _bits solo ocupa 1 byte y presenta 8 campos: uno para cada bit de

    dicho byte. El bit menos significativo (bit0) se declara primero, mientras que el bit ms significativo

    (bit7) se declara al final. Si esta estructura se introduce en la memoria de datos del PIC18,

    entonces solo ocupara una nica direccin. En el Programa 8.24 se muestra un ejemplo de

    manipulacin de una estructura.

    Programa 8.24. Ejemplo de manejo de estructuras con campos de 1 bit de longitud

    #pragma udata ESTRUCTURA = 0x100

    struct{

    char bit0: 1;

    char bit1: 1;

    char bit2: 1;

    char bit3: 1;

    char bit4: 1;

    char bit5: 1;

    char bit6: 1;

    char bit7: 1;

    }_bits;

    char car;

    #pragma udata

    char *p;

    void main()

    {

    _bits.bit0 = 1;

    _bits.bit1 = 1;

    _bits.bit2 = 0;

    _bits.bit3 = 0;

    _bits.bit4 = 0;

    _bits.bit5 = 0;

  • 7/29/2019 2. Arreglos y Punteros

    10/17

    _bits.bit6 = 0;

    _bits.bit7 = 1;

    p=&car;

    p--;

    car = *p;

    while(1);

    }

    En el Programa 8.24 se muestra una estructura de nombre _bits cuyos 8 campos son de 1

    bit de longitud. Esta estructura se encuentra declarada en la direccin 0x100 de la memoria de

    datos, con lo cual todo la estructura _bits se encuentra alojada en esta direccin. Por tal motivo, la

    siguiente variable declarada: carocupa la direccin siguiente o 0x101. Posteriormente, se culmina

    la directiva #pragma y se declara el puntero *p en la direccin por defecto.

    Cuando el programa inicia, se actualizan los 8 campos binarios de la estructura _bits con

    los siguientes valores 100000112. Esto significa que la direccin 0x100 de la memoria de datos

    automticamente (despus de la actualizacin del campo _bits.bit7) contiene el valor 0x83. Luego,

    el puntero p toma la direccin de la variable car, que es 0x101. Luego, el puntero se auto

    decrementa, apuntando a la direccin 0x100. Finalmente, la variable cartoma el valor apuntado

    por el punterop, lo que implica el contenido de la direccin 0x100 que contiene el valor 0x83.

    Ahora analice el Programa 8.26 que es una copia fiel del Programa 8.25. Se ha incluido un

    pequeo cambio que corresponde a un campo ms a la estructura: bit8y9:2. Qu cambios

    ocurrirn en el programa?

    Programa 8.26. Ejemplo de manejo de estructuras con ms de ocho campos de 1 bit

    #pragma udata ESTRUCTURA = 0x100

    struct{

    char bit0: 1;

    char bit1: 1;

    char bit2: 1;

    char bit3: 1;

    char bit4: 1;

    char bit5: 1;

    char bit6: 1;

    char bit7: 1;

    char bit8y9: 2;

  • 7/29/2019 2. Arreglos y Punteros

    11/17

    }_bits;

    char car;

    #pragma udata

    char *p;

    void main()

    {

    _bits.bit0 = 1;

    _bits.bit1 = 1;

    _bits.bit2 = 0;

    _bits.bit3 = 0;

    _bits.bit4 = 0;

    _bits.bit5 = 0;

    _bits.bit6 = 0;

    _bits.bit7 = 1;

    _bits.bit8y9 = 2;

    p=&car;

    p--;

    car = *p;

    while(1);

    }

    Ahora, los resultados son diferentes. En primer lugar, la estructura _bits posee un campo

    adicional: bit8y9 que es de 2 bits, con lo cual toda la variable ocupa 10 bits de longitud. Debido a

    esto, la estructura deber ocupar dos direcciones de la memoria de datos. Los primeros 8 bits

    menos significativos ocuparn toda la direccin 0x100, mientras que el campo _bits.bit8y9

    ocupar los dos bits menos significativos de la direccin 0x101.

    Qu ocurre con los 6 bits ms significativos de la direccin 0x101? Pues, mediante la

    estructura no es posible acceder a ellos. Tendra que utilizarse un puntero para poder apuntar a

    dicha direccin y modificar el valor de 8 bits de esa posicin.

    En el programa principal se vuelve a cargar la direccin 0x100 con el valor 0x83 y el campo

    _bits.bit8y9 se carga con 2 (102), lo cual modifica el contenido de los dos bits menos significativos

    de la posicin 0x101. Los 6 bits ms significativos de esta direccin permanecen en 0000002, con lo

    cual el valor obtenido es 0x02. Luego, la variable carocupa la direccin 0x102, con lo cual al tomar

  • 7/29/2019 2. Arreglos y Punteros

    12/17

    el puntero p su direccin y ejecutar el auto decremento, se apuntar la direccin 0x101. Cuando

    cartome el valor contenido en esa direccin recibir 0x02 en vez de 0x83.

    Por otro lado, Qu pasara si se quisiera tener acceso a cada bit de un registro y al mismo

    tiempo poder acceder a todo el valor de dicho registro? En los ejemplos mostrados en losProgramas 8.26 y 8.25 se vio que para tal efecto se tena que reasignar la direccin de la

    estructura a un puntero. Pero, esto requiere de carga computacional adicional.

    Las uniones son otro tipo de dato del ANSI C que contribuyen a solucionar el problema

    presentado. Observe el siguiente programa en lenguaje ensamblador:

    movlw 0x88

    movwf LATD

    bsf LATD,0

    Se puede observar de esta rutina en ensamblador que el registro LATD ha sido accedido de

    dos formas diferentes. Primero, se ha cargado el valor 0x88 en todo su registro de 8 bits de

    longitud. Luego, solo se ha afectado el bit LSB, cargndose el nivel 12 y modificando la cifra

    completa del registro de 0x88 a 0x89. Este mismo efecto se puede lograr haciendo uso de una

    unin.

    Las uniones en ANSI C presentan una sintaxis muy parecida a la estructura. Observe la

    siguiente unin:

    #pragma udata ESTRUCTURA = 0x100

    union{

    unsigned char a;

    unsigned char b;

    int dato;

    }campos;

    #pragma udata

  • 7/29/2019 2. Arreglos y Punteros

    13/17

    La variable campos es una unin de tres elementos: uno de 8 bits de nombre a, otro de 8

    bits de nombre b y un campo de 16 bits de nombre dato. En una unin, los campos declarados

    ocupan el mismo espacio en memoria. Es decir, a y b al ser de la misma longitud toman posicin

    de la direccin 0x100 de la memoria de datos. En cambio el campo dato, al ser de 16 bits debe

    ocupar dos direcciones. Su parte baja ocupa la direccin 0x100, mientras que sus 8 bits ms

    significativos ocupan la posicin 0x101, tal como se observa en el esquema de la Figura 8.3.

    De tal manera, acceder a la variable a o b implica reutilizar la misma direccin de memoria.

    De igual forma, la parte baja del campo dato apunta a la misma direccin. Esto ofrece una gran

    ventaja, ya que como se ver ms adelante, se podr programar un cdigo equivalente al visto en

    la rutina de ensamblador de la pgina anterior. Observe el Programa 8.27. En este se crean los tres

    campos: a, b y dato. En la funcin principal main() se asignan tres valores diferentes a cada campo.

    Al final, cada asignacin sobrescribe el valor de la variable anterior. Por ejemplo, la asignacin de

    campos.b reemplaza al valor del campos.a y finalmente, el byte menos significativo de

    campos.dato reemplaza a las dos variables anteriores con el valor 0x34.

    Figura 8.3. Esquema de asignacin de direcciones a los campos de una unin en la memoria de

    datos.

  • 7/29/2019 2. Arreglos y Punteros

    14/17

    Programa 8.27. Ejemplo de manipulacin de campos de una unin

    #pragma udata ESTRUCTURA = 0x100

    union{

    unsigned char a;

    unsigned char b;

    int dato;

    }campos;

    #pragma udata

    unsigned char car;

    void main()

    {

    campos.a = 0x50;

    campos.b = 0x12;

    campos.dato = 0x7434;

    car = campos.a;

    while(1);

    }

    Es as que al finalizar el programa, la variable campos.a = 0x34, campos.b = 0x34,

    campos.dato = 0x7434 y car= 0x34.

    Lo interesante resulta al combinar la estructura y la unin. Regresando al ejemplo en

    lenguaje ensamblador. Suponga que se quiere crear una variable de nombre PUERTOB cuyos

    campos son: _Byte tipo char y RB0, RB1, RB2, RB3, RB4, RB5, RB6 y RB7 cada uno de un 1 bit.

    Cuando uno de los campos de un bit se actualiza, inmediatamente esto se ve reflejado en el

    campo _Byte. Eso es lo mismo que ocurre en el ejemplo mostrado en ensamblador. Observe el

    Programa 8.28 en donde se muestra este ejemplo.

    Programa 8.28. Ejemplo de combinacin de una estructura y una unin

    #pragma udata ESTRUCTURA = 0x100

    union{

    struct{

    char RB0:1;

    char RB1:1;

    char RB2:1;

  • 7/29/2019 2. Arreglos y Punteros

    15/17

    char RB3:1;

    char RB4:1;

    char RB5:1;

    char RB6:1;

    char RB7:1;

    }_bits;

    char _Byte;

    }PUERTOB;

    #pragma udata

    unsigned char car;

    void main()

    {

    PUERTOB._Byte = 0xA5;

    PUERTOB._bits.RB1 = 1;

    PUERTOB._bits.RB7 = 0;

    car = PUERTOB._Byte;

    while(1);

    }

    En el programa se observa que la variable PUERTOB es declarada como una unin. Esta

    presenta dos campos internos: _Byte y la estructura _bits. Al estar ambos campos dentro de la

    unin y al tener la misma dimensin (la estructura presenta 8 campos de 1 bit cada uno, es decir 8

    bits en total) ocupan la misma direccin en la memoria de datos (definida en el valor 0x100).

    En el programa principal, se asigna el valor 0xA5 al campo _Byte de la variable PUERTOB

    con lo cual la direccin 0x100 se carga con este valor. Luego, el campo RB1 de la estructura _bits

    se pone a nivel 12, con lo cual el valor de la direccin 0x100 cambia a 0xA7. Luego, el campo RB7

    de la estructura se pone a 02, quedando como valor final el valor 0x27 el cual se carga en la

    variable car.

    El uso de esta combinacin de estructuras y uniones es muy til para diversas aplicacionesen las cuales se quieren manipular los bits de un registro de modo independiente. Esto es muy til

    para aplicaciones de conversin serial a paralelo, como se ver ms adelante en la aplicacin de

    interfaz con un teclado PS/2 o tambin en el siguiente captulo cuando se vea la deteccin de

    teclas pulsadas de un control remoto infrarrojo para televisin.

  • 7/29/2019 2. Arreglos y Punteros

    16/17

    8.9. TIPOS DE VARIABLES COMPUESTOS

    Para mejorar la legibilidad de un programa muchas veces es necesario aclarar los tipos de

    variable a usar. Por ejemplo, el tipo int se sabe representa una variable de 16 bits. Queda claro

    esto para un programador que hace uso de otro compilador para programar otra marca de

    sistema embebido? La respuesta es no. Lo ms probable es que el programador dude si el tipo int

    representa 8 o 16 bits. Para dejar en claro qu se est declarando se puede hacer uso del operador

    typedef.

    Al redefinir un tipo de variable podemos dejar muy en claro que se quiere representar. Por

    ejemplo, si queremos declara una variable num de tipo inty se quiere dejar muy presente que esta

    variable es de 16 bits con signo se puede hacer lo siguiente:

    typedef int _16bits_con_signo;

    _16bits_con_signo num;

    Entonces, queda claro que la variable num corresponde a un tipo de tamao de 16 bits con

    signo. El programador sabr de acuerdo a su experiencia cual es el tipo de dato que corresponde a

    estas caractersticas y de esta manera tendr una comprensin ms clara del programa.

    De la misma manera, las uniones y estructuras se pueden convertir a nuevos tipos

    compuestos, de tal manera que una estructura muy necesitada se puede definir a travs del

    operador typedefy de esta manera crear nuevas variables.

    Suponga que se tienen conectados a cada uno de los pines RB0, RB1, RB2 y RB3 un sensor

    magntico que opera como alarma de seguridad para cuatro ventanas. Cuando una de las

    ventanas se abre, el sensor enva un nivel 12 al pin respectivo.Dependiendo de la ventana (ventana

    1, 2, 3 o 4) se requiere generar un cdigo de alarma de 4 bits que ser transmitido a un dispositivo

    externo que recibe este valor binario a travs de los pines RB4, RB5, RB6 y RB7 del PIC18F4550. Si

    la alarma es detectada por el pin RB0 el cdigo a enviar es 0x08, si se detecta por RB1 el cdigo

    ser 0x0E, si se detecta en el pin RB2 el cdigo es 0x0A y por el pin RB3 el cdigo ser 0x02. En el

    Programa 8.29 se muestra un ejemplo. Observe que se crea un nuevo tipo de variable compuesto

    por una estructura dentro de una unin. Los campos de la estructura presentan un nombre

    asociado a su funcin, lo cual hace ms entendible el programa.

  • 7/29/2019 2. Arreglos y Punteros

    17/17

    Programa 8.29. Ejemplo de un tipo de dato compuesto para una aplicacin de deteccin de

    alarmas

    typedef union

    {

    struct{

    char alarma1:1;

    char alarma2:1;

    char alarma3:1;

    char alarma4:1;

    char cod_alarma:4;

    }info_alarma;

    char estado;

    }alarmas;

    alarmas puertob;

    void main()

    {

    TRISB = 0x0F;

    while(1)

    {

    puertob.estado = PORTB;

    if(puertob.info_alarma.alarma1 = 1)

    puertob.info_alarma.cod_alarma = 8;

    elseif(puertob.info_alarma.alarma2 = 1)

    puertob.info_alarma.cod_alarma = 14;

    elseif(puertob.info_alarma.alarma3 = 1)

    puertob.info_alarma.cod_alarma = 10;

    elseif(puertob.info_alarma.alarma4 = 1)

    puertob.info_alarma.cod_alarma = 2;

    else

    puertob.info_alarma.cod_alarma = 0;

    LATB = puertob.estado;

    }

    }