Whats wrong with my preprocessor statements?

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simple:

#define QUAD_SPEED_SAMPLE_TIME 0.2
#define TIMER0_PRESCALER 64
#define QUAD_SAMPLE_TIME_COUNT (int) (F_CPU*QUAD_SPEED_SAMPLE_TIME/256/TIMER0_PRESCALER)

...

#if QUAD_SAMPLE_TIME_COUNT < 1
		#error "Sample period too short, or prescaler too large"
#endif

Error: missing binary operator before token "("

I've trying making the QUAD_SAMPLE_TIME_COUNT into a function accepting the "TIMER0_PRESCALER" variable, but I just had the exact same error message. I also tried calculating QUAD_SAMPLE_TIME_COUNT and then made a new variable TEMP_SAMPLE and tried testing that against "< 1" with the same problem.

I'm at a loss.

Cheers,
Tom

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#defines terminate at the end of a line, unless the line ends with backslash.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can never have too many parentheses.

I would do this:

#define QUAD_SPEED_SAMPLE_TIME 0.2
#define TIMER0_PRESCALER 64
#define QUAD_SAMPLE_TIME_COUNT ((int) (F_CPU*QUAD_SPEED_SAMPLE_TIME/256/TIMER0_PRESCALER))

...

#if (QUAD_SAMPLE_TIME_COUNT < 1)
      #error "Sample period too short, or prescaler too large"
#endif

This would probably have solved your problem.

#if (QUAD_SAMPLE_TIME_COUNT) < 1

Mind you, I can see no reason for the (int) cast if you are only using this expression in the pre-processor.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why tempt fate with the 0.2? How about a 1/5?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lee,

You can use double precision arithmetic if you like for pre-processor math. The only risky part is if you test 'floating point equalities'. A negative comparison should always be fine.

Unless of course the macro is used elsewhere in the C code. A cast is always wise in this case.

Using 0.2 ensures f-p math. Using 1/5 would mean integer math. In this case either would do. But there are many expressions that go seriously wrong in integer arithmetic. They work fine in f-p.

David.

Last Edited: Thu. Jun 3, 2010 - 04:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lagger: it is one line. the forum put it in two.
david: done both, both unsuccessful
theusch: didnt work

:(

thanks for the suggestions so far though!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just food for thought:

#define SUB_ONE(x) (x-1)

Now think about how your (int) cast in the above is interpreted.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you getting the #error line? i.e. it is CPP.

Or are you getting errors from the C parser? i.e. what is seen in the expanded source code.

The latter needs you to inspect "file.i"

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tkurowski wrote:
theusch: didnt work
Have you tried removing the "(int)" cast?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson: it just subtracts one, then rounds down to the nearest integer, right? the problem was that if i didnt put the (int) cast, Id get a "floating constant in preprocessor definition" error.

David: I'm not too knowledgable in what youre talking about. I can tell you im using gcc with winavr. so probably not CPP...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Traditionally a C compiler used several programs:
pre-processor: cpp
parser: cc1
code generator: cc2
optimiser: opt

Nowadays all these passes are combined in one program. You can always get cpp to run even if it is only a command line switch to the big compiler program. Conventionally you use: 'cc -E' to run cpp

Your makefile may even have a rule to make 'file.i' or you look up the docs to tell you how via a GUI.

My question really is:
What error report do you get from compilation?

The error messages are there for a reason. It tells you where the problem lies. Or a least gives a pretty good clue.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think '#if' likes to play with 'non-integer constants'

try this-
#if 0.2 < 1
#endif

preprocessor no likey

http://gcc.gnu.org/onlinedocs/cp...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You could use this code:

#define QUAD_SPEED_SAMPLE_TIME 5
#define TIMER0_PRESCALER 64
#define QUAD_SAMPLE_TIME_COUNT                                          \
(                                                                       \
    (F_CPU + (QUAD_SPEED_SAMPLE_TIME * 256 * TIMER0_PRESCALER / 2)) /   \
    (QUAD_SPEED_SAMPLE_TIME * 256 * TIMER0_PRESCALER)                   \
)

It only utilizes integer math. Adding the half divisor to the divident results correct rounding.

Example:
1024.0 / 38.0 = 26.947
1024 / 38 = 26
(1024 + 19) / 38 = 27

Regards
Sebastian

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

first of all, sorry for not replying sooner.

Second of all:
david and curtvm:
i think you are right.

i changed some stuff around (i dont remember what), but I definitely kept 1/5 instead of 0.2. With that, everything ran smoothly. Kind of annoying that only integer constants can be used... what if I wanted 0.27213? Would the only way to get around that be to multiply it all by 1000000?

Cheers,
Tom

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

what if I wanted 0.27213

17834 / 65536 is 0.272125244140625 - is that close enough?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tkurowski wrote:
Kind of annoying that only integer constants can be used... what if I wanted 0.27213
What compiler? Maybe check at the C level rather than CPP? With GCC, I do something like:
#define compileTimeAssert(pred) switch(0){case 0:case pred:;}
...
compileTimeAssert(QUAD_SAMPLE_TIME_COUNT >= 1);

Google for compile time assert for other alternatives.

Eugene

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

what if I wanted 0.27213? Would the only way to get around that be to multiply it all by 1000000?


That is too broad a statement to answer directly.

Let's consider my typical app first. Input might come from a 10-bit A/D value, or maybe a 10- to 16-bit timer count number--a small integer. Does it make sense to try to get the calculations to 5 figures? Usually not.

Back to the pre-processor: You could let the compiler do the arithmetic at compile time and then the cast would use the resulting [small] integer value. No different than your example and 100000l.

In specific cases, I often have equations with factors such as yours. Most typical is A/D counts to some value like temperature. I let Excel do the linear curve fitting for me with test data, and might come up with

degreesF = -3.333*ADC + 162.2

Then it is easy to go to tenths of degrees

degreesF*10 = -3333*ADC/10000 + 1622

to do the y = rise * x / run + intercept.

But I digress. I set up a VB program to brute-force find a nice ratio for an arbitrary number such as yours. Firing it up for curiousity with your 0.27213:

83/305 is within 1.1E-6
455/1672 is within 8.1E-7
704/2587 is within 1.2E-7

If we relax it a bit to <1E-5, 37/136 and 40/147 and many others will allow using a 10-bit A/D count and calculations without going to "long".

So that's what I do with arbitrary factors. :)

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah, both youre points are obviously good. And I'mre sure there are more ways of doing it. That last question was just curiosity I guess. Floating point preprocessing would still be awesome!

Thanks for your help everyone.

Tom