|
|
View previous topic :: View next topic |
Author |
Message |
bliztkrieg
Joined: 23 Jul 2018 Posts: 20
|
Problem with ccp |
Posted: Mon Jul 23, 2018 10:37 am |
|
|
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
|
|
Posted: Mon Jul 23, 2018 11:21 am |
|
|
What are the value 300* 316 respective to what an unsigned int16 can hold.? |
|
|
bliztkrieg
Joined: 23 Jul 2018 Posts: 20
|
|
Posted: Mon Jul 23, 2018 9:58 pm |
|
|
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
|
|
Posted: Mon Jul 23, 2018 10:47 pm |
|
|
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
|
|
Posted: Tue Jul 24, 2018 1:21 am |
|
|
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.. |
|
|
|
|
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
|