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 CCS Technical Support

Problem with ccp

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



Joined: 23 Jul 2018
Posts: 20

View user's profile Send private message

Problem with ccp
PostPosted: Mon Jul 23, 2018 10:37 am     Reply with quote

Code:
#include <18f252.h>
#use delay(clock=20M)
#fuses NOPROTECT, HS, NOWDT, NOBROWNOUT, NOLVP
#use rs232 (baud=9600, xmit=PIN_C6, rcv=PIN_C7)

unsigned int16 ccp_val1 = 0, ccp_val2 = 0;
int8 counter = 0;
unsigned int16 count = 0, _count = 0;
int1 flag = false;

#INT_CCP1
void ccp_isr()
{
   count+=1;
}

#INT_CCP2
void ccp2_isr()
{
   _count+=1;
}

#INT_TIMER1
void tmr1_isr()
{
   counter++;

   if(counter == 10)
   {
      flag = true;
      /*ccp_val1 = count-3;
      ccp_val2 = _count;
      counter = 0;
      count = 0;
      _count = 0;*/
   }
}
void main()
{
   setup_ccp1(CCP_CAPTURE_RE);
   setup_ccp2(CCP_CAPTURE_DIV_16);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
   enable_interrupts(INT_CCP1);
   enable_interrupts(INT_CCP2);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   while(1)
   {
      if(flag)
      {
         disable_interrupts(GLOBAL);
         ccp_val1 = count - 3;
         ccp_val2 = _count * 316; // problem lies here
         counter = 0;
         count = 0;
         _count = 0;
         flag = false;
         enable_interrupts(GLOBAL);
      }

      printf("ccp1 = %lu, ccp2 = %lu\r\n", ccp_val1, ccp_val2);
   }
}


whenever i try to manipulate ccp_val2 variable it does not give me a fixed value instead sometimes it goes to zero sometimes to 60k, while the answer should be, say _count=300, 300*316, can anyone tell me what am i doing wrong ?
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 11:21 am     Reply with quote

What are the value 300* 316 respective to what an unsigned int16 can hold.?
bliztkrieg



Joined: 23 Jul 2018
Posts: 20

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 9:58 pm     Reply with quote

alan wrote:
What are the value 300* 316 respective to what an unsigned int16 can hold.?


yes i know the value will exceed 65535 it was just an example to give a better picture of what is happening
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jul 23, 2018 10:47 pm     Reply with quote

What if you hardcode the value of _count at 200, for testing ?
What happens ? Does it still fail ? Example:
Quote:

while(1)
{
if(flag)
{
disable_interrupts(GLOBAL);
ccp_val1 = count - 3;

_count = 200; // *** Hardcoded value for debugging ***

ccp_val2 = _count * 316; // problem lies here
counter = 0;
count = 0;
_count = 0;
flag = false;
// enable_interrupts(GLOBAL); // *** Disable interrupts for now
}

printf("ccp2 = %lu\r\n", ccp_val2); // *** Print only ccp2 for now
}
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Tue Jul 24, 2018 1:21 am     Reply with quote

Comments:

First, you say "i know the value will exceed 65535". Do you realise what will happen when it does?. You get the 16bit remainder into 'ccp_val2'. So when _count is 207, you will get 65412, but when it gets to 208, you will get just 192. Hence the big jump you are seeing....

Then your count may well miss counts, because you are disabling interrupts for a long time. Keep the time as short as you can:
Code:

         disable_interrupts(GLOBAL);
         ccp_val1 = count;
         ccp_val2=_count;
         enable_interrupts(GLOBAL);
         ccp_val1-=3;
         ccp_val2 *=316; // problem lies here
         counter = 0;
         count = 0;
         _count = 0;
         flag = false;

This way the interrupts only have to be disabled for two data moves, while all the other operations like the maths can be done afterwards.
To avoid the maths problems, make ccp2_val an int32 variable. Then the maths will use int32 arithmetic.

Now as already mentioned, there are 'issues' with the maths. So the multiplication will cause an overflow at a count of 208, but also the subtraction will cause a problem at the start. 'count' is 1 (say). ccp_val1, will then become 65534. It'll go 65534 65535, 0, 1 etc.. This can be avoided by making ccp1_val a signed int32, and printing with ld instead of lu, so it'll display -2, -1, 0 etc..
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