|
|
View previous topic :: View next topic |
Author |
Message |
J.H.Sun
Joined: 27 Jun 2011 Posts: 4
|
2 CCPs conflict |
Posted: Mon Jun 27, 2011 11:17 pm |
|
|
Dear all, I want to ask for help that the PIC18 used to receive and calculate the tachometer signal and also used to get the signal from remote controller (flight). So CCP1 is for remote controller(low:20ms, high:1ms), CCP2 is for tachometer. Here is the problem I am curious:
1. The code can not calculate the CCP1.
2. Even I once let CCP1 run, but it does not calculate properly.
3. How could I solve the conflict between multi-interrupts ?
Thank you!
Code: |
#include <18F458.h>
#include <stdlib.h>
#fuses HS,WDT1//(18ms&4ms)
#use delay(clock=20000000)
#use rs232(baud=9600,rcv=PIN_C7,xmit=PIN_C6)
#priority CCP1,CCP2,RDA
#define bsize 128
#include <18F458.h>
#include <stdlib.h>
#fuses HS,WDT1//(18ms&4ms)
#use delay(clock=20000000)
#use rs232(baud=9600,rcv=PIN_C7,xmit=PIN_C6)
#priority CCP1,CCP2,RDA
#define bsize 128
int8 H_flg=0,A_flg=0,buffer[bsize],len=0,i,j,n,out[13];
int16 rpm=0,force=0,rate_ctrl=0;
int32 pwm=0;
float period=0;
char data[4];
void rcv()
{
int8 buf[20], ii, jj ;
for(ii = 0 ; ii < len ; ++ii)
{
for(jj = 0 ; jj < 15 ; jj++)
buf[jj] = buf[jj+1] ;
buf[15] = buffer[ii] ;
if(buf[1] == '4' && buf[2] == '1' &&
buf[3] == '5' && buf[4] == '5' &&
buf[6] == '2' && buf[7] == '0' &&
buf[8] == '0' && buf[9] == '0' &&
buf[10] == '0')
{
data[0] = buf[11] ;
data[1] = buf[12] ;
data[2] = buf[13] ;
data[3] = buf[14] ;
if(buf[5] == '0')
force = atof(data) ;
else if(buf[5] == '1')
force = -atof(data) ;
out[8]=force/256;
out[9]=force%256;
}
}
for(ii = 0 ; ii < bsize ; ++ii )
buffer[ii] = 0;
len = 0;
}
#INT_CCP1 //(pwm, initial rising edge)
void CCP1_isr()
{
if(H_flg ==0 && A_flg ==0)
{
set_timer1(0);
setup_ccp1(CCP_CAPTURE_FE) ;
H_flg = 1 ;
}
else if(H_flg ==1 && A_flg ==0)
{
pwm =get_timer1()*8; //10^-1 us
setup_ccp1(CCP_CAPTURE_RE) ;
H_flg = 0 ;
out[3]= pwm/65536;
out[4]=(pwm%65536)/256;
out[5]=(pwm%65536)%256;
}
}
#INT_CCP2 //(rpm)
void CCP2_isr()
{
if(A_flg ==0 && H_flg ==0)
{
set_timer3(0) ;
A_flg = 1;
}
else if(A_flg ==1 && H_flg ==0)
{
period = (float)get_timer3()*0.0008 ;
A_flg = 0;
rpm = (int16)(60000.0/period) ;
out[6]=rpm/256 ;
out[7]=rpm%256 ;
}
}
#int_RDA
void RDA_isr(void)
{
if(H_flg ==0)
{
buffer[len] = getc() ;
++len ;
if(len >= 16)
rcv() ;
}
}
void main ()
{
for(n=0;n<13;n++)
{
out[n]=0;
}
setup_wdt(WDT_ON) ;
setup_ccp1(CCP_CAPTURE_RE) ;
setup_ccp2(CCP_CAPTURE_RE) ;
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4) ;
setup_timer_3(T3_INTERNAL|T3_DIV_BY_4) ;
enable_interrupts(INT_CCP1) ;
enable_interrupts(INT_CCP2) ;
enable_interrupts(INT_RDA) ;
enable_interrupts(GLOBAL) ;
while(TRUE)
{
restart_wdt();
out[0]=252;
out[1]=253;
out[2]=0;
out[10]=0;
out[11]=254;
out[12]=255;
if(rate_ctrl ==15000)//20Hz(10750)
{
for(i=0;i<13;i++)
{ restart_wdt();
printf("%c",out[i]);
}
rate_ctrl = 0 ;
}
rate_ctrl++ ;
}
} |
Last edited by J.H.Sun on Tue Jun 28, 2011 2:09 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Jun 28, 2011 2:00 am |
|
|
On thing 'leaping out', is your INT_RDA.
If H_FLG is non zero, characters won't be read. This _will_ result in the handler being repeatedly called, and the code effectively being hung.
If you want to throw characters away, read the character, then don't save it into the buffer. INT_RDA, says 'there is a character waiting to be read'. You _must_ read the character.
Then, remember that when the CCP triggers, it is the CCP registers that hold the timer value at the moment it triggered, not the timer registers. read the CCP, not the timer to get the moment when this occurred. Otherwise if another interrupt is being handled when the event occurs, there will be a significant error in the value you get.
Best Wishes |
|
|
J.H.Sun
Joined: 27 Jun 2011 Posts: 4
|
|
Posted: Tue Jun 28, 2011 2:26 am |
|
|
thanks,Ttelmah !!
I just edit the code and still some problems.
The "H_flg" and "A_flg" is used to guarantee when CCP1 or CCP2 working
without being interrupt by other interruptions. Now, CCP2 can receive signal and calculate RPM from tachometer correctly, but CCP1 can not work. I tries to input signal (low:2ms, high:2ms ...), it can run. But if the signal like this (low:20ms, high:1.5ms), result from CCP1 is "0". I guess it is running, but some error causing it unable to detect, or the data being "reset" by watchdog timer.
Sincerely |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Jun 28, 2011 9:25 am |
|
|
OK.
Your other big problem, is performing float maths in the ISR. Don't.
Just store the values from the CCP registers, and set a flag. Perform the maths in the main code, if the flag is set. Float maths take s huge amount of time. You are performing a multiplication, and a division in the ISR. General rule of thumb is "always keep ISR's short". You are talking about 2000 machine instructions to do these operations.....
Best Wishes |
|
|
J.H.Sun
Joined: 27 Jun 2011 Posts: 4
|
|
Posted: Wed Jun 29, 2011 5:21 am |
|
|
Thanks,Ttelmah!
All the suggestions really help me a lot , by taking out some works especially "float" in the interruptions. The probelm has been solved.
Sincerely |
|
|
|
|
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
|