Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy odd * even does not return exact value in C?
    primarykey
    data
    text
    <p>After finishing my project (The Calculator using PIC18 with Keypad 4x4, LCD and 4 LEDs), I faced wierd issue in the multiplication operation</p> <p>When multiply odd (> 1) * even (> 0) the result is not exactly correct, for example, 3 * 4 = 11.99999</p> <p>====================</p> <p>Here I would try to descripe the situation:</p> <p>The user press a button of the keypad, then the program takes the char from the keypad and stores it into char[] (A char at a time) so finally we have two char[] Operand[13] and Operand[13]. After Entering Operand1 and Operand2 the program converts it to floating number using atof() function then apply some operation ('+', '-', '*' or '/') and stores the result in int Result. Finally, the program convert this int to char[] using FloatToStr() function and display it on the LCD.</p> <p>=====================</p> <p>Here is my code: (Sorry, it's kinda long but I want you help me solving this issue)</p> <pre><code>unsigned char Key[4][4] = {{'1','2','3','4'}, // Keypad 4x4 Matrix {'5','6','7','8'}, {'9','0','.','E'}, {'+','-','*','/'}}; unsigned char Operand_String[2][13], Operation_String, Result_String[15]; // Where we store the operand, operation &amp; Result as chars unsigned char Row, Column; // Row &amp; Column determine the location of Key in the Keypad matrix that the user pressed unsigned char State; // 1: Operand1 - 2: Operand2 - 3: Operation - 4: Result unsigned int EntryCount; // Counter for counts entries on LCD unsigned int Operand1_length, Operand2_length; // Lengths of Operand1 &amp; Operand2 bit Direction; // 1: right - 0: left bit Operand1_Sign, Operand2_Sign; // 1: negative - 0: positive signed float Operand1, Operand2, Result; // Fields where we store Operand1, Operand2 and Result typedef unsigned int boolean; // ** DEFINING ** #define false 0 // ** BOOLEAN ** #define true (!false) // ** TYPE ** boolean ButtonIsPressed = false; // Flag that indicates whether a button is pressed or no button is pressed boolean FloatingPointIncluded = false; // Flag that indicates if there is a floating point in the LCD or not boolean Operand1_signed = false; // Flag that indicates if Operand1 has a sign or not boolean Operand2_signed = false; // Flag that indicates if Operand2 has a sign or not // ***** Lcd pinout settings ***** sbit LCD_RS at RD4_bit; sbit LCD_EN at RD5_bit; sbit LCD_D7 at RD3_bit; sbit LCD_D6 at RD2_bit; sbit LCD_D5 at RD1_bit; sbit LCD_D4 at RD0_bit; // ***** Pin Direction ***** sbit LCD_RS_Direction at TRISD4_bit; sbit LCD_EN_Direction at TRISD5_bit; sbit LCD_D7_Direction at TRISD3_bit; sbit LCD_D6_Direction at TRISD2_bit; sbit LCD_D5_Direction at TRISD1_bit; sbit LCD_D4_Direction at TRISD0_bit; // ***** End LCD module connections ***** // ***** Method that determines no. of Row and Column of keypad matrix where the user presses the button of that location on the keypad ***** void scan_key() { unsigned char portValue[4][4] = {{0b11101110, 0b11101101, 0b11101011, 0b11100111}, {0b11011110, 0b11011101, 0b11011011, 0b11010111}, {0b10111110, 0b10111101, 0b10111011, 0b10110111}, {0b01111110, 0b01111101, 0b01111011, 0b01110111}}; unsigned char temp[4] = {0B11111110, 0B11111101, 0B11111011, 0B11110111}; unsigned int loop_col = 1; unsigned int loop_row = 1; for (loop_col = 1; loop_col &lt; 5; loop_col++) { PORTB = temp[loop_col - 1]; for (loop_row = 1; loop_row &lt; 5; loop_row++) { if ( PORTB == portValue[loop_row - 1][loop_col - 1]) { Row = loop_row; Column = loop_col; return; } } PORTB = 0B11110000; } } // ***** Interrupt Service Routine (ISR) ***** void interrupt() org 0x08 { if (INTCON.TMR0IF) // Timer0 Interrupt { scan_key(); //Delay_ms(40); INTCON.RBIE = 1; INTCON.TMR0IF = 0; } else if (INTCON.RBIF) // PORTB Interrupt { INTCON.TMR0IF = 1; INTCON.TMR0IE = 1; INTCON.RBIE = 0; INTCON.RBIF = 0; ButtonIsPressed = true; } } // ***** Method that calculates the result of the arithmatic Operation ***** float CalculateResult() { Operand1 = atof(Operand_String[0]); Operand2 = atof(Operand_String[1]); if(Operand1_sign == 1) Operand1 = - Operand1; if(Operand2_sign == 1) Operand2 = - Operand2; switch(Operation_String) { case '+': Result = Operand1 + Operand2; break; case '-': Result = Operand1 - Operand2; break; case '*': Result = Operand1 * Operand2; break; case '/': Result = Operand1 / Operand2; break; } return Result; } // ***** Method that makes LEDs blink ***** void LEDsBlink(int iteration) { char PORTA_Temp; int i; PORTA_Temp = PORTA; if(iteration &lt; 0) { PORTA = ~PORTA; Delay_ms(200); } else { for(i = 0; i &lt; iteration; i++) { PORTA = 0x0F; Delay_ms(50); PORTA = 0x00; Delay_ms(50); } PORTA = PORTA_Temp; } } // ***** Method that resets the variables ***** void Reset_Values() { EntryCount = 0; State = 1; Row = 0; Column = 0; Direction = 0; Operand1_Sign = 0; Operand2_Sign = 0; Operand1 = 0; Operand2 = 0; Result = 0; memset(Operand_String, 0, 2 * 13); memset(Result_String, 0, 15); ButtonIsPressed = false; Operand1_signed = false; Operand2_signed = false; PORTA = 0x0F; // Turn on the 4 LEDs } void main() { // ***** Initializations of PIC18F4550 ***** TRISA = 0; // Configure the 4 LEDs as output PORTA = 0x0F; // Turn on the 4 LEDs TRISB = 0xF0; // Configure RB0 ~ RB3 as outputs &amp; RB4 ~ RB7 as inputs PORTB = 0xF0; // Assign 0xF0 OSCCON = 0x63; // 4 MHz - Internal oscillator INTCON2.B7 = 0; // PORTB pull-ups are enabled by individual port latch values INTCON.RBIF = 0; // Reset the interrupt flag INTCON.RBIE = 1; // RB Change interrupt ON INTCON.GIE = 1; // Global interrupts ON ADCON1 = 0b00001111; // Digital inputs // ***** Initializations of LCD ***** Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off Lcd_Out(1, 2, "Fouad Al-Malki"); // ** WELCOME ** Lcd_Out(2, 4, "CALCULATOR"); // ** MESSAGE ** Delay_ms(2000); // delay for 2 seconds Lcd_Cmd(_LCD_CLEAR); // Clear DCD Lcd_Out(1, 4, "Operand1: "); // Write "Operand1: " at first row Lcd_Cmd(_LCD_SECOND_ROW); // Make current position at second row Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on // ***** Reset all values ***** Reset_Values(); while(1) { // ***** Control of LCD ***** if(ButtonIsPressed) { if(State == 1) { if(Key[row-1][column-1] != 'E') { if((EntryCount &lt;= 13 &amp;&amp; Key[row-1][column-1] != '+' &amp;&amp; Key[row-1][column-1] != '-' &amp;&amp; Key[row-1][column-1] != '/' &amp;&amp; Key[row-1][column-1] != '*')) { if((Key[row-1][column-1] == '.' &amp;&amp; !FloatingPointIncluded &amp;&amp; EntryCount &gt; 0) || Key[row-1][column-1] != '.') { Lcd_Chr_Cp(Key[row-1][column-1]); Operand_String[0][EntryCount] = Key[row-1][column-1]; EntryCount++; if(Key[row-1][column-1] == '.') FloatingPointIncluded = true; } else LEDsBlink(3); } else if(!Operand1_signed &amp;&amp; EntryCount == 0 &amp;&amp; (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-')) { if(Key[row-1][column-1] == '+') Operand1_Sign = 0; else if(Key[row-1][column-1] == '-') Operand1_Sign = 1; Lcd_Chr_Cp(Key[row-1][column-1]); Operand1_signed = true; } else LEDsBlink(3); } else if(Key[row-1][column-1] == 'E' &amp;&amp; EntryCount != 0) { State = 2; FloatingPointIncluded = false; Operand1_length = EntryCount; EntryCount = 0; Row = 0; Column = 0; Lcd_Cmd(_LCD_CLEAR); // Clear display Lcd_Out(1, 4, "Operand2: "); Lcd_Cmd(_LCD_SECOND_ROW); Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on if(PORTA.B0 == 1) { PORTA = 0x08; } } else LEDsBlink(3); } else if(State == 2) { if(Key[row-1][column-1] != 'E') { if((EntryCount &lt;= 13 &amp;&amp; Key[row-1][column-1] != '+' &amp;&amp; Key[row-1][column-1] != '-' &amp;&amp; Key[row-1][column-1] != '/' &amp;&amp; Key[row-1][column-1] != '*')) { if((Key[row-1][column-1] == '.' &amp;&amp; !FloatingPointIncluded &amp;&amp; EntryCount &gt; 0) || Key[row-1][column-1] != '.') { Lcd_Chr_Cp(Key[row-1][column-1]); Operand_String[1][EntryCount] = Key[row-1][column-1]; EntryCount++; if(Key[row-1][column-1] == '.') FloatingPointIncluded = true; } else LEDsBlink(3); } else if(!Operand2_signed &amp;&amp; EntryCount == 0 &amp;&amp; (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-')) { if(Key[row-1][column-1] == '+') Operand2_Sign = 0; else if(Key[row-1][column-1] == '-') Operand2_Sign = 1; Lcd_Chr_Cp(Key[row-1][column-1]); Operand2_signed = true; } else LEDsBlink(3); } else if(Key[row-1][column-1] == 'E' &amp;&amp; EntryCount != 0) { State = 3; FloatingPointIncluded = false; Operand2_length = EntryCount; EntryCount = 0; Row = 0; Column = 0; Lcd_Cmd(_LCD_CLEAR); // Clear display Lcd_Out(1, 4, "Operation: "); Lcd_Cmd(_LCD_SECOND_ROW); Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on if(PORTA.B0 == 1) { PORTA = PORTA &lt;&lt; 1; Direction = 0; } } else LEDsBlink(3); } else if(State == 3) { if(Key[row-1][column-1] != 'E') { if(EntryCount == 0 &amp;&amp; (Key[row-1][column-1] == '+' || Key[row-1][column-1] == '-' || Key[row-1][column-1] == '/' || Key[row-1][column-1] == '*')) { Lcd_Chr_Cp(Key[row-1][column-1]); Operation_String = Key[row-1][column-1]; EntryCount++; } else LEDsBlink(3); } else if(Key[row-1][column-1] == 'E' &amp;&amp; EntryCount != 0) { State = 4; FloatingPointIncluded = false; EntryCount = 0; Row = 0; Column = 0; Lcd_Cmd(_LCD_CLEAR); // Clear display Lcd_Out(1, 3, "The Result: "); Lcd_Cmd(_LCD_SECOND_ROW); Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off Result = CalculateResult(); //printOut(Result, "/*rn"); FloatToStr(Result, Result_String); Lcd_Out(2,1,Result_String); PORTA = 0x0F; } else LEDsBlink(3); } else if(State == 4) { if(Key[row-1][column-1] == 'E') { Reset_Values(); Lcd_Cmd(_LCD_CLEAR); // Clear display Lcd_Out(1, 4, "Operand1: "); Lcd_Cmd(_LCD_SECOND_ROW); Lcd_Cmd(_LCD_BLINK_CURSOR_ON); // Cursor on PORTA == 0x0F; } } ButtonIsPressed = false; } // ***** Control of LEDs ***** else { if(State == 1) { if(PORTA == 0x0F) PORTA = 0x01; Delay_ms(300); if(PORTA &lt; 0x08) PORTA = PORTA &lt;&lt; 1; if(PORTA == 0x08) { Delay_ms(300); PORTA = 0x01; } } if(State == 2) { Delay_ms(300); PORTA = PORTA &gt;&gt; 1; if(STATUS.C == 1) { PORTA = 0x08; STATUS.C = 0; } } if(State == 3) { Delay_ms(300); if (Direction == 0) { PORTA = PORTA &gt;&gt; 1; if (PORTA.B0 == 1) Direction = 1; } else { PORTA = PORTA &lt;&lt; 1; if (PORTA.B3 == 1) Direction = 0; } } if(State == 4) { LEDsBlink(-1); } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload