Calculadora Juan Manuel Laiseca, María Alejandra Páez, Carol Quiroga, Carlos Romero Facultad de ingeniería biomédica, Universidad Manuela Manuela Beltrán Bogotá, Colombia
[email protected] [email protected] [email protected] [email protected]
this project is based on developing a calculator with basic functions, where a PIC18F4550 microcontroller, an LCD display and a keypad matrix was used. Microcontroller programming programming was done in C language l anguage from program PIC C. Abstract —
I.
OBJETIVOS
Objetivo General
Elaborar una calculadora de operaciones básicas mediante la programación del PIC18F4550.
Objetivos Específicos
Realizar un algoritmo en lenguaje C, donde se puedan utilizar herramientas como teclado matricial, LCD y microcontrolador para observar el funcionamiento de una calculadora Utilizar los programas PIC C y PROTEUS para compilar y realizar la simulación del proyecto. Elaborar el circuito en una protoboard donde sea posible evidenciar las operaciones básicas de la calculadora satisfactoriamente. II.
INTRODUCCIÓN
En esta práctica de laboratorio se desarrolló un proyecto en lenguaje C, el programa se fundamenta en una serie de instrucciones que ocasionan que el microcontrolador realice una terea particular, en este caso se utilizaron los programas PIC C y Proteus para el diseño y construcción del proyecto. El código fuente está compuesto por una sucesión de líneas de texto que se van a encargar de dar la instrucción al microcontrolador, en esta oportunidad se realizó un algoritmo capaz de originar una calculadora que realiza operaciones como suma, resta, multiplicación y división, las herramientas utilizadas para el funcionamiento correcto de la
calculadora fueron un PIC18F4550, un teclado matricial y una pantalla LCD. En la pantalla LCD es posible visualizar las instrucciones para el usuario y el resultado de las operaciones, y por medio del teclado matricial el usuario ingresa los valores que desea operar y la operación que desea realizar. I.
PROCEDIMIENTO
Como ya se ha mencionado el fin de este proyecto es crear una calculadora que realice operaciones básicas que se puedan visualizar en una pantalla LCD y los datos se puedan ingresar por medio de un teclado matricial, el algoritmo empieza cuando el usuario ingresa el primer número, número, luego ingresa la operación que desea realizar y por último puede digitar el segundo número, cada número se visualiza en la LCD después de ser digitado y finalmente se observa la operación con su respectivo resultado. Inicialmente se elaboró el código fuente para poder compilarlo exitosamente en PIC C, posteriormente se realizó la simulación correspondiente en el programa PROTEUS, y después de observar su funcionamiento se procede a quemar el microcontrolador con el archivo .hex generado por PIC C para realizar el montaje adecuado en la protoboard. A. Código
En la figura 1 se puede observar el procedimiento utilizado en el código mediante un diagrama de flujo, principalmente es necesario incluir la librería del PIC18F4550 para contar con todos sus recursos durante la ejecución ejec ución del programa, la inclusión de los fuses se hace para que el watchdog este desactivado y el oscilador este dado por un cristal de cuarzo de 4 MHz, el puerto para usar la lcd será el puerto d y se incluye la librería lcd.c para contar con todos los recursos de la pantalla lcd, se define el puerto b para el uso del teclado matricial y
también es necesario incluir la librería kbd_lib. c, esta es una librería para teclado 4*4. Las variables char se refieren a que estas van a ser de tipo caracter y las tipo float se usan para manejar número enteros, números decimales y variables signed es decir que incluyan el signo del número, entonces k es la variables donde se va a guardar el valor que el usuario ingrese y las variables como num1, cont, cont1, x, y, num2 y res son variables que serán utilizadas como operandos, contadores y el resultado de las operaciones. El código ejecuta primero el void main que es la función principal de programa, en esta función se inicializan el teclado matricial y la lcd, se activan las resistencias de pullups del puerto b, estas resistencias serán resistencias de polarización cuyo fin es proporcionar baja impedancia de salida sin usar un gran consumo de energía, se usan instrucciones como lcd_gotoxy( ) que le indica a la pantalla en que posición tiene que imprimir, se usa
reset_cpu ( ), cuando el código ya sabe que operación realizar el usuario puede ingresar el número 2 que se adquiere de la misma manera que el número 1, al presionar la tecla “=” en la pantalla lcd se podrá
visualizar el resultado de la operación. B. Simulación
La simulación es realizada en el programa Proteus, se utiliza el PIC18F4550, es necesario tener como base el Datasheet del microcontrolador correspondiente para poder identificar las conexiones del PIC, se conecta a Vcc a través de MCLR, la pantalla LCD es conectada al puerto D y el teclado matricial se conecta al puerto B, para observar el funcionamiento se importa desde el PIC del circuito el archivo .hex, este archivo es el que genera PIC C luego de haber compilado el código, finalmente es necesario configurar la frecuencia con la que va a trabajar el cristal de cuarzo, en la figura 2 se observa el resultado de la simulación.
printf( lcd_putc, “ “) para mostrar el pantalla lo que
se desea que el usuario pueda ver y el delay_ms( ) es usado para generar un retardo. Las variables num1 y cont se inicializan en 0, se pide al usuario que ingrese el número 1 y se crea un ciclo do- while, mientras el carácter adquirido sea diferente de cualquier símbolo el código va a guardar en k el digito ingresado por el usuario, se realiza una conversión de la variable k a ASCII restándole 48, esta conversión se guarda en la variable x, luego se genera una instrucción para que num1 sea igual a (num1*cont*10)+x, esta instrucción va a indicar cuales son las centenas, decenas, unidades, etc. del número ingresado por el usuario, cuando se muestra en pantalla num1, el usuario vuelve a ingresar otro número y se realiza el mismo procedimiento hasta que el usuario presione una tecla que contenga algún símbolo, básicamente esto quiere decir que la calculadora puede operar números de más de un digito. Cuando se presiona un caracter diferente a un número, la pantalla le pedirá al usuario que ingrese la operación que desea hacer y en la función void oper se indicará que si el signo es “+” se vaya a void suma, si es “ -“a void resta, si es “X” void multi, si es “/” void divi, se creó una función para que al presionar ON dado por la tecla “*” del teclado el
código vuelva a empezar desde el main, esto se hizo por medio de un ciclo infinito con la instrucción
Fig.2 Simulación del proyecto de Proteus
C. Montaje
Para realizar el montaje se utilizan materiales como un PIC18F4550, un cristal de cuarzo de 4 MHz, un teclado matricial 4*4, una pantalla LCD 16x2, un potenciómetro, resistencia de 1 KΩ y cables. Inicialmente se quema el PIC
mediante el programa MPLAB con ayuda del PICSTART plus, en la configuración de bits se modifica el uso del cristal y se desactiva el watch dog y el LVP luego de se procede a realizar las conexiones del PIC de acuerdo al datasheet. Finalmente en las figuras 3, 4, 5 y 6 se puede observar el correcto funcionamiento del proyecto.
Fig.1 Diagrama de flujo del funcionamiento de la calculadora
Fig.3 Montaje y funcionamiento de la calculadora
II.
CONCLUSIONES
A partir del programa elaborado fue posible visualizar una calculadora de operaciones básicas capaz de reconocer números negativos, generar números decimales y adquirir números de más de un digito, lo más importante fue tener los conceptos muy claros respecto al lenguaje c, las conexiones del teclado matricial y la LCD al microcontrolador, la manipulación de PIC C y el simulador Proteus. Para el código elaborado se utilizaron instrucciones básicas que se encargaban de adquirir y guardar números y caracteres en una variable para posteriormente escoger una operación y adquirir el siguiente número que se desea operar y finalmente observar los resultados de las operaciones en la LCD. Tal vez el mayor inconveniente fue lograr adquirir números de más de un digito y reconocer si el signo del número era positivo o negativo, pero esto se solucionó por medio de un ciclo do-while y un bucle infinito al momento de adquirir el número para reconocer si el número ingresado era positivo o negativo, pero esto genero un código demasiado extenso. Finalmente se obtuvo satisfactoriamente el programa deseado, es decir una calculadora que puede realizar operaciones básicas y cumplir prácticamente todas las funciones de las que se encarga una calculadora normal. REFERENCIAS [1] DataSheet 28/40/44-Pin Enhanced Flash Microcontrollers, (PIC18F4550), Microchip, Disponible en: [http://ww1.microchip.com/downloads/en/devicedoc/39582b.pd f] [2] Teclado matricial, Galia Microcontroladores, Disponible en: [http://galia.fc.uaslp.mx/~cantocar/microcontroladores/SLIDES _8051_PDF/20_MATRI.PDF]
[3] LCD Module, Xiamen Amotec, Disponible en: [https://www.sparkfun.com/datasheets/LCD/ADM1602K NSW-FBS-3.3v.pdf]
while(TRUE)//ciclo infinito
CÓDIGO EN PIC C #include <18f4550.h> //se nombra libreria del pic18f4550 para contar con todos sus recursos #fuses NOWDT,NOPROTECT,XT guardian, no preoteccion,cristal #use delay(clock=4000000)
//no perro //se utiliza un reloj
de 40 mhz #define lcd_data_port getenv("sfr:portd") //se define el puerto d para usar el lcd #include
lcd para contar con todos sus recursos
{num2=0;//vaciar variables cont1=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo { k=kbd_getc(); }while(k==0);
//se nombra libreria del
#include //se nombra libreria del keypad 4x4 para contar con todos sus recursos #use standard_io(b) registro tris en
//se puede modificar el
#use standard_io(d) mediante la directiva "standard"
//cualquier momento
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) { y=k-48;// conversion numerica num2=(num2*cont1*10)+y; lcd_putc("\f"); printf(lcd_putc,"%f",num2);
char k;
//variable k tipo char
float num1,cont,cont1, x,num2,y, sig, res; tipo flotante
//variables
delay_ms(100); k=0; do{ k=kbd_getc(); //Obtener variable y guardar en k
void limpiar ()
//función de reset
{while(true) {
//bucle infinito
k=kbd_getc();
//Obtener variable y guardar
en k num2=k-48; guardar en num2
//conversión ASCII de k y
}while(k==0); cont1=1;} num2=num2*(-1); printf(lcd_putc,"%f",num2); res=num1+(num2);
if(k!=0)
//se presiono una tecla
{ if(k=='*')
//si es igual a k=*
reset_cpu(); memoria del PIC
//instrucción que borra la
delay_ms(100); lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila) printf(lcd_putc, "\f Su resultado es");
} }}
lcd_gotoxy(1,2); printf(lcd_putc,"%f+%f=%f",num1,num2,res);
void suma()
//Operación suma
delay_ms(100);
{lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila) printf(lcd_putc, "\f Ingrese num 2"); usuario que ingrese el segundo número while(TRUE)
//Se pide al
//ciclo infinito
{k=kbd_getc(); //Obtener variable y guardar en k sig=k-48; //se obtiene el dato de la tecla pulsada y se guarda en la varible k } if(k!=0)//se presiono una tecla {if(k=='-')//si k el número ingresado es negativo {
limpiar (); }
} else if(k=='+')//si k el número ingresado es positivo {while(TRUE)//ciclo infinito {num2=0;//vaciar variables cont1=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo
{ k=kbd_getc();//Obtener variable y guardar en k
while(TRUE)//ciclo infinito
}while(k==0);
{num2=0;//vaciar variables cont1=0;//vaciar variables
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) {y=k-48;// conversion numerica
do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo {
num2=(num2*cont1*10)+y; lcd_putc("\f");
k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{ k=kbd_getc();//Obtener variable y guardar en k }while(k==0); cont1=1; res=num1+(num2); delay_ms(100); lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) { y=k-48;// conversion numerica num2=(num2*cont1*10)+y; lcd_putc("\f"); printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{
printf(lcd_putc, "\f Su resultado es");
k=kbd_getc();//Obtener variable y guardar en k
lcd_gotoxy(1,2);
}while(k==0);
printf(lcd_putc,"%f+%f=%f",num1,num2,res);
cont1=1;}
delay_ms(100);
num2=num2*(-1);
limpiar (); }
printf(lcd_putc,"%f",num2); res=num1-(num2);
}
delay_ms(100);
} else printf(lcd_putc,"error");} } }
lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila) printf(lcd_putc, "\f Su resultado es"); lcd_gotoxy(1,2); printf(lcd_putc,"%f-%f=%f",num1,num2,res);
void resta()//Operación resta {lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
delay_ms(100); limpiar (); }
printf(lcd_putc, "\f Ingrese num 2"); while(TRUE)//ciclo infinito
}
{k=kbd_getc();//Obtener variable y guardar en k
else if(k=='+')//si k el número ingresado es positivo
sig=k-48; //se obtiene el dato de la tecla pulsada y se guarda en la varible k } if(k!=0)//se presiono una tecla {if(k=='-')//si k el número ingresado es negativo {
{while(TRUE)//ciclo infinito {num2=0;//vaciar variables cont1=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo
{ k=kbd_getc();//Obtener variable y guardar en k
while(TRUE)//ciclo infinito
}while(k==0);
{num2=0;//vaciar variables cont1=0;//vaciar variables
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) {y=k-48;// conversion numerica
do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo {
num2=(num2*cont1*10)+y; lcd_putc("\f");
k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{ k=kbd_getc();//Obtener variable y guardar en k }while(k==0); cont1=1; res=num1-(num2); delay_ms(100); lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) { y=k-48;// conversion numerica num2=(num2*cont1*10)+y; lcd_putc("\f"); printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{
printf(lcd_putc, "\f Su resultado es");
k=kbd_getc();//Obtener variable y guardar en k
lcd_gotoxy(1,2);
}while(k==0);
printf(lcd_putc,"%f-%f=%f",num1,num2,res);
cont1=1;}
delay_ms(100);
num2=num2*(-1);
limpiar (); }
printf(lcd_putc,"%f",num2); res=num1*(num2);
}
delay_ms(100);
} else printf(lcd_putc,"error");} } }
lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila) printf(lcd_putc, "\f Su resultado es"); lcd_gotoxy(1,2); printf(lcd_putc,"%f*%f=%f",num1,num2,res);
void multi()//Operación multiplicación {lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
delay_ms(100); limpiar (); }
printf(lcd_putc, "\f Ingrese num 2"); while(TRUE)//ciclo infinito
}
{k=kbd_getc();//Obtener variable y guardar en k
else if(k=='+')//si k el número ingresado es positivo
sig=k-48; //se obtiene el dato de la tecla pulsada y se guarda en la varible k } if(k!=0)//se presiono una tecla {if(k=='-')//si k el número ingresado es negativo {
{while(TRUE)//ciclo infinito {num2=0;//vaciar variables cont1=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo
{ k=kbd_getc();//Obtener variable y guardar en k
{num2=0;//vaciar variables
}while(k==0);
cont1=0;//vaciar variables
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+'))
do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo {
{y=k-48;// conversion numerica num2=(num2*cont1*10)+y;
k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
lcd_putc("\f"); printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{ k=kbd_getc();//Obtener variable y guardar en k }while(k==0); cont1=1; res=num1*(num2); delay_ms(100); lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) { y=k-48;// conversion numerica num2=(num2*cont1*10)+y; lcd_putc("\f"); printf(lcd_putc,"%f",num2); delay_ms(100); k=0; do{ k=kbd_getc();//Obtener variable y guardar en k
printf(lcd_putc, "\f Su resultado es");
}while(k==0);
lcd_gotoxy(1,2);
cont1=1;}
printf(lcd_putc,"%f*%f=%f",num1,num2,res);
num2=num2*(-1);
delay_ms(100);
printf(lcd_putc,"%f",num2);
limpiar (); }
res=num1/(num2); delay_ms(100);
}
lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
} else printf(lcd_putc,"error");} } }
printf(lcd_putc, "\f Su resultado es"); lcd_gotoxy(1,2); printf(lcd_putc,"%f/%f=%f",num1,num2,res);
void divi()//Operación división {lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
delay_ms(100); limpiar (); }
printf(lcd_putc, "\f Ingrese num 2"); while(TRUE)//ciclo infinito
}
{k=kbd_getc();//Obtener variable y guardar en k
else if(k=='+')//si k el número ingresado es positivo
sig=k-48; //se obtiene el dato de la tecla pulsada y se guarda en la varible k } if(k!=0)//se presiono una tecla {if(k=='-')//si k el número ingresado es negativo { while(TRUE)//ciclo infinito
{while(TRUE)//ciclo infinito {num2=0;//vaciar variables cont1=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo { k=kbd_getc();//Obtener variable y guardar en k
}while(k==0);
else if(k=='X') {lcd_putc("\f");
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+'))
multi(); }
{y=k-48;// conversion numerica
else if(k=='*')
num2=(num2*cont1*10)+y;
{lcd_putc("\f");
lcd_putc("\f");
limpiar ();}
printf(lcd_putc,"%f",num2);
else
delay_ms(100);
lcd_putc("\f");
k=0;
divi();} } }
do{ k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
void main()
cont1=1;
{ lcd_init(); kbd_init();
res=num1/(num2); delay_ms(100); lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila)
//se inicializa lcd //se inicializa keypad
port_b_pullups (true); //se activan resistencias pullups de puerto b lcd_gotoxy(1,1);
printf(lcd_putc, "\f Su resultado es");
printf(lcd_putc,"calculadora");
lcd_gotoxy(1,2);
delay_ms(500);
printf(lcd_putc,"%f/%f=%f",num1,num2,res);
lcd_gotoxy(1,1);
delay_ms(100);
printf(lcd_putc,"\f Ingrese num 1");
limpiar (); }
while(TRUE)//ciclo infinito {k=kbd_getc();//Obtener variable y guardar en k sig=k-48; //se obtiene el dato de la tecla pulsada y se guarda en la varible k }
} }
if(k!=0)//se presiono una tecla
else
{if(k=='-')//si k el número ingresado es negativo
printf(lcd_putc,"error");} } }
{ while(TRUE)//ciclo infinito
void oper() {lcd_gotoxy(1,1); //Se le indica a la lcd donde se va a comenzar a escribir (columna y fila) printf(lcd_putc, "\fOperacion"); while(true)//ciclo infinito { k=kbd_getc();//Obtener variable y guardar en k if(k!=0)//se presiono una tecla
{num1=0;//vaciar variables cont=0;//vaciar variables do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo { k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
{ if(k=='+') { lcd_putc("\f"); suma(); } else if(k=='-') {lcd_putc("\f"); resta(); }
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+')) { x=k-48;// conversion numerica num1=(num1*cont*10)+x;
lcd_putc("\f"); printf(lcd_putc,"%f",num1);
{ k=kbd_getc();//Obtener variable y guardar en k }while(k==0);
delay_ms(100); k=0;
while((k!='*')&&(k!='X')&&(k!='/')&&(k!='=')&&(k!='')&&(k!='+'))
do{
{x=k-48;// conversion numerica
k=kbd_getc();//Obtener variable y guardar en k
num1=(num1*cont*10)+x;
}while(k==0);
lcd_putc("\f");
cont=1;}
printf(lcd_putc,"%f",num1);
num1=num1*(-1);
delay_ms(100);
printf(lcd_putc,"%f",num1);
k=0;
oper();}
do{
}
k=kbd_getc();//Obtener variable y guardar en k
else if(k=='+')//si k el número ingresado es positivo
}while(k==0);
{while(TRUE)//ciclo infinito
cont=1; }
{num1=0;
oper();} }
cont=0;
else
do//ciclo que adquiere el número ciclicamente siempr y cuando no se presiones ningún símbolo
printf(lcd_putc,"error");} } }