Hades logoHades applet banner
PIC16F84 calculator

applet icon

The image above shows a thumbnail of the interactive Java applet embedded into this page. Unfortunately, your browser is not Java-aware or Java is disabled in the browser preferences. To start the applet, please enable Java and reload this page. (You might have to restart the browser.)

Circuit Description

This applet demonstrates a PIC16-based controller for simple calculator. The circuit consists of the microcontroller, a standard ASCII-mode liquid-crystal display, and a multiplexed keyboard.

Open the PIC user-interface to watch the program execution, setting breakpoints, etc. (I recommend to uncheck the 'update display' checkbox and to click the data and program memories to enforce repainting. This saves a lot of CPU cycles and makes the animation of the calculator go smoothly).

The keyboard is scanned by row and column. Press twice each key to send a number to LC Display. The maximum resolution is 2 digits.

The C source code has been written by Alex, Juliana, and Ricardo Ferreira, during the Computer Organization Undergraduate Course, Universidade Federal de Višosa, Brazil.

This is the current source code in C compiled by using Picclite from Hitech.

// /usr/hitech/bin/picl  -16f84 -C 
//               -Zg henriquecalculator.c lcda0a1b4_7.c delay.c
// /usr/hitech/bin/picl  -16f84 -Ocalculator.hex 
//               henriquecalculator.obj lcda0a1b4_7.obj delay.obj

#include	
#include	"lcd.h"
#include	"delay.h"

#define col0 RB4
#define col1 RB5
#define col2 RB6
#define col3 RB7


#define row0 RB3
#define row1 RB2
#define row2 RB1
#define row3 RB0

#define PRESSED 0

char index = 0, op = 0;
char num = 0, result = 0;
char estado[2];
char limpa;

void SWITCH_LCD_ON()
{
TRISB = 0x00;
}

void SWITCH_LCD_OFF()
{
TRISB = 0xF0;
}


limpaLCD(){
	SWITCH_LCD_ON();
	lcd_clear();
	SWITCH_LCD_OFF();
}

void SendNumbertoLCD(char n)
{
    char c;
    SWITCH_LCD_ON();
    lcd_goto(index);
    c = (char)(n+48);
    lcd_putch(c);
    SWITCH_LCD_OFF();
    ++index;

}

void showResult(){
	num = result;
	limpa = 1;
	
	for (index = 8; index != 0; ){
		SendNumbertoLCD((char)(num%10));
		num = num/10;
		if (num==0) break;
		index-=2;
	}
	index = 0;
}

void resolveOp(){
	switch(op){
	case 5:
		break;
	case 1:
		result = result+num;
		break;
	case 2:
		result = result-num;
		break;
	case 3:
		result = result*num;
		break;
	case 4:
		result = result/num;
		break;
	default:
		result = num;
		break;
	}
}

void verificaEstado(char tecla)
{
	switch(tecla){
	case 1:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x80) )
		{
			SendNumbertoLCD(1);
			num = num*10 + 1;
			estado[0] |= 0x80;
		}
		break;
	case 2:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x40) )
		{
			SendNumbertoLCD(2);
			num = num*10 + 2;
			estado[0] |= 0x40;
		}
		break;
	case 3:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x20) )
		{
			SendNumbertoLCD(3);
			num = num*10 + 3;
			estado[0] |= 0x20;
		}
		break;
	case 4:
		if( ! (estado[0] & 0x10) )
		{
			limpaLCD();
			resolveOp();
			showResult();
			op = 1;
			num = 0;
			estado[0] |= 0x10;
		}
		break;	
	case 5:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x08) )
		{
			SendNumbertoLCD(4);
			num = num*10 + 4;
			estado[0] |= 0x08;
		}
		break;	
	case 6:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x04) )
		{
			SendNumbertoLCD(5);
			num = num*10 + 5;
			estado[0] |= 0x04;
		}
		break;
	case 7:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[0] & 0x02) )
		{
			SendNumbertoLCD(6);
			num = num*10 + 6;
			estado[0] |= 0x02;
		}
		break;	
	case 8:
		if( ! (estado[0] & 0x01) )
		{
			limpaLCD();
			resolveOp();
			showResult();
			op = 2;
			num = 0;
			estado[0] |= 0x01;
		}
		break;	
	case 9:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[1] & 0x80) )
		{
			SendNumbertoLCD(7);
			num = num*10 + 7;
			estado[1] |= 0x80;
		}
		break;	
	case 10:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[1] & 0x40) )
		{
			SendNumbertoLCD(8);
			num = num*10 + 8;
			estado[1] |= 0x40;
		}
		break;	
	case 11:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[1] & 0x20) )
		{
			SendNumbertoLCD(9);
			num = num*10 + 9;
			estado[1] |= 0x20;
		}
		break;	
	case 12:
		if( ! (estado[1] & 0x10) )
		{
			limpaLCD();
			resolveOp();
			showResult();
			op = 3;
			num = 0;
			estado[1] |= 0x10;
		}
		break;	
	case 13:
		if(limpa){ limpaLCD(); limpa = 0;}
		if( ! (estado[1] & 0x08) )
		{
			SendNumbertoLCD(0);
			num = num*10 + 0;
			estado[1] |= 0x08;
		}
		break;	
	case 14:
		if( ! (estado[1] & 0x04) )
		{
			limpaLCD();
			op = 0;
			result = 0;
			num = 0;
			estado[1] |= 0x04;
		}
		break;	
	case 15:
		if( ! (estado[1] & 0x02) )
		{
			limpaLCD();
			resolveOp();
			showResult();
			op = 5;
			num = 0;
			estado[1] |= 0x02;
		}
		break;	
	case 16:
		if( ! (estado[1] & 0x01) )
		{
			limpaLCD();
			resolveOp();
			showResult();
			op = 4;
			num = 0;
			estado[1] |= 0x01;
		}
		break;
	}
	return;
}

main(){

	estado[0] = estado[1] = 0;

  TRISA = 0x00; // Output bits porta, xxxRE
  SWITCH_LCD_ON();
  lcd_init();
  //lcd_puts("Press 4 or 2=");
  SWITCH_LCD_OFF();


  while(1){

	
	//scan row0
	row0 = 0;
	
	if(col3 == PRESSED)
	{
		verificaEstado(4);
	}else estado[0] &= 0xEF;	
	
	if(col0 == PRESSED )
	{
		verificaEstado(1);
	}else estado[0] &= 0x7F;
	
	if(col1 == PRESSED )
	{
		verificaEstado(2);
	}else estado[0] &= 0xBF;
	
	if(col2 == PRESSED )
	{
		verificaEstado(3);
	}else estado[0] &= 0xDF;
	
	row0 = 1;

	//scan row1
	row1 = 0;
	
	if(col3 == PRESSED)
	{
		verificaEstado(8);
	}else estado[0] &= 0xFE;		
	
	if(col0 == PRESSED )
	{
		verificaEstado(5);
	}else estado[0] &= 0xF7;
	
	if(col1 == PRESSED )
	{
		verificaEstado(6);
	}else estado[0] &= 0xFB;	
	
	if(col2 == PRESSED )
	{
		verificaEstado(7);
	}else estado[0] &= 0xFD;
	
	row1 = 1;

	//scan row2
	row2 = 0;
	
	if(col3 == PRESSED)
	{
		verificaEstado(12);
	}else estado[1] &= 0xEF;	
	
	if(col0 == PRESSED )
	{
		verificaEstado(9);
	}else estado[1] &= 0x7F;
	
	if(col1 == PRESSED )
	{
		verificaEstado(10);
	}else estado[1] &= 0xBF;
	
	if(col2 == PRESSED )
	{
		verificaEstado(11);
	}else estado[1] &= 0xDF;	

	row2 = 1;

	//scan row3
	row3 = 0;
	
	if(col3 == PRESSED)
	{
		verificaEstado(16);
	}else estado[1] &= 0xFE;		
	
	if(col0 == PRESSED )
	{
		verificaEstado(13);
	}else estado[1] &= 0xF7;
	
	if(col1 == PRESSED )
	{
		verificaEstado(14);
	}else estado[1] &= 0xFB;	
	
	if(col2 == PRESSED )
	{
		verificaEstado(15);
	}else estado[1] &= 0xFD;	
	
	row3 = 1;

    }
}

Print version | Run this demo in the Hades editor (via Java WebStart)
Usage | FAQ | About | License | Feedback | Tutorial (PDF) | Referenzkarte (PDF, in German)
Impressum http://tams-www.informatik.uni-hamburg.de/applets/hades/webdemos/95-dpi/pic16f84-calculator/calculator.html