Está en la página 1de 19

INSTITUTO POLITÉCNICO NACIONAL

UNIDAD INTERDISCIPLINARIA DE INGENIERÍA CAMPUS ZACATECAS

INGENIERÍA MECATRÓNICA

ALUMNOS:
OSCAR ULISES LARA DÍAZ
ERIC RAFAEL DE LA ROSA RAMÍREZ
LUIS ALONSO TREJO LUNA
JESÚS ÁVILA VARELA

FECHA DE ENTREGA:
14/10/2020

MICROCONTROLADORES AVANZADOS

DOCENTE:
ADÁN ORENDAY DELGADO

TAREA 1

PUERTOS DE ENTRADA Y SALIDA DIGITAL


Objetivo
Utilizar los puertos de entrada y salida digitales del microcontrolador ATMega328P
para la implementación de aplicaciones en sistemas embebidos.
Material y Equipo Virtuales Necesarios
● Teclado matricial 4x4.
● Display de 7 segmentos de cátodo común.
● Display 16x2.
● Microcontrolador ATMega328P.

Software
● Entorno de desarrollo CodeVision.
● Proteus.
Desarrollo
La práctica consta básicamente de dos puntos, el primero consiste en asignar los
números del 0 al 15 en hexadecimal a cada una de las teclas del teclado matricial
4x4, y a través de los puertos I/O del microcontrolador determinar qué tecla fue
presionada y mostrar en el display de 7 segmentos el valor que se le asignó a esa
tecla. Lo anterior, con la finalidad de saber si el algoritmo programado para leer el
teclado funciona de la manera deseada.
En el segundo punto, se propone implementar una aplicación que por medio del
teclado 4x4, permita ingresar una contraseña y se muestre en el renglón superior
del display 16x2. Si la contraseña fue aceptada o rechazada, aparecerá
parpadeando un mensaje en el renglón inferior que diga “ES CORRECTO” o
“INCORRECTO”, según sea el caso. Cinco segundos después de que aparezca
este mensaje, la aplicación se ejecutará de nuevo pidiendo contraseña.

Primer punto.
Mediante el asistente de CodeVision, se generó el código de configuración del
microcontrolador. La velocidad de reloj se dejó en 8MHz, ya que es la frecuencia
que tiene el oscilador interno, luego, se configuró el puerto B para las entradas y
salidas del teclado matricial; en este caso, B0, B1, B2 y B3 fungen como entradas
con la configuración PULL-UP activa y B4, B5, B6 y B7 son salidas con un valor
por defecto de 1. Los pines del D0 al D6 se configuraron como salidas, donde se
conectó el display de 7 segmentos.
En la siguiente imagen se muestra la conexión entre los componentes requeridos
para el desarrollo de este primer punto de la práctica.
Una vez que se generó el código de configuración, se escribió una función llamada
“f_controlfilas(fila)” en código C, para pasar un pulso bajo por todas las filas del
teclado, una a la vez. Esta función hace que el puerto B pase continuamente por
los siguientes valores de salida: 0b11100000, 0b11010000, 0b10110000 y
0b01110000. ”f_controlfilas(fila)” tiene como parámetro de entrada un número
entero (número de la fila), el cual, irá aumentando del 0 al 3 en cada iteración del
while loop, esto es así porque el índice de las filas y columnas de la matriz va del 0
al 3, dado que es de dimensión 4x4. La función retorna un dato del tipo unsigned
char, que es el valor que se le asignará al puerto B.
//Dependiendo de la fila que queramos poner en bajo el teclado, una de las salidas del
puerto B se pondrá en bajo
unsigned char f_controlfilas(int fila)
{
switch (fila)
{
case 0: return 0b11100000;
break;
case 1: return 0b11010000;
break;
case 2: return 0b10110000;
break;
case 3: return 0b01110000;
}
}
Ya que se tiene la parte de las filas, falta identificar en qué columna está el botón
que se presionó, para ello se escribió la función “f_columna(puertob)”, esta retorna
un entero, que es el número de la columna y se le pasa como parámetro el valor
de las entradas del puerto B, para ello se hace una operación and entre dicho
puerto y 0x0F, esto es, PINB&0X0F. De acuerdo a la conexión que se mostró
anteriormente, se asignan los distintos valores del puerto B a una columna en
específico, por medio de una estructura del tipo switch case.
//Según el valor de las entradas del puerto B, arroja la columna en la que está el botón
presionado
int f_columna(unsigned char puertob)
{ int columna;
switch(puertob)
{
case 0b00001110: columna=0;
break;
case 0b00001101: columna=1;
break;
case 0b00001011: columna=2;
break;
case 0b00000111: columna=3;
break;
case 0b00001111: columna=4;
break;
}
return columna;
}

A pesar de que los índices de filas y columnas van del 0 al 3, la función


“f_columna(puertob)” tiene un caso donde devuelve un 4, esto no significa que se
presionó una tecla en la columna 4 del teclado, sino que no se presionó alguna,
dado que el valor de las entradas del puerto B es 0x0F.
Con estas dos funciones se definió el programa principal en el while y se
declararon tres variables, una para la fila, otra para la columna y una para el valor
que tiene la tecla presionada.
Al inicio del programa, el valor de fila, de columna y de valor es 0. Una vez que
entra al while, se le asignan a las salidas del puerto B el valor que corresponde a
la fila 0, por medio de la función “f_controlfilas(fila)” para que el teclado ponga en 0
su fila 0. Después, por medio de la función “f_columna(puertob)” se determina si el
botón de alguna columna fue presionado y devuelve el valor de la columna, si es
que se presionó y si no, se devolverá un 4. El condicional del tipo if verifica que el
valor de columna sea diferente de 4, si lo es, quiere decir que se presionó algún
botón y se procede a sacar el valor de la tecla accionada; en cambio, si columna
es igual a 4, quiere decir que no pasó nada y por lo tanto se debe mantener el
valor del botón que se accionó la última vez. Después, por medio de un switch
case, se manda ese valor al display de 7 segmentos para que se pueda visualizar.
Por último, se comprueba que el valor de fila sea diferente de 3, si lo es, dicho
valor se aumente en una unidad, de lo contrario se reinicia a 0.

Segundo Punto.
Usando las mismas configuraciones que en el punto anterior con la diferencia que
en el puerto D se configuro un LCD alfanumérico usando la librería de CodeVision.
Una vez que se generó el código de configuración, se desarrolló un algoritmo más
reducido que el anterior para la detección de teclas, considerando el teclado una
matriz, la cual recorremos por medio de un ciclo for anidado, de forma que
ponemos en cero lógico cada una de las filas mientras que las columnas están
todas en pull-up y al pulsar algún botón según la fila que este activa se identifica la
celda activa al conocer los índices activos.
Una vez que se identifica la posición del botón activo por medio de un switch case
se identifica la tecla según su posición física.
El sistema de login consiste en una simple concatenación y comparación, se
permite ingresar cuatro dígitos, con cada pulsación y usando un algoritmo anti-
rebote se almacena carácter a carácter, cuando el sistema detecta que se
ingresaron los 4 dígitos se realiza la comparación con la contraseña almacenada.
Código de los Programas
Primer Punto.
#include <mega328p.h>

// Prototipo de las funciones hechas


int f_columna(unsigned char puertob);//Dada la fila, nos dice qué columna se encendió
unsigned char f_controlfilas(int fila);//Función que se encarga de cambiar el estado de los
pines de salida para el teclado 4x4
void main(void)
{
// Declare your local variables here
int columna, fila=0;//Variables tipo entero para la fila y la columna
int valor=0;//Guarda el valor de la tecla que se ha presionado

// Crystal Oscillator division factor: 1


#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTB=0xFF;
PORTD=0X00;
DDRB=0xF0;//Pines del puerto B como salida y entrada
DDRD=0x7F;//Pines del puerto D como salida para la display de 7 seg

columna=0;
while (1)
{
PORTB=f_controlfilas(fila);//Asignamos que pin de B7,B6,B5,B4 estrá en bajo
columna=f_columna(PINB&0x0F);//Dependiendo del valor del puerto B, la función
nos arrojará la columna en la que está el botón presionado
if(columna!=4)//Mientras que el pin B sea diferente de 0xF0, es decir, que un botón se
haya presionado
{
valor=(fila*4)+(columna+1);//Se obtiene el valor númerico del botón que se presionó
if(valor==16) valor=0;//Este botón corresponde al cero del teclado
} else valor=valor;//Si sigue sin presionarse un botón, el valor es el mismo

switch(valor)//Estructura Switch para poner el valor del botón que se presionó en el


display
{
case 0: PORTD=0b00111111;
break;
case 1: PORTD=0b00000110;
break;
case 2: PORTD=0b01011011;
break;
case 3: PORTD=0b01001111;
break;
case 4: PORTD=0b01100110;
break;
case 5: PORTD=0b01101101;
break;
case 6: PORTD=0b01111101;
break;
case 7: PORTD=0b00000111;
break;
case 8: PORTD=0b01111111;
break;
case 9: PORTD=0b01101111;
break;
case 10: PORTD=0b01110111;
break;
case 11: PORTD=0b01111100;
break;
case 12: PORTD=0b00111001;
break;
case 13: PORTD=0b01011110;
break;
case 14: PORTD=0b01111001;
break;
default: PORTD=0b01110001;
}

if(fila==3) fila=0;//Esto permite ir switcheando el pin en 0 en las salidas del puerto B


else fila++;
}
}

//Según el valor de las entradas del puerto B, arroja la columna en la que está el botón
presionado
int f_columna(unsigned char puertob)
{ int columna;
switch(puertob)
{
case 0b00001110: columna=0;
break;
case 0b00001101: columna=1;
break;
case 0b00001011: columna=2;
break;
case 0b00000111: columna=3;
break;
case 0b00001111: columna=4;
break;
}
return columna;
}
//Dependiendo de la fila que queramos poner en bajo el teclado, una de las salidas del
puerto B se pondrá en bajo
unsigned char f_controlfilas(int fila)
{
switch (fila)
{
case 0: return 0b11100000;
break;
case 1: return 0b11010000;
break;
case 2: return 0b10110000;
break;
case 3: return 0b01110000;
}
}
Segundo Punto.

#include <mega328p.h>
#include <alcd.h>
#include <delay.h>

void main(void)
{
// Declare your local variables here
char i;
char j;
char valor;
char tecla;
char cnt=0;
char p[4];
char p1[4]={'0','1','1',''};
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTD=0X00;
PORTB=0xF0;
DDRB=0x0F;
PORTD=0x00;
DDRD=0x00;
PORTC=0x00;
DDRC=0x7F;

// Alphanumeric LCD initialization


// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTD Bit 0
// RD - PORTD Bit 1
// EN - PORTD Bit 2
// D4 - PORTD Bit 4
// D5 - PORTD Bit 5
// D6 - PORTD Bit 6
// D7 - PORTD Bit 7
// Characters/line: 8
lcd_init(16);
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts("Ingrese pin");
delay_ms(1000);
lcd_gotoxy(0,1);
while (1)
{
for(i=0;i<4;i++){
PORTB&=~(1<<i);
for(j=4;j<8;j++){
if(!(PINB&(1<<j))){
char fil=i;
char col=j-4;
while(!(PINB&(1<<j)));
valor=(fil*4)+(col+1);//Se obtiene el valor númerico del botón que se presionó
if(valor==16) valor=0;//Este botón corresponde al cero del teclado
else valor=valor;//Si no es el cero, el valor es el mismo

delay_ms(100);
switch(valor){
case 1:
tecla=7;
break;
case 2:
tecla=8;
break;
case 3:
tecla=9;
break;
case 5:
tecla=4;
break;
case 6:
tecla=5;
break;
case 7:
tecla=6;
break;
case 9:
tecla=1;
break;
case 10:
tecla=2;
break;
case 11:
tecla=3;
break;
case 14:
tecla=0;
break;
default:
tecla=tecla;
break;
}
PORTC=tecla;
if(cnt==3){
lcd_gotoxy(0,1);
lcd_puts(p);
delay_ms(200);
if(p1[0]==p[0]){
if(p1[1]==p[1]){
if(p1[2]==p[2]){
lcd_gotoxy(0,1);
lcd_puts("CORRECTO");
delay_ms(1000);
lcd_gotoxy(0,1);
lcd_puts(" ");
}
}
}else{
lcd_gotoxy(0,1);
lcd_puts("INCORRECTO");
delay_ms(1000);
lcd_gotoxy(0,1);
lcd_puts(p);
lcd_puts(" ");
//p={'0','0','0','0'};
}

cnt=0;
}else{
p[cnt]=tecla+48;
lcd_gotoxy(0,1);
lcd_puts(p);
lcd_gotoxy(0,1);
cnt=cnt+1;
}
}
}
PORTB|=(1<<i);
}
}
}
Simulaciones en Proteus.
Primer Punto.
Segundo Punto.
Conclusiones Personales
Oscar Ulises Lara Díaz.
Se desarrolló una aplicación de un sistema embebido, capaz de leer una
contraseña por medio de un teclado matricial 4x4 y mostrar si esta fue o no
aceptada por medio de un display 16x2. Esto se logró mediante el uso de los
puertos de entrada y salida digitales del microcontrolador, conocidos como GPIO
(General Purpose Input/Output). Se programó un algoritmo que reconociera cuál
tecla estaba siendo pulsada, para después conformar una contraseña de cuatro
dígitos, la cual se compara con la contraseña del sistema y en base a ello muestra
el mensaje de correcto o incorrecto, para después de 5 segundos limpiar pantalla
y pedir una nueva contraseña.
Con el funcionamiento que se obtuvo del sistema embebido realizado, se puede
decir que una aplicación útil de ella es hacer interfaces de control para máquinas o
ciertos dispositivos que requieren variar su funcionalidad o los parámetros con los
que trabajan, haciéndolo así, más amistoso para el usuario.

Eric Rafael de la Rosa Ramírez.


Se cumplió el objetivo de la practica ya que se dio una aplicación bastante útil al
GPIO del microcontrolador, durante la realización tuve algunos conflictos sobre
todo con los tipos de variables, ya que estaba acostumbrado a otros entornos de
programación, sin embargo, no representaron mayor conflicto para la realización
del programa.
Jesús Ávila Varela
Se cumplió satisfactoriamente el objetivo ya que reforzamos los conocimientos
sobre GPIO al dar una aplicación que observamos de forma cotidiana en nuestro
entorno, así obtenemos mayores herramientas a la hora de realizar proyectos ya
que este tipo de prácticas simples pueden ayudar al desarrollo de sistemas más
complejos.

También podría gustarte