sábado, 11 de marzo de 2017

WINAVR PUERTOS IO parte 1.


WinAvr nos permite acceder a los puertos de entrada y salida mediante los registros DDRx, PORTx y PINx, donde x corresponde al nombre del puerto a utilizar.

DDRx.


Es el registro que se ocupa de hacer que el puerto sea de entrada o salida según el valor que tenga.

Si los bits de DDRx son 0 entonces será de entrada y si los bits son 1 será de salida.

Ejemplo:

DDRA=0b00001111; //los bits 0 a 3 del puerto A son de salida el resto son de entrada.

PORTx.


Es el registro que escribe o lee el puerto.

Si los bits de PORTx son 0 entonces en el puerto se escribirá un nivel bajo y si los bits son 1 en puerto tendrá nivel alto.

Ejemplo:

PORTA=0b11000000; //los bits 0 a 5 tienen nivel bajo, el resto son de nivel alto (esto si el puerto es configurado como salida mediante el registro DDRA=0b11111111).

PINx.


Este registro se utiliza para efectuar la lectura de un puerto configurado como entrada.

Ejemplo:

var=PINA; //Guarda en la variable var el valor de los niveles que existe en el puerto A (esto si se configura al puerto A como entrada mediante el registro DDRA=0b00000000).

En WinAVR para tener acceso a los puertos de entrada y salida se debe incluir la librería io.h del siguiente modo.

#include <avr/io.h>

Para poder hacer uso de retardos en los programas se tiene la librería delay.h y se la llama del siguiente modo.

#include <util/delay.h>

Ejercicio 1.


Hacer un contador ascendente por el puerto D con un tiempo de retardo de 200m[s].

Solución.

Se debe configurar el puerto como salida (0b11111111=255) y luego hacer que el valor del puerto se incremente en 1.

#include <avr/io.h>     //incluye la librería para el acceso a los puertos

#include <util/delay.h>           //incluye la librería para los retardos

int main(void)                        

{

            PORTD=0;                  //borra el puerto D

            DDRD=255;               //configura todo el puerto D como salida

            while(1)

            {

                        PORTD++;                 //el puerto D se incrementa en 1

                        _delay_ms(200);         //retardo de 200ms

            }

            return 0;

}

Ejercicio 2.


Reflejar por el puerto D los valores lógicos que existen el puerto C.

Solución.

Pare este caso el puerto D debe ser configurado como salida y el puerto C como entrada y para no utilizar resistores externos, en el puerto C activaremos los pull-up internos (estos existen en todos los puertos del ATMEGA 32). Hay que tener cuidado de no manipular bit 2 (PUD) del registro SFIOR.

#include <avr/io.h>

#include <avrlib/avrlibdefs.h>

#include <util/delay.h>

int main(void)

{

            PORTD=0;      //borra el puerto D

            PORTC=255;  //habilita el pull up en el puerto C

            DDRD=255;   //puerto D como salida

            DDRC=0;        //puerto C como entrada

            while(1)

            {

                        PORTD=PINC;           //escribe en el puerto D los valores leídos en el puerto C

                        _delay_ms(10);                       //retardo de 10ms

            }

}

El acceso a los bits individuales de los puertos es algo engorroso teniendo que hacer bastante uso de los enmascaramientos pero podemos lidiar con esos problemas con la ayuda de las librerías proporcionadas por Procyon AVRlib (la manera de obtenerlos y situarlos en el lugar adecuado se mencionan en la anterior entrega titulada WINAVR 0).

La nueva librería a utilizar es avrlibdefs.h y la incluiremos del siguiente modo.

#include <avrlib/avrlibdefs.h>

Las funciones disponibles para la manipulación de bits de los puertos son:

bit_is_set(sfr, bit);       //Retorna verdadero si el bit esta a 1

bit_is_clear(sfr, bit);   //Retorna verdadero si el bit es 0

cbi(reg,bit);                 //Pone a 0 el bit

sbi(reg,bit);                 //Pone a 1 el bit

Ejercicio 3.


Hacer que el bit 1 del puerto D muestre el estado invertido del bit 5 del puerto C.





Solución.

Los puertos después del reset siempre inician como entradas así que solo hacen falta definir los puertos de salida y para no usar resistores externos utilizaremos los pull up internos del puerto C.

#include <avr/io.h>

#include <avrlib/avrlibdefs.h>

#include <util/delay.h>

int main(void)

{

            sbi(PORTC,5); //pull up activado en el bit 5 del puerto C

            sbi(DDRD,1);  //bit 1 del puerto D como salida

            while(1)

            {

                        if(bit_is_set(PINC,5))

                        {

                                   cbi(PORTD,1);

                        }

                        else

                        {

                                   sbi(PORTD,1);

                        }

                        _delay_ms(100);

            }

}

Ejercicio 4.


Efectuar un contador ascendente descendente visualizado en un display conectado al puerto B. Cuando el pin 0 del puerto A esta a nivel bajo el contador es ascendente y de otro modo el contador es descendente.

Solución.
Para generar los dígitos en el display se hará uso de un decodificador implementado en forma de vector.
#include <avr/io.h>
#include <avrlib/avrlibdefs.h>
#include <util/delay.h>
int main(void)
{
            //decodificador para el display
unsigned char tabla[]={63,6,91,79,102,109,125,7,127,103};
            unsigned char contador=0;
            PORTD=0;                  //borra el puerto D
            DDRD=255;                //puerto D como salida
            sbi(PORTA,0);            //pullup en el bit 0 del puerto D
            while(1)
            {
                        PORTD=tabla[contador];
                        _delay_ms(500);
                        if(bit_is_clear(PINA,0))
                        {
                                   if(++contador==10)    //primero incrementa contador y luego compara
                                   {
                                               contador=0;
                                   }
                        }
                        else
                        {
                                   if(--contador==255)    //primero decrementa contador y luego compara
                                   {
                                               contador=9;
                                   }
                        }
            }
            return 0;
}



Hasta la siguiente entrega.