miércoles, 10 de octubre de 2018

Conceptos a tener en cuenta

                                                                 Registro DDRX
Registro que se usa para configurar si un pin o puerto X se configura como salida o como entrada.





En general un registro DDR de cualquier puerto , esta dividido en 8 bits, como se muestra el la figura siguiente:
Muchas veces se va a trabajar con los bits de cada registro para ello hay que tener en cuenta como se trabajan en lenguaje C. Aquí un un tutorial ==>>  Trabajo con Bits

-número binario de 8 bits ---> 0b00000000--->>> 0b bit7..........bit0
Ejemplos:
poner a 1 el Bit 0==>0b00000001=(1<<0)
poner a 1 el Bit 1==>0b00000010=(1<<1)
poner a 1 el Bit 2==>0b00000100=(1<<2)
poner a 1 el Bit 3==>0b00001000=(1<<3)
poner a 1 el Bit 4==>0b00010000=(1<<4)
poner a 1 el Bit 5==>0b00100000=(1<<5)
poner a 1 el Bit 6==>0b01000000=(1<<6)
poner a 1 el Bit 7==>0b10000000=(1<<7)

                                                                     Salidas Digital 
DDRX = DDRX|(1<<7)<==>DDRX = DDRX|(0b01000000)<==>DDRX|=(0b01000000)<==> DDRX|=(DDRX7)

---------------------------------------------------------------------------------------------------------------------
Explicación:
DDRX | (0b10000000) ==> Se realiza la operación OR entre el número binario y el registro DDRX, así se logrará que el Bit7 del resultado  se mantenga en 1 lógico en este caso.
y el resto de los Bits serán igual a los de DDRX, en conlusión:
si es que se quiere guardar en el mismo registro DDRX, entonces la situación final sería de la siguiente manera:
DDRX=DDRX|(0b10000000)
se pondrá a 1 si antes estaba en 0 y si ya estaba a 1 se mantendrá a 1, los otros Bits mantendrán sus valores ya que los otros Bits son 0.
---------------------------------------------------------------------------------------------------------------------

Si se desea que los pines 2,4 y 6 se pongan a 1 se puede hacer uno por uno como en el ejemplo anterior, o los 3 en una sola linea de código, veamos:

DDRX=DDRX|((1<<2)|(1<<4)|(1<<6))<==>DDRX=DDRX|((1<<DDRX2)|(1<<DDR4)|(1<<DDR6));

                                                                   Entrada Digital
Configurar el Bit 5 como salida digital:
DDRX&=~(1<<5)<==>DDRX=DDRX&~(0b00100000);
---------------------------------------------------------------------------------------------------------------------
Explicación:
recordemos que & es un operador AND y ~ es un operador negación.
(1<<5) = 0b00100000
~(1<<5) =0b11011111
DDRX&(0b11011111)==> se realiza la operación AND, el bit5 se mantiene en 0 lógico(entrada digital) y el resto como 1 lógico (salida digital).
guardamos el resultado como el nuevo valor del registro DDRX
DDRX=(0b11011111)==> El registro quedó con el Bit5, como único puerto de entrada digital.
--------------------------------------------------------------------------------------------------------------------- 
Se niega el número binario con lo que el bit0 se pone a 0 y todos sus demás bits se ponen a 1, luego se realiza la operación AND con el registro DDRB, con lo que se logra que el bit0 del registro DDRB mediante la operación AND se ponga a 0.

Si es que se requiere en una sola linea hacer que los Bit 2,4 y 6 del puerto B sean configurados como entradas digitales , se puede hacer de la siguiente manera:
DDRB& = ~((1<<2)|(1<<4)|(1<<6));
También puede ser así:

DDRB &=~((1<<DDB2)|(1<<DDB4)|(1<<DDB6));//se usa los nombres de los bits.

Recordemos que el registro DDRX sirve para configurar el puerto X como entrada o como salida.

                                                           Registro PORTX

Su funcionamiento esta ligado al registro anterior(DDR), Tiene dos modos de funcionamiento, mas adelante se verán mas detalladamente:



En general un registro PORT de cualquier puerto, esta dividido en 8 bits, como se muestra el la figura siguiente:
Tiene dos modos de uso según como esta configurado el Registro DDRX.

PRIMER MODO:

Si DDRX está configurado como salida, entonces PORTX funcionará para escribir un valor en el puerto, dicho de otra manera el registro PORTX servirá para poner en alto(1 lógico) ó en bajo(0 lógico) cada bits de ese puerto X.

Ejemplos:

PORTB = 0b10101010; // valor en decimal es de 170, se escribe el valor de 170 en el Puerto B.

PORTB|=(1<<0);//Solo el bit 0 se pone a 1 lógico.
PORTB|=(1<<4);//Solo el bit 4 se pone a 1 lógico.

En ATMEL STUDIO se puede hacer lo siguiente:

PORTB|=(1<<PB0);
PORTB|=(1<<PB4);
PORTB|=((1<<PB0)|(1<<PB4));Si se quiere poner a 1 lógico el bit 0 y bit 4;

PORTB& = ~(1<<0) ;Si es que se quiere poner a cero lógico el bit 0;
PORTB&=~((1<<0)|(1<<4)); Si se quiere poner a cero lógico el bit 0 y el bit 4;//////

SEGUNDO MODO:

Si DDRX está configurado como entrada digital(Bits en 0 lógico), el registro PORTX servirá para activar(1 lógico) o desactivar(0 lógico) las resistencias PULL UP internas al microcontrolador AVR

Ejemplos:

DDRB= 0x00=0b00000000;
PORTB=0b01010100; Activar las resistencias PULL UP de los bits 2,4,6 del puerto B.
PORTB|=(1<<2); activar la resistencia PULL UP del PORTB(bit2).
PORTB|=(1<<2)|(1<<4); activar las resistencias PULL UP del PORTB(bit2 y bit4).
En ATMEL STUDIO se puede hacer lo siguiente:

PORTB|=(1<<PB0);
PORTB|=(1<<PB2)|(1<<PB4)|(1<<PB6); activar las resistencias PULL UP del PORTB(bit2,4 y 6).

                                                          Registro PINX

Independiente si el puerto esta configurado como salida o entrada. el registro PINX leerá el puerto, es decir, con este registro se puede obtener el estado de los valores de los pines del puerto X que esta siendo leído. Una vez obtenida el estado de los valores de los pines se guarda en una variable "Y".




Procedimiento de programación en  C - ATMEL STUDIO 

1=====>> La primera línea de código es la directiva de preprocesador para incluir el archivo de cabecera general de AVR I / O. Esta es una línea importante sin la cual el código podría no ser generado.
                                                  #include <avr/io.h>

2=====>> Algunas directivas para que puedan ser usadas primero necesitan que se definan ciertos parámetros, como por ejemplo:
                                                  #define F_CPU 8000000UL 
/Se refiere a la frecuencia de reloj, en este caso de 8MHz, UL se refiere a Unsignal Lon

3=====>>La siguiente línea para incluir el archivo de cabecera de E / S específico ATmega8. Esto puede ser opcional en algunos IDE, ya que utilizan las propiedades del proyecto para utilizar el archivo de encabezado de E / S adecuado basado en el microcontrolador seleccionado.
# include <avr/iom8.h> for ATmega8
# include <avr/iom32.h>for ATmega32

4=====>>Opcionalmente podemos tener un archivo de biblioteca externa incluyendo lo siguiente. Por ejemplo, para incluir un archivo de biblioteca llamado servo, como escribimos a continuación
#include <util/delay.h>
# include "servo.h"

5=====>>Escribir una función principal con un bucle infinito para hacer que el esqueleto del código C del microcontrolador sea muy básico.

int main(void)
{
while (1)
       {


       }
}

6=====>>Ahora, como ya hemos comentado en la introducción de AVR siempre hay tres registros asociados.
DDRx: registro de dirección de datos, controla la dirección de los pines PORT individualmente.
PORTx: Registro para escribir datos en los pines PORT. Para la operación de salida, el bit respectivo del registro DDRx debe estar en 1.
PINx: Cuando los datos necesitan ser leídos de un pin del PUERTO, entonces necesitamos tener acceso al bit respectivo del registro del PIN. Para que un Pin se configure como entrada, el bit respectivo de la DDRx debe estar en 0.

int main(void)
{
//declaramos puerto C como salida
DDRC = 0xFF;
//Valor inicial del puerto C
PORTC.0 =0xFF;

while (1)
            {
             PORTC = 0b01010101;
            _delay_ms(10);
             PORTC = 0b10101010;
            _delay_ms(10);// no olvidar que cuando se usa retartos se debe de incluir <util/delay.h> pero                primero se debe definir primero la frecuencia en la directiva
            }
}

Lo anterior en la estructura básica para empezar a programar.

NOTAS:

Existen  maneras de reducir el código o hacerlos mas entendible(humanizarlo) realizando definiciones en cabecera(# define), veremos algunos ejemplos:


  • (1)===>Si es que se quiere evitar hacer (1<<PB0); a cada momento podemos definir en cabecera , por ejemplo :

#define _BV(bit) (1 << (bit))  //Convierte un número de bit en un valor de byte.
ahora escribimos solo así 
PORTB|= _BV(PB0); ///PORTB |= _BV(0);

DDRB |= _BV(PB0) | _BV(PB1);
PORTB |= _BV(PB0); 
PORTB &= ~_BV(PB1);

para que se pueda realizar lo anterior se debe primero incluir las librerias de avr 
-->#include <avr/io.h>


  • (2)===>Si es que se quiere evitar  hacer !(PINB & (1<<PB0)), se debe de hacer lo siguiente:

#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))// Test whether bit bit in IO register sfr is clear. This will return non-zero if the bit is clear, and a 0 if the bit is set.
Comprueba si el bit "bit"(PB0) en el registro PINB está libre. Esto devolverá cero si el bit está limpio, y un 0 si el bit está en establecido.
ahora escribimos solo así
bit_is_clear(PINB,PB0)

  • (3)===>Haremos lo contrario; Si es que se quiere evitar  hacer (PINB & (1<<PB0)), se debe de hacer lo siguiente:

#define bit_is_st(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))// Test whether bit bit in IO register sfr is set. This will return a 0 if the bit is clear, and non-zero if the bit is set.
Comprueba si el bit "bit"(PB0) en el registro PINB está configurado. Esto devolverá 0 si el bit está limpio, y 1 si el bit está en establecido.

  • (4)====>otra forma de humanizar el código :
#define loop_until_bit_is_clear ( sfr, bit ) do { } while (bit_is_set(sfr, bit))// bit= PB1,etc; sfr=PORTB,etc
Espere hasta que el bit "bit" en el registro entrada/salida sfr esté libre.

  • (5)====>otra forma de humanizar el código :
#define loop_until_bit_is_set ( sfr, bit ) do{}While(bit_is_set(sfr,bit))    
Espere hasta que el bit "bit" en el registro entrada/salida sfr esté establecido.
Para mayor información de las NOTAS se puede revisar este Link.

En resumen

según lo antes visto y reducirlos tiempos de programación se puede expresar lo siguiente:

DDRD|= (1<<DDD0); // DDD0=1= salida
DDRD&=~(1<<DDD1); //DDD1= entrada
PORTD|=(1<<PD1);//
          Si DDD1 está como salida(1 lógico) , entonces PD1=será el valor de un bit en alto.
          Si DDD1 está como entrada(0 lógico), entonces se activará PULL UP para PD1
PORTD &=~(1<<PD0);
         Si DDD0(Registro de configuración de salida / entrada) está como salida(1 lógico),entonces                PD0 será el valor de un bit en bajo(0 lógico).
         Si DDD0 esta como entrada(0 lógico), entonces el registro PORT es para activar o desactivar              las resistencias PULL UPP,en este caso  la resistencia PULL UP de PD0 estará desactivada.

PORTD  ^= (1<<PD0); // Se alterna el valor del led
        
Diagrama de Bloques

Simbología

Se recomienda ver el siguiente VIDEO donde explica muy bien y de manera sencilla la simbología.


No hay comentarios:

Publicar un comentario

Uso del firmware original de la grabadora USBasp AVR en MX-USBASP (clon chino)

Te vendieron un USBisp pensado que es un USBasp?? Hace 2 meses compré un "USBasp" fui a probarlo y no funcionó....pensé me estafar...