Optimization levels in WinAVR, wierd problem.
2009-04-30 by David VanHorn
Bear with me, this isn't simple. I have two sensors, each outputs a square wave. I need to accurately measure the period of each, and determine the difference in the two periods. Depending on how I set the optimization, I get different results. At -Os, I see values like 292, 304, 316. The values are spaced by 12! I won't ever see 305, 306, 307... If I recompile with -O0, the spacing between the values is different, but still mostly three discrete steps in values with nothing in between. I'm using an M644 at 20 MHz, T1 is running at CK/1 The basics are that I stop the clock to T1, and clear it.. Then I wait till I see a low, then wait till I see a high, then I start the timer. With the timer running, I wait till I see low, high, low high... till five periods have passed, then I stop the clock to T1, and take the data. Having done that, I do the same thing for the other sensor, then subtract the second sensor from the first, which should give me some small-ish value. The exact number isn't important, but what is puzzling me is that the intermediate values are missing. Like somehow I'm loosing low bits, but the delta is 12, which makes no sense from a binary perspective. // Prep for aquisition TCCR1B &= ~(1<<CS10); // Stop T1 (should already BE stopped, // but it's cheap insurance) TCNT1=0; // Clear T1 // Sync to the A channel while ( Sensor_Pin & (1<<ChannelA)); // Wait for a low, so we know we're not seeing // a high level yet while (!(Sensor_Pin & (1<<ChannelA))); // Wait for the high edge TCCR1B |=(1<<CS10);// START the clock to T1 // T1 is now counting the period width. // That can be as little as 25us // (5 periods * 5us * 20 MHz = 500 counts) // or as much as 138 uS // (5 periods * 23uS * 20 MHz = 2300 counts) while ( Sensor_Pin & (1<<ChannelA)); // Wait for a low on PD2 while (!(Sensor_Pin & (1<<ChannelA))); // Wait for a high on PD2 // One pulse has gone while ( Sensor_Pin & (1<<ChannelA)); while (!(Sensor_Pin & (1<<ChannelA))); // Now two while ( Sensor_Pin & (1<<ChannelA)); while (!(Sensor_Pin & (1<<ChannelA))); // Now three while ( Sensor_Pin & (1<<ChannelA)); while (!(Sensor_Pin & (1<<ChannelA))); // Now four while ( Sensor_Pin & (1<<ChannelA)); while (!(Sensor_Pin & (1<<ChannelA))); // Now five TCCR1B &= ~(1<<CS10); // Stop T1 A_Sensor_Raw = TCNT1; // Grab the data TCNT1=0; // Clear T1 for the next measurement. // Sync to the B channel, and proceed as above while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); TCCR1B |=(1<<CS10); while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); while ( Sensor_Pin & (1<<ChannelB)); while (!(Sensor_Pin & (1<<ChannelB))); TCCR1B &= ~(1<<CS10); Temp2 = TCNT1; TCNT1=0; //********** // Condition according to sensor // Scale to fit the histogram array // Take the difference, and add half A_Sensor_Raw = ((A_Sensor_Raw - Temp2) + (Sample_Bins/2)); // If the value is out of range then wrap it A_Sensor_Raw = (A_Sensor_Raw & 0x01FF); Why do I not see output like 290,291,292... ? -- There is no computer problem which cannot be solved by proper application of a sufficiently large hammer.