Hades logo    Hades applet banner

TAMS / Java / Hades / applets (print version): contents | previous | next

PIC16F84 calculator

PIC16F84 calculator screenshot

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;

    }
}

Run the applet | Run the editor (via Webstart)


Impressum | 24.11.06
http://tams.informatik.uni-hamburg.de/applets/hades/webdemos/95-dpi/pic16f84-calculator/calculator_print.html