|
|
View previous topic :: View next topic |
Author |
Message |
bnfdvn1 Guest
|
Frequency Generator Issue |
Posted: Tue Feb 03, 2009 3:38 pm |
|
|
I am using a 16F819 to generate two square wave outputs 90 degrees phase displaced based on an analog input (10 bits). My problem is that for two ranges, 0-3500 Hz and 0-220 Hz, the outputs drop out periodically for 22 mSecs at certain points on the analog scale. On the 0-220 Hz range, the outputs drop out at 183 Hz. As I am writing this, I don't remember the point on the 0-3500 Hz scale but it is a different analog value. The PIC is running at 12 MHz and I am using timer 1, which runs at 3 MHz. FWIW, 22 mSec is around 16384 (0x4000) clock ticks. Below is the code to calculate the clock ticks.
Code: |
if ((AnaVal >= 8) & (Range > 0)) {
NoOutput = False;
TempVal4 = (long long)AnaVal * (long long)Range;
TempVal2 = 750000 * (long long)CalRange;
TempVal3 = TempVal2 / TempVal4;
TempVal4 = TempVal3 / 65536;
TempVal = TempVal3 % 0x10000;
TempVal4++;
}
else {
NoOutput = True;
TempVal4 = 1;
TempVal = 0x0DE8;
Delay_us(100);
}
T1Value = ~TempVal;
LoopCtr = TempVal4;
|
The LoopCtr value will be 1 for all frequencies higher than 11 Hz.
And this is the interrupt routine for timer 1.
Code: |
#int_TIMER1
void TIMER1_isr(void) {
byte ndx;
byte AFreqPhase[4] = {0x10,0x30,0x20,0x00};
set_Timer1(T1Value);
TimesThru--;
if (TimesThru == 0) {
TimesThru = LoopCtr;
PhaseCtr++;
if (NoOutput == False) {
ndx = PhaseCtr & 0x03;
Output_B(AFreqPhase[ndx]);
}
else
Output_B(0);
}
else
set_Timer1(0);
}
|
Why does the frequency drop out for 22 mSec at the specific analog inputs?? Any help will be greatly appreciated. I have been looking at this for a few days now.
Thanks! |
|
|
bnfdvn1 Guest
|
|
Posted: Tue Feb 03, 2009 3:39 pm |
|
|
Sorry - Compiler version is 4.082. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 03, 2009 3:44 pm |
|
|
Put some printf() statements in between the lines of code in your
calculations to check the math. Use "%LX" or "%LD" to display
values greater than a byte (in hex or decimal).
Then load some parameters for your calculations code, that you
believe are in the range that causes a problem. See if your math
is producing the correct results. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: Frequency Generator Issue |
Posted: Tue Feb 03, 2009 4:48 pm |
|
|
Here is how the CCS compiler compiles:
Code: |
.................... T1Value = ~TempVal;
0310: MOVF 58,W
0311: MOVWF 56
0312: COMF 56,F
0313: MOVF 59,W
0314: MOVWF 57
0315: COMF 57,F
|
Now suppose TempVal is 0x03ff, so that T1Value should be 0xfc00. But suppose this happened:
Code: |
.................... T1Value = ~TempVal;
0310: MOVF 58,W
0311: MOVWF 56
0312: COMF 56,F
0313: MOVF 59,W
0314: MOVWF 57
**** Timer 1 interrupt hits ****
0315: COMF 57,F
|
Then what T1Value will the interrupt routine use that time? 0xfc00? No it will be 0x03ff, which will cause a looooooong gap until Timer 1 reaches 0 again. (But I can't quite justify the 22 msec. gap. This gaps looks to be much longer.)
So you need to hand off the 16-bit value to the interrupt routine in a way that makes sure the interrupt routine is always seeing a complete calculation. You could do several things:
1. Disable interrupts around T1Value = ~TempVal;
2. Or, wait until just after an interrupt to do the assignment. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
bnfdvn1 Guest
|
|
Posted: Tue Feb 03, 2009 5:31 pm |
|
|
Ding, Ding, Ding!! We have a winner!!
I changed the code to be:
Code: |
TempVal = ~TempVal;
T1Value = TempVal;
LoopCtr = TempVal4;
|
and, at least after a quick look, it appears to be working correctly! This isn't a fast changing analog signal so this should work okay for this application.
Now that I know what the problem was, I know where the 20 mSec came from. Originally, I thought that the analog conversion wasn't completely done when I read the value so I increased the delay to 20 mSec to insure it was complete.
Code: |
set_adc_channel(ADCChannel);
delay_ms(20);
AnaVal = read_adc(); // Read the analog value
|
Now I can change this back to 10 uSec.
Thanks for the help!! I appreciate it!!! |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
|
Posted: Tue Feb 03, 2009 6:14 pm |
|
|
bnfdvn1 wrote: |
Code: |
TempVal = ~TempVal;
T1Value = TempVal;
LoopCtr = TempVal4;
|
and, at least after a quick look, it appears to be working correctly! |
Well, it is true that this can't cause the big error you had before, but it is still vulnerable to a smaller error. When setting T1Value = TempVal, it is possible to get interrupted between the setting of the two bytes. If you happen to be changing from 0xfbff to 0xfc00, then you could get one interrupt period of 0xfb00, which is off by 256 counts. You may not even notice it by casual observation on a scope, but if it matters, you ought to do something else to fix it. _________________ Robert Scott
Real-Time Specialties
Embedded Systems Consulting |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|