I am new to C programming. I wrote calculator program to check my ability in c. I am using ADUC831 demo board, 5x5 matrix keypad, 16x2 LCD in 4 bit mode. following is the code listing. program when run, executes printf statement to show "num1" (checked this by inserting delay) but do not executes scanf to receive float number fl1 and proceeds to display "operator>" and receives variable "operator". on further execution it displays num2> on LCD but skips execution of scanf to receive float no fl2 and directly shows result float no fr. Pl. indicate where am I wrong? Is there a better way to scan keyboard then the one I adopted? Thanks
listing getkey.c char _getkey (void) { while (!kbhit); /* wait for a character */ kbhit = 0 ; /* clear receive interrupt bit */ return(scancode) ; } listing putchar.c #include <ADI\ADUC831.h> #include "kbd.h" #include "lcd.h" #define MAX_COL_NUM 0x0f #define MAX_ROW_NUM 0x02 #define CR 0x0d #define LF 0x0a #define FORM_FEED 0x0c #define BACKSPACE 0x08 unsigned char g_byRow = 0 ; unsigned char g_byCol = 0 ; unsigned char putchar (unsigned char c) { if (c == CR) { g_byCol = 0 ; if (g_byRow < MAX_ROW_NUM) g_byRow ++ ; } else if (c == FORM_FEED) { lcd_cmd(0x80) ; for(c = 0 ; c < 16 ; c ++) lcd_dat(' ') ; lcd_cmd(0xc0) ; for(c = 0 ; c < 16 ; c ++) lcd_dat(' ') ; g_byRow = 0 ; g_byCol = 0 ; c = FORM_FEED ; } else if (c == BACKSPACE) { if (g_byCol) { g_byCol -- ; if (g_byRow == 0) lcd_cmd(0x80 + g_byCol) ; else lcd_cmd(0xc0 + g_byCol) ; lcd_dat(' ') ; } } else { if (g_byRow == 0) lcd_cmd(0x80 + g_byCol) ; else lcd_cmd(0xc0 + g_byCol) ; lcd_dat(c) ; g_byCol ++ ; if (g_byCol > MAX_COL_NUM) { g_byCol = 0 ; if (g_byRow < MAX_ROW_NUM) g_byRow ++ ; } } return(c) ; } Listing kbd.h extern bit kbhit ; extern char scancode ; listing lcd.h void lcd_cmd1 (unsigned char cmd) ; void lcd_dat1 (unsigned char dat) ; void lcd_cmd (unsigned char cmd) ; void lcd_dat (unsigned char dat) ; void lcd_init () ; void delay (unsigned int ms) ; Listing kbd 5x5.c #include <ADI\ADUC831.h> #include <stdio.h> unsigned char scancode ; bit kbhit = 0 ; unsigned char g_byScanCount = 0 ; unsigned char g_byTheScanCount ; unsigned char g_byRetCode ; bit g_bKeyIsDown = 0 ; // upper 3 bits of P0 and upper 2 bits of P2 are scan lines sbit SL0 = P0 ^ 5 ; sbit SL1 = P0 ^ 6 ; sbit SL2 = P0 ^ 7 ; sbit SL3 = P2 ^ 7 ; sbit SL4 = P2 ^ 6 ; // lower 5 bits of P0 are return lines const unsigned char KeyCodes[25] = { 0x0d, // CR 'F', 'G', 'H', 8, // backspace 'D', 'E', '-', '*', '/', 'C', '+', '3', '6', '9', 'B', '.', '2', '5', '8', 'A', '0', '1', '4', '7' } ; void timer0 (void) interrupt 1 using 1 { // this interrupt will occur every 10 ms (assuming ADuC831 @ 11.0592 MHz) TH0 = 0xDC ; if (g_byScanCount == 0) SL0 = 0 ; else if (g_byScanCount == 1) SL1 = 0 ; else if (g_byScanCount == 2) SL2 = 0 ; else if (g_byScanCount == 3) SL3 = 0 ; else SL4 = 0 ; #pragma asm nop ; nop ; nop ; #pragma endasm // small delay to allow the scan lines to settle if (g_bKeyIsDown) { if (g_byTheScanCount == g_byScanCount) { if ((P0 & 0x1f) == 0x1f) g_bKeyIsDown = 0 ; } } else { g_byRetCode = P0 & 0x1f ; if (g_byRetCode == 0x1e) g_byRetCode = 0 ; else if (g_byRetCode == 0x1d) g_byRetCode = 1 ; else if (g_byRetCode == 0x1b) g_byRetCode = 2 ; else if (g_byRetCode == 0x17) g_byRetCode = 3 ; else if (g_byRetCode == 0x0f) g_byRetCode = 4 ; else g_byRetCode = 5 ; // illegal return code if (g_byRetCode != 5) { scancode = KeyCodes[(g_byRetCode * 5) + g_byScanCount] ; g_bKeyIsDown = 1 ; g_byTheScanCount = g_byScanCount ; kbhit = 1 ; } } g_byScanCount ++ ; if (g_byScanCount > 4) g_byScanCount = 0 ; SL0 = 1 ; SL1 = 1 ; SL2 = 1 ; SL3 = 1 ; SL4 = 1 ; } Listing 16x2lcd.c #include <ADI\ADUC831.h> #include "lcd.h" #include "kbd.h" unsigned char p2data = 0xff ; void delay (unsigned int ms) { unsigned int i = 0 ; for (i=0; i < ms ; i++) { } } void lcd_cmd1 (unsigned char cmd) { // sends the 4 LSBits of cmd as a (half) command to the LCD p2data = (p2data & 0xc0) | (cmd & 0x0f) ; P2 = p2data ; p2data |= 0x10 ; // EN high P2 = p2data ; p2data &= 0xef ; // EN low P2 = p2data ; } void lcd_dat1 (unsigned char dat) { // sends the 4 LSBits of dat as a (half) data to the LCD p2data = (p2data & 0xc0) | (dat & 0x0f) | 0x20 ; // A0 = high P2 = p2data ; p2data |= 0x10 ; // EN high P2 = p2data ; p2data &= 0xef ; // EN low P2 = p2data ; } void lcd_cmd (unsigned char cmd) { // sends cmd as a command to LCD lcd_cmd1(cmd >> 4) ; lcd_cmd1(cmd & 0x0f) ; delay(125) ; } void lcd_dat (unsigned char dat) { // sends dat as data to LCD lcd_dat1(dat >> 4) ; lcd_dat1(dat & 0x0f) ; delay(125) ; } void lcd_init () { lcd_cmd1(0x03) ; delay(2750) ; lcd_cmd1(0x03) ; delay(125) ; lcd_cmd1(0x03) ; delay(125) ; lcd_cmd1(0x02) ; delay(125) ; lcd_cmd(0x28) ; lcd_cmd(0x08) ; lcd_cmd(0x0c) ; lcd_cmd(0x06) ; } Listing Calci.c #include <ADI\ADUC831.h> #include "kbd.h" #include "lcd.h" #include <stdio.h> /* global variables */ #define CR 0x0d #define LF 0x0a #define FORM_FEED 0x0c #define BACKSPACE 0x08 unsigned char operator ; float fl1, fl2, fr; void main () { TH0 = 0xDC ; // for interrupt every 10 ms (assuming ADuC831 @ 11.0592 MHz) TL0 = 0x00 ; TMOD = 0x21 ; // t0 = 16 bit timer, t1 = 8 bit auto-reload timer TCON = 0x55 ; IE = 0x82 ; // enable timer0 interrupt lcd_init() ; while(1) // infinite loop { putchar(FORM_FEED) ; printf("Num1> "); scanf("%f",&fl1) ; // get the first number from serial port putchar(FORM_FEED) ; printf("Operator> ") ; scanf("%c",&operator); // get the operator from the serial port putchar(FORM_FEED) ; printf("Num2> ") ; scanf("%f",&fl2) ; // get the second number from serial port putchar(FORM_FEED) ; switch(operator) // according to the operator do the calculations { case '+' : fr = fl1 + fl2 ; break ; case '-' : fr = fl1 - fl2 ; break ; case '*' : fr = fl1 * fl2 ; break ; case '/' : fr = fl1 / fl2 ; break ; default : printf("Illegal operator") ; // if none of the above operators are present then the // entered operator is an illegal operator } // end of switch // send the answer to the serial port // show 6 places after decimal point printf("\r= %.6f",fr) ; getchar() ; } // end of while }