Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to separate decimal and fraction part of a number in C language

Status
Not open for further replies.

djc

Advanced Member level 1
Joined
Jan 27, 2013
Messages
402
Helped
3
Reputation
6
Reaction score
2
Trophy points
1,298
Location
India
Activity points
4,554
Hi all,

Can anybody please suggest me a logic to separate decimal part and fraction part of a number using C. Say i have a current value of 12.15 mA and corresponding ADC value is 155.2. Now i will convert it using some formula to original value 12.15. Now how to separate fraction and decimal part using C and display it on 4 FND's connected on PORT B1,B2,B3 and B4. I can display direct ADC value on FND like 123 or any other ADC value directly on FND but separation is the issue now .I am using PIC16F72 and mickroC PRO for PIC. Please guide

Thanking You
 


Code C - [expand]
1
2
3
4
5
6
7
8
9
unsigned int beforedecimal, afterdecimal;
 
void main(){
 
         beforedecimal = 12.15;   //result is 12
         afterdecimal = 12.15 * 100;    //result is 1215
         afterdecimal = afterdecimal - (beforedecimal * 100);  //result is 1215 - 1200 = 15
 
}

 

this works fine if you know beforehand what's before the decimal ...

I would rather go for something like this:
Code:
...
after_decimal = number - floor(number);
before_decimal = number - after_decimal;
..
 

hi,
Thanx jayanth n lucbra, However what library we have to add for floor function? will it work in mikroC pro for PIC compiler?
 

yes - math.h is the one you need for floor and ceiling functions
 

hi,
Thanx for the guidance guys. However i am facing new issue now. The logic i applied to convert current which is i am getting through ADC into same value as current is not working. Means for 12.15mA i am getting abrupt value. Formula i derived is (required scale * ADC reading)/256. Required scale is 0-20 here and 256 is range of ADC 8 bit ADC output. How to tackle this issue?
 

For all programming tasks that involve conversion of numbers into a decimal representation, I would primarly think of sprintf() and similar formatting functions provided by the C compilers.
 

hi,
I am using inbuilt ADC in PIC16F72, Vref is VDD. How to multiply float and unsigned int?
 

Hi,
Here is the code. Compiler is mikroC PRO for PIC. Now I am getting only decimal part and no fractional part on FND. I have ready made hardware so cant show you the circuit, however its tested so no isues with the circuit and hardware.
Code:
/****************************************************************
1) RA0 is selected as input channel
2) GO/DONE bit must be set before monitoring it for going low.
******************************************************************/

     int arr[10] = {0x5f,0x06,0x3b,0x2f,0x66,0x6d,0x7d,0x47,0xff,0x6f};
     int  no1,no2,no3,no4;
     int value=20,bulb=0,On_Off=1,k=220,i;
     int temp,temp_1;
     int beforedecimal, afterdecimal;

void interrupt()
{
     if(PIR1.ADIF == 1)
     PIR1.ADIF = 0;

}
void convert()
{
                                       no1 = beforedecimal/10;   //1st digit in decimal no.
                                       no2 = beforedecimal%10;   //2nd digit in decimal no
                                       no3 = afterdecimal/10;    //1st digit in fractional no
                                       no4 = afterdecimal%10;    //2nd digit in fractional no


                                       PORTC = arr[no1];         //1st digit in decimal no.
                                       PORTB.B1 = 1;
                                       Delay_ms(5);
                                       PORTB.B1 = 0;

                                       temp_1 =  0x80 | arr[no2]; //2nd digit in decimal no
                                       PORTC = arr[no2];
                                       PORTB.B4 = 1;
                                       Delay_ms(5);
                                       PORTB.B4 = 0;

                                       PORTC = arr[no3];        //1st digit in fractional no
                                       PORTB.B3 = 1;
                                       Delay_ms(5);
                                       PORTB.B3 = 0;

                                       PORTC = arr[no4];        //2nd digit in fractional no
                                       PORTB.B2 = 1;
                                       Delay_ms(5);
                                       PORTB.B2 = 0;
                                       Delay_us(4);    //Call delay 4 microseconds;
}

void main()
{
     TRISA = 0xff;      //Set port A direction as i/p
     //TRISA = 0x00;        //Port A as output
     PORTA = 0X00;        //ALL BITS OFF
     TRISB = 0x00;        //Set port B as output
     TRISC = 0x00;        //Set PORT C as output

    

    
     ADCON0 = 0X40;       //CLOCK SELECTION Fosc/2 AND ANALOG CHANNEL SELECTION channel RA0 as input
     ADCON1 = 0X00;       //ALL CHANNELS AS ANALOG INPUT Vref is VDD
     //ADCON1 = 0x00;     //Vref is VDD

     //PORTA.A1 = 1;        //PORT A0 as input

     PORTB.B1 = 1;
     PORTB.B2 = 1;
     PORTB.B3 = 1;
     PORTB.B4 = 1;

                PORTC = 0xFF;
                Delay_ms(1000);
                PORTC = 0x00;
                Delay_ms(1000);

                INTCON.GIE = 0x80;              //Enable global interrupts GIE=1
                PIR1.ADIF = 0;
                PIE1.ADIE = 1;               //Enable ADC interrupt
                               while(1)

                               {
                                       
                                       temp = ADC_Read(0);             //read the ADC value

                                       temp = ((20*temp)/255);
                                       //temp = 8.12;
                                       beforedecimal = temp;
                                       afterdecimal  = temp*100;
                                       afterdecimal  = (afterdecimal - (beforedecimal*100));                              
                                            
                                                                                                                                  
                                         convert();

                                    }


}
 

Make Vref = 1.7V and use the below code. If you use 5V Vref you wont get good values as max o/p of LM35 is 1.5V.

https://www.edaboard.com/threads/288404/#post1233434

https://www.st.com/st-web-ui/static...ical/document/application_note/CD00015425.pdf


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
unsigned char strtemp[5];
float temp = 0.0;
unsigned char ccdigits[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned char ccdigitsdp[10] = {0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF};
unsigned char cadigits[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
unsigned char cadigitsdp[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned int i = 0;
 
void display()
{
       PORTB = 0x01;
       PORTC = ccdigits[strtemp[0] - 0x30];
       Delay_ms(5);
       PORTB = 0x02;
       PORTC = ccdigits[strtemp[1] - 0x30];
       Delay_ms(5);
       PORTB = 0x04;
       PORTC = ccdigits[strtemp[2] - 0x30];
       Delay_ms(5);
 
 
}
 
 
void main()
{
     TRISA = 0xFF;
     PORTA = 0X00;
     TRISB = 0x00;
     TRISC = 0x00;
     PORTB = 0x00;
     PORTC = 0x00;
     ADCON1 = 0b00000011;
 
     while(1){
 
            temp = ADC_Read(0);
            temp = temp * 0.6666666666666667;
            FloatToStr(temp, strtemp);
            strtemp[3] = '\0';
        display();
 
     }
}

 
Last edited:

hi,

Hey thanx jayanth. Issue is solved now. I just divided by 231 instead of 255 as ADC is giving o/p of 231 for 20mA. I am trying your post now.

Thanking you
 

hi jayanth,

In my compiler mikroC PRO for PIC it's giving an error when i add function "FloatToStr(temp, strtemp);" though i added the required libraries. May i ask you wy you multiplied with the no '0.6666666666666667'. How does it help? One more question, 8 bit ADC output is 0-255 in decimal. But when when current which is input to ADC varies many times due to transition the last digit flickers, eg. if current value is 78 then as current input varies slowly digit 8 flickers to show 9. It happens almost every time for the last digit. For this i tried to read ADC multiple times and took average but its affecting the accuracy. Can you plz tell any other solution?
 

hello,

why not using 10 bits for ADC resolution ?
do the measure inside the interrupt , or disable
this interrupt wich do nothing usable.
 

hello paul,

ADC is inbuilt in pic 16f72, it's 8 bit, can't change it.
 

hello,

Oups !

Maybe you can accumulate 10 times the ADC value in an integer variable
and do calculation on it , to increase resolution.


Code:
int Somme=0;

void main()
{
.......
........
while(1)
{
Somme=0;
for (i=0;i<9;i++
{
Somme=Somme + (int) ADC_Read(0);
Delay_ms(100);
}
temp=(float) Somme * 12.5 / 1552.0 ;  //from  your data in post #1
FloatToStr(temp, strtemp);
 strtemp[3] = '\0';
display();
 }
}
 

1.7 V gives 255 as adc value so, for

1.5 V adc value will be 225

If 225 adc value = 150 degree C, then

225 * x = 150

x = 0.6666666666666667

If your adc value is 175 then

175 * 0.6666666666666667 = 116.6666666666667 deg C.
 

hi,

Thanx jayanth and paul. Paul current value 12.5mA and corresponding value 155.2 which will actually be whole number not exactly 155 may be near about that these are just an examples. These values will keep on changing. As current changes ADC value will also change.

Thanking you
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top