Calculator example


 Allows enter 2 float numbers from keypad and shows result on LCD
 # - enter
 * - decimal point
 A - add
 B - subtract
 C - mutiply
 D - devide

Toolkit:AVR Development System

Location:/bipom/devtools/WinAVR/minimaxavrc/Examples/calculator

Code Example


int main()
{
	float num1, num2, result;
	char  num1txt[MAX_NUM_LEN];
	char  num2txt[MAX_NUM_LEN];
	int   p = 0;
	char  IsPointAdded = 0;
	
	int State = STATE_IDLE;
	
	// delay 500 milliseconds after power up

	_delay_ms(500);        

	// Initialize the serial port 0 to 19200 baud

	uart1Init(19200);
	uart1Printf( "\rCALCULATOR SAMPLE" );
	
	// Initialize the keypad 

	InitKeypad();
	
	// Initialize the LCD 

	lcdInit();	
	pwmInit();	// Adjust LCD contrast 

	lcdControlCursor(CURSOR_OFF);
	 

	// Write a simple message to the LCD 

	lcdClearDisplay();
	lcdSetTopLine();
	lcdPrintf("CALCULATOR SAMPLE");
	
	_delay_ms(2000);
	
	num1 = num2 = result = 0;
	
	while(1)
	{
		char ch = ScanKeypad();
		if(ch == 0 && State != STATE_IDLE)
			continue;
			
		switch(State)
		{
		default:
		case STATE_IDLE:
			lcdClearDisplay();
			lcdSetTopLine();
			lcdPrintf("ENTER NUM1: ");
			
			memset(num1txt, 0, MAX_NUM_LEN);
			memset(num2txt, 0, MAX_NUM_LEN);
			IsPointAdded = 0;
			p = 0;
			
			State = STATE_ENTER_NUM1;
			break;

		case STATE_ENTER_NUM1:
			if(ch >= '0' && ch <= '9')
			{
				num1txt[p++] = ch;
				lcdWrData(ch);
			}

			if(ch == '*' && !IsPointAdded)
			{
				num1txt[p++] = '.';
				IsPointAdded = 1;
				lcdWrData('.');
			}
			
			if(ch == '#' || p >= (MAX_NUM_LEN-1))
			{
				State = STATE_ENTER_NUM2;
				p = 0;
			}

			if(State == STATE_ENTER_NUM2)			
			{
				lcdSetBottomLine();
				lcdPrintf("ENTER NUM2: ");
			}
			
			break;

		case STATE_ENTER_NUM2:
			if(ch >= '0' && ch <= '9')
			{
				num2txt[p++] = ch;
				lcdWrData(ch);
			}
			
			if(ch == '*' && !IsPointAdded)
			{
				num2txt[p++] = '.';
				IsPointAdded = 1;
				lcdWrData('.');
			}
			
			if(ch == '#' || p >= (MAX_NUM_LEN-1))
				State = STATE_ENTER_OPERATION;

			if(State == STATE_ENTER_OPERATION)			
			{
				lcdClearDisplay();
				lcdSetTopLine();
				lcdPrintf("ENTER OPERATION: ");
			}

			break;

		case STATE_ENTER_OPERATION:
			if(ch == 'A' || ch == 'B' || ch == 'C' || ch == 'D')
			{
				num1 = atof(num1txt);
				num2 = atof(num2txt);

				uart1Printf("\rNUM1: %f", num1);
				uart1Printf("\rNUM2: %f", num2);
				uart1Printf("\rOPERATION: %c", ch);
				
				if(ch == 'A')
				{
					lcdWrData('+');
					result = num1 + num2;
					uart1Printf("\rRESULT (+): %f", result);
				}
				if(ch == 'B')
				{
					lcdWrData('-');
					result = num1 - num2;
					uart1Printf("\rRESULT (-): %f", result);
				}
				if(ch == 'C')
				{
					lcdWrData('*');
					result = num1 * num2;
					uart1Printf("\rRESULT (*): %f", result);
				}
				if(ch == 'D')
				{
					lcdWrData('');
					result = num1  num2;
					uart1Printf("\rRESULT (/): %f", result);
				}
				
				State = STATE_SHOW_RESULT;
			}
			
			if(State == STATE_SHOW_RESULT)			
			{
				lcdSetBottomLine();
				lcdPrintf("RESULT: %f", result);
			}
			
			break;

		case STATE_SHOW_RESULT:
			if(ch == '#')
				State = STATE_IDLE;

			break;
		}
	}
}


// ******************************************************************

void InitKeypad()
{
	// Set lower 4 bits of Port K as output, these are the rows of the keypad

	DDRK |= _BV(PK0);
	DDRK |= _BV(PK1);
	DDRK |= _BV(PK2);
	DDRK |= _BV(PK3);

	// Set upper 4 bits of Port H as input, these are the columns of the keypad

	
	PORTH |= _BV(PH4);     // Enable internal pull-up resistor for PH4 so it will not float

	PORTH |= _BV(PH5);     // Enable internal pull-up resistor for PH5 so it will not float

	PORTH |= _BV(PH6);     // Enable internal pull-up resistor for PH6 so it will not float

	PORTH |= _BV(PH7);     // Enable internal pull-up resistor for PH7 so it will not float

	
	DDRH &= ~_BV(PH4);     // Set PH4 as input

	DDRH &= ~_BV(PH5);     // Set PH5 as input

	DDRH &= ~_BV(PH6);     // Set PH6 as input

	DDRH &= ~_BV(PH7);     // Set PH7 as input

}


// ******************************************************************

char ScanKeypad()
{
	int row;
	int col;

	unsigned char RowTable[] = { 0xFE, 0xFD, 0xFB, 0xF7 };
	
	static char KeyTable[] = { 	'1', '2', '3', 'D',
								'4', '5', '6', 'A',	 
								'7', '8', '9', 'B',
								'*', '0', '#', 'D'
							 };
						 
	col = 0;
	for( row=0; row<MAX_ROWS; row++ )
	{
		PORTK = RowTable[row];
		
		if( !(PINH & 0x80) ) col = 4;
		if( !(PINH & 0x40) ) col = 3;
		if( !(PINH & 0x20) ) col = 2;
		if( !(PINH & 0x10) ) col = 1;
			
		if( col != 0 ) 						
		{
			_delay_ms(500);
			return KeyTable[col-1 + row*MAX_COLS];
		}					
	}
	
	return 0;
}