CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Frequency Generator Issue

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
bnfdvn1
Guest







Frequency Generator Issue
PostPosted: Tue Feb 03, 2009 3:38 pm     Reply with quote

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







PostPosted: Tue Feb 03, 2009 3:39 pm     Reply with quote

Sorry - Compiler version is 4.082.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 03, 2009 3:44 pm     Reply with quote

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

View user's profile Send private message

Re: Frequency Generator Issue
PostPosted: Tue Feb 03, 2009 4:48 pm     Reply with quote

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







PostPosted: Tue Feb 03, 2009 5:31 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Feb 03, 2009 6:14 pm     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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