This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

improper fixup error



I have written a program read the converted Analog to digital signal and disply on 4 digit seven
segment display indicator, by multiplexing .

Alos I have multiplied the ADC out put by 2.78 and 0.02, to get a perfect scaling for the
display

I have attached code for reference.

When I compiled this program , I am GETTING " IMPROPER FIXUP ERROR"

please let me know if this( test= adc_input*.02*2.78; ) multiplication allowed. I think it is not a full floting point
arithmetic



Kindly help me resolve this.

****************************************************************************************

#include<reg51.h>
#include<intrins.h> 

sbit unit=  P2^0;	 /* unit data for sending through the port */
sbit tens=	P2^1;    /* Tens  place for sending the data */
sbit hundred=P2^2;   /* Hundred place for sending the data */
sbit thousand=P2^3;  /* thousand place for sending the data */
sbit relay= P2^4;    /* for relay */
sbit write = P2^5;   //set to   zero for write(p2.5)
sbit read  = P2^6;   //set to zero for read (p2.6)

unsigned int count;	 /*count to track 2 millisecond interrupt */

/* CODE FOR SEVEN SEGMENT DISPLAY */
unsigned char code table[]={0xBF,0x86,0xDB,0xCF,0xEC,0xED,0xFC,0x87,0xFF,0XE7};

unsigned char code  lookup[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};

unsigned char  temp;    /* TO increment the variable  at every  2 seconds */

void sec_timer(void);   /* Interrupt fnction for timer 0 */      
void convert(void);		/* interrupt function to read analog to digital output */
void _nop_(void);  
void display(void);

float test;
unsigned int t_first,t_second,new_test;
unsigned int  volatile  adc_input;
unsigned char first,second,third,fourth;
unsigned char msb,msb_1,msb_2,msb_3;

void main()

{
	TMOD= 0x01; /* set the timer 0 to MODE 1 for 16 bit counting */
   	TH0=  0xF8; /* th=f8,tl=f8 */ 
   	TL0=  0x2F;
	temp=0;
	ET0=1; /* enable timer over flow interrupt */
	IT0=0; /* Set the external interrupt  INT0/ to  low level triggered  interrupt */ 
    EX0=1; /* Enable the external interrupt INT0/ */
	EA=1; /* Enable  all the  interrupt */

	TR0=1; /* start  the timer */	

  while(1)
	  {

	write =0;	//start conversion
 	test= adc_input*.02*2.78;

	new_test =test*100;

	first =  new_test /1000;
	t_first =new_test%1000;
	second  =  t_first/100;
	t_second= t_first%100;
	third   = t_second/10;
   	 fourth = t_second%10;


	msb=   lookup[first];//MSB, left most digit
	msb_1= lookup[second];//MSB-1
	msb_2= lookup[third];//MSB -2
	msb_3= lookup[fourth];//MSB-3 

    display();	//call to display routine.


	}

}

	void display (void)
	{
		 P0=table[msb];
		  unit=1; /* Send the data on  PORT 0 for MSB0 LED */
		  _nop_();		
		   unit=0;
		  _nop_();
		 P0=table[msb_1];
		  tens=1;
		  _nop_();
		  tens=0;
		  _nop_();
		P0=table[msb_2];
		  hundred=1;
		  _nop_();
		  hundred=0;
		P0=table[msb_3];
		   thousand=1;
		  _nop_();
		  thousand=0;
	}



void convert(void)interrupt 0  using 2

{
	
	write=1;	/* stop convertion */
	read = 0; /* send the read pulse */
	adc_input=P1; /* Read the ADC out put*/
	read=1; /* disable the read switch,INT0 will go low following this*/
	IE0= 0; /* clear the interrupt */
	write =0; /*start convert */

}

/* To generate the interrupt at interval of 2 milliseconds  USING TIMER 0 IN  MODE 1 */
/* USING 12MHz crystal,1 count - 1 microseconds . hence when "0xF82F' is loaded to  */
/* the TH0 and TL0   Timer register ,will generate interrupt at every 2 millisecods */

 void sec_timer(void)interrupt 1 using 1
	{
	 TR0=0; /* stop  timer */
	 EA =0; /* Disable interupt */
	 TH0=0xF8;/* Reload timer to generate interrupt for every 2 milliseconds */
	 TL0=0x2F;/*Reload timer to generate interrupt for evert 2 milliseconds */
	 count=count-1; /* decrement  counter fo revery 2 milliseconds */
	 EA=1;/* enable interrupt */
	 TR0=1; /* start timer */	
	} 	      		

*********************************************************************************************

Parents
  • Hello:

    Sorry I can't help you with the error you are getting. I just have a suggestion that may or may not help you with your application. How about replacing your floating point math with something like this.

    (UWORD)(((ULONG)adc_input * 5693 + 512 ) >> 10 );
    Where:
    1. 5693 = 2.78 * 2 * 1024
    2. Adding 512 rounds up (optional)
    3. Shifting right 10 time divides the result by 1024

    This avoids floating point math which is generally slow (I have not timed the Keil compiler's performance). The only question is if it provides enough accuraccy. You can use a spreadsheet to quickly calculate the result for every possible adc_count. You can increase the muliplier and divider (1024) to gain more accuraccy, just be careful to check for overflow.

    Here is an example using adc_count = 867:

    Using floating point math
    867 * 2.78 * 0.02 * 100 = 4820 (following your program flow)

    Using integer math
    (867 * 5693 + 512) >> 10 = 4820

    -Walt

Reply
  • Hello:

    Sorry I can't help you with the error you are getting. I just have a suggestion that may or may not help you with your application. How about replacing your floating point math with something like this.

    (UWORD)(((ULONG)adc_input * 5693 + 512 ) >> 10 );
    Where:
    1. 5693 = 2.78 * 2 * 1024
    2. Adding 512 rounds up (optional)
    3. Shifting right 10 time divides the result by 1024

    This avoids floating point math which is generally slow (I have not timed the Keil compiler's performance). The only question is if it provides enough accuraccy. You can use a spreadsheet to quickly calculate the result for every possible adc_count. You can increase the muliplier and divider (1024) to gain more accuraccy, just be careful to check for overflow.

    Here is an example using adc_count = 867:

    Using floating point math
    867 * 2.78 * 0.02 * 100 = 4820 (following your program flow)

    Using integer math
    (867 * 5693 + 512) >> 10 = 4820

    -Walt

Children
No data