Using global float not working.

I'm working with a Freescale MC9S12DG256B with MW CodeWarrior IDE in C. I am using a global float in a RTI to accumulate a value, but I keeps displaying 7271460400000000.... as the result of the calculation.

Code snippet:

top of file: //they are initialized to zero. float currentMCF;

In RTI_ISR: // update minutes if(sec_ctr == 60){ sec_ctr = 0; mins_ctr = mins_ctr+1; currentMCF = (currentMCF + SCFM/1000.0); }

currentMCF is displayed on an LCD and alway comes back as garbage. SCFM is another global float that is being updated from a different function in the same file.

Any thoughts???

Reply to
eeboarder
Loading thread data ...

You're only showing half of the problem, the input part. What's the output part look like (as in sprintf)?

Otherwise, maybe sec_ctr never evaluates to 60. How is SCFM declared? If you're using the C formatting library, do you have the right floating point support enabled?

Do yourself a favor and declare currentMCF as volatile. Same for other non-local ISR variables.

JJS

Reply to
johnspeth

Well, for starters this is missing a "volatile" qualifier. And this being a float on a CPU which, I guess, doesn't support those in hardware, would complicate matters further. Just how certain are you that your compiler's runtime library support functions for implementing 'float' are reentrant?

In a nutshell: don't do that.

Reply to
Hans-Bernhard Bröker

I

is

in

I'm using floats just fine in other locations of the code. I put in the 'volatile' just now. Still not working.

SCFM is a global float. It is initialized to 0 in an initialize function, then calculated as follows:

SCFM=128.8*K*Di*Di*sqrt((ambPressure*diffPressure)/((ambTemperature+460.0)*Ss));

ambPressure and diffPressure are both floats calculated by other equations through my ADC.

Output: // displaying yesterday MCF sprintf(ATDstring6,"%f MCF yesterday ",currentMCF); writeLine(ATDstring6,1);

All other global variables in RTI_ISR are working fine. I have them outputing as a clock, and it is counting appropriately.

Reply to
eeboarder

Here is my file. I'll spare you the huge lookup table. Please excuse the sloppiness for now. It's a first run. :)

#include // derivative information #include "pll.h" #include "adc.h" // ADC_Init, ADC_Read #include "lcd.h" // LCD Display #include "flow.h" // flow calculation fuction #include "stdio.h" // common functions #include "math.h" // math functions

unsigned int ms_ctr; unsigned int sec_ctr; unsigned int mins_ctr; unsigned int hrs_ctr; unsigned int days_ctr;

float Temp[446]; volatile float currentMCF; volatile float yesterdayMCF;

float SCFM;

void flowCalc() {

float ambPressure; float diffPressure; float ambTemperature; unsigned int Conv1; unsigned int Conv2; unsigned int Conv3; char ATDstring1[16]; char ATDstring2[16]; char ATDstring3[16]; char ATDstring4[16]; char ATDstring5[16]; char ATDstring6[16];

for(;;) { // reading ATD channel 13(Temperature) Conv1 = ADC_Read(0x85); ambTemperature = Temp[Conv1]; //sprintf(ATDstring1,"%f deg F ",ambTemperature); //writeLine(ATDstring1,1); // reading ATD channel 14(Ambient Pressure) Conv2 = ADC_Read(0x86); ambPressure = (float)(((Conv2-205.0)/819.0)*50.0); //sprintf(ATDstring2,"%f PSIA ",ambPressure); //writeLine(ATDstring2,0); // reading ATD channel 15(Differential Pressure) Conv3 = ADC_Read(0x87); diffPressure = (float)(((Conv3-205.0)/819.0)*138.40); //sprintf(ATDstring3,"%f in H2O ",diffPressure); //writeLine(ATDstring3,1); // calculating flow in SCFM SCFM=128.8*K*Di*Di*sqrt((ambPressure*diffPressure)/((ambTemperature+460.0)*Ss)); sprintf(ATDstring4,"%f SCFM ",SCFM); writeLine(ATDstring4,0); // displaying time // sprintf(ATDstring5,"%id%ih%im%is ",days_ctr,hrs_ctr,mins_ctr,sec_ctr); // writeLine(ATDstring5,1); // displaying yesterday MCF sprintf(ATDstring6,"%f MCF yesterday ",currentMCF); writeLine(ATDstring6,1); } }

__interrupt void RTI_ISR() { // clearing flag CRGFLG = 0x80; // update milliseconds ms_ctr = ms_ctr+1; // update seconds if(ms_ctr == 25) { ms_ctr = 0; sec_ctr = sec_ctr+1; } // update minutes if(sec_ctr == 60){ sec_ctr = 0; mins_ctr = mins_ctr+1; currentMCF = (currentMCF + SCFM); } // fudge correction if(mins_ctr == 30){ sec_ctr = sec_ctr+42; } // updates hours if(mins_ctr == 60){ // fudge correction sec_ctr = sec_ctr+42; mins_ctr = 0; hrs_ctr = hrs_ctr+1; } // updates days if(hrs_ctr == 24) { hrs_ctr = 0; days_ctr = days_ctr+1; yesterdayMCF = currentMCF; currentMCF = 0.00; } }

void RTI_Init() { SCFM = 0.00;

ms_ctr = 0; sec_ctr = 0; mins_ctr = 0; hrs_ctr = 0; days_ctr = 0; currentMCF = 0.00; yesterdayMCF = 0.00; // Enable interrupts asm cli // RTIE On CRGINT = 0x80; // RTI Freq Divide Rate 11x2^16 // Interrupts every 90.112 ms RTICTL = 0x74; }

void temperatureInit() { Temp[0]=-60.0000000000000; Temp[1]=-53.1734380020266; Temp[2]=-46.2560695623409;

Reply to
eeboarder

"volatile" is far from enough - in fact, it probably will not affect the code at all. The important thing is to make sure that accesses outside the interrupt routine are atomic.

However, a better solution is to use a single byte flag variable (which should be volatile) and do the calculation outside the ISR.

This is important - on small micros, library functions used for floating point are often not re-entrant.

At least, don't do it in the interrupt routine. Have the interrupt routine set a flag, and do the calculations in the main code when the flag is set.

Reply to
David Brown

Well, let's see. All of these:

have to be either made volatile, or removed from file scope. As-is, there's no way of knowing what'll happen if any routine other than your RTI ISR accesses them.

This has to be made volatile, too.

What calls this routine? And, perhaps more importantly, who will pat the puppy while it sits in an endless loop?

[...]

So your variable ms_ctr is ill-named. It doesn't count ms.

This completely misfires. You're applying your fudge term 2400 times in that minute. Not even to mention that your (secs_ctr == 60) condition will fail miserably with the above kind of fudging in place.

That doesn't seem to match the way you count interrupts into seconds.

Reply to
Hans-Bernhard Bröker

Well, let's see. All of these:

have to be either made volatile, or removed from file scope. As-is, there's no way of knowing what'll happen if any routine other than your RTI ISR accesses them.

This has to be made volatile, too.

What calls this routine? And, perhaps more importantly, who will pat the puppy while it sits in an endless loop?

[...]

So your variable ms_ctr is ill-named. It doesn't count ms.

This completely misfires. You're applying your fudge term 1500 times in that minute. Not even to mention that your (secs_ctr == 60) condition will fail miserably with the above kind of fudging in place.

That doesn't seem to match the way you count interrupts into seconds.

Reply to
Hans-Bernhard Bröker

There are forums you can ask about this at

formatting link
(the appropriate Codewarrior compiler forum would be the appropriate forum...), and there are people there who KNOW whether the FP package is re-entrant or not.

Reply to
Ben Bradley

I set flags and did the calcualtion elsewhere. Everything is working as it should!

Thank you.

Reply to
eeboarder

Everyone learns this lesson ("set flags in the ISR and do the real stuff elsewhere") eventually ;).

Welcome!

Best,

Steve

--

formatting link

Reply to
Steve at fivetrees

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.