|
|
View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Problem with CCP1 interrupt |
Posted: Sat Aug 07, 2004 10:32 am |
|
|
Hi I am hoping that someone smarter than me can shed some light on the problem I am encountering below. I am trying to generate a pulse train of 108 cycles of a 50% duty cycle square wave at exactly 8192 Hz (tone burst) then space this burst from the next by a dead time of 31.25 mS and repeat the cycle once again, in other words we have a 8192Hz burst at a rate of 32 Hz. Simple enough?
My approach to doing this with a PIC16F628 was to use the Capture/Compare module. Now, because this device is going into an existing design and I cannot change the port pinout asignment, I am stuck using the current IO pins, otherwise I would have chosen to use the PWM output module and that would have been much easier to implement.
The way I have I have decided to implement this function; is to use the compare function, load CCP_1 with a count value (128) that would generate one half cycle of the 8192Hz then toggle the port pins on the next half cycle and do this for the number of required cycles. Although this approach seems to work quite well, I seem to have a problem sitting inside the " while( pulse < n ) " for a lot longer that Ishould, 108 cycles of 8192Hz should only take 13.18 mS and although my burst width is exactly that, I seem to hang around inside this loop for approximately another 30 mS doing nothing. The first thing that comes to mind is that when I enterd this while loop, is that I may be between interrupts. But the interrupts should already be occurring every 61uS as I have already loaded CCP_1 with an increment of 128.....should be interrupting every timer1 count + 128???
So I have no idea where this 30mS dead time is coming from............Any sugestions or ideas would be greatly appreciated!
I have included just a few sections of the code, as It contains many more irrelevant functions, for clarity I have listed most of the items that depict what I am trying to do. I am also shutting off INT_CCP1 as I get into the void hf_op() function; I then turn it on just prior to generating the burst, the reason I do this is to not have continuos interrups while trying to generate accurate timing delays. The one very interesting thing that does come to mind, is that Timer1 is a 16 bit timer and if I take my period of the sytem clock X 65535 = 31.25 mS If that is what is happening, then I do not understand why my incremental value to Timer1 is not preventing this from happening.
108 cycles of 8192 Hz
----||||||||||||||||------------||||||||||||||||--------------
gap = 31.25 mS
***********************************************************
#include<16F628.h>
//#include<16F648A.h>
#use delay(clock=8388608)
#fuses HS,NOPROTECT,WDT,PUT,NOLVP
#define LFPTIME 256 // number of half cycles at 4096 Hz
#define HFPTIME 128 //512 // number of half cycles at 8192 Hz
#use fast_io(A)
#byte port_a=5
#byte port_b= 0x6
#bit LED = 0x6.0
#bit A0 = 0x5.0
#bit A1 = 0x5.1
#bit A2 = 0x5.2
#bit A3 = 0x5.3
// using cycles for delay, each cycle is 476.837 nS with 8.388608 MHz clock
// the same applies to the actual clock cycle for all the calculations
// below.
// Variable Definitions
unsigned int8 i,n;
unsigned int16 count, fsel,pulse, cycles;
unsigned int16 MarkClocks, MarkPulses, SpaceClocks, SpacePulses;
unsigned int16 FillCycles, DummyFill;
int1 op_mode, f,loop_flag,outa =0,outb=1, intflag =0, OutEn =0;
int1 flag_8k;
#int_CCP1
CCP1_isr()
{ CCP_1 = CCP_1 + fsel;
outa ^=1;
outb ^=1;
A0 = outa && OutEn; A1 = outb && OutEn;
pulse ++; }
void init()
{
set_tris_a(0x0); // Set port A I/O pins to all outputs
set_tris_b(0xfe); // Set port B to B0=output, B1-B7= inputport_b_pullups(TRUE);
setup_timer_0(RTCC_INTERNAL);
setup_wdt( WDT_2304MS); // Watchdog timer expires in 2.3 seconds
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_COMPARE_INT);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
port_a = 0; // Set port A low
}
void burst()
{
// Burst generation loop
if (loop_flag) // Check for loop status
{ LED =1; // Loop closed
n = n * 2; // number of interrupt pulses for a cycle of burst freq or # of cycles per burst
port_a = 0; OutEn = 1; // Make sure both RA0 and RA1 are zero
pulse = 0; //
while( pulse < n ) // Do nothing but toggle RA0 and RA1 for the determined amount of cycles
{ ;}
OutEn = 0;
port_a = 0; // Once again make sure both RA0 and RA1 return to zero
}
void hf_op()
{
n = 108; // number of pulse groups
enable_interrupts(INT_CCP1);
do
{ // Do all of these forever
disable_interrupts(INT_CCP1);//setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
restart_wdt(); // service watchdog timer
port_a = 0; // make sure all lines are low
delay_us(1750); // delay testing loop by 1.8mS
if (input(BREAK_INPUT))
loop_flag = TRUE;
else
loop_flag = FALSE;
if (input(L_PPS) & input(H_PPS)) // Rate delay for 32 PPS OK
{ if (!input(CORRECT))
{ delay_us(9200);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); fsel = HFPTIME; burst(); }
else
{ delay_us(31000);
enable_interrupts(INT_CCP1);//setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
fsel = HFPTIME;
burst(); } }
} while(op_mode); }
void main()
{
init();
op_mode = input(MODE); // Read operational mode (RB2)
if(input(F_MODE)) // Read F-Mode jumper (RB3)
{ f = 1; hf_op();} // Sets operation frequency to 8192 Hz.
else
{ f = 0; lf_op();} // Sets operation frequency to 4096 Hz.
} |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sat Aug 07, 2004 1:46 pm |
|
|
Briefly looking at your code, before you burst, you should set timer1 = 0 and set ccp1 = fsel otherwise your first ccp1 int could be as much as 1 timer1 overflow. |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sat Aug 07, 2004 4:43 pm |
|
|
Thank you Mark, I have actually tried to set timer1 to 0 and load the value for CCP_1 just prior to entering the while loop.. It had no effect, I still get the misterious 31 mS or a full 16bit count out of timer1 before it starts doing the burst. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Aug 08, 2004 5:10 am |
|
|
The first line in you do loop is disabling the CCP1 interrupt. Therefore this int is not occuring as you state. You have a 1.75ms delay and a 31ms delay in that loop. Timer1 overflows every 31.25ms. Lets say your system has run through a few cycles. I am going to simply things a bit but here it goes.
We just generated the last pulse. Lets say timer1 = 0 just for grins. That would mean that CCP1 = 128. Your int and int handler take about 96 instructions so timer1 = 96
timer1=96
CCP1 = 128
You disable CCP1 int therefore CCP1 doesn't change
Now you delay 1750us. Dividing that by timer1's rate of change gives a timer1 value of 96 + 3670 = 3766.
timer1=3766
CCP1=128
Now you delay 31ms. Dividing that by timer1's rate of change gives a timer1 value of 65011 + 3766 = 68777 = 3241.
timer1=3241
CCP1=128
Now you enable interrupts which is going to generate and int since the timer has already overflowed and the CCP1 value has been matched.
timer1=3241
CCP1=256
Now you will not get another int until timer1 = 256 which will be 62551 instructions later or about 29.8ms which clearly show me your problem! So I say again (trust me ) it is do to not setting timer1 and the CCP1 value. You could also use one of the features of the CCP which resets the timer1 value on match. This would also fix your problem. You would only need to set the CCP1 value once though. Here is the code with a few extra defines so that I could run it:
Code: |
#include<16F628.h>
//#include<16F648A.h>
#use delay(clock=8388608)
#fuses HS,NOPROTECT,WDT,PUT,NOLVP
#define LFPTIME 256 // number of half cycles at 4096 Hz
#define HFPTIME 128 //512 // number of half cycles at 8192 Hz
#use fast_io(A)
#byte port_a=5
#byte port_b= 0x6
#bit LED = 0x6.0
#bit A0 = 0x5.0
#bit A1 = 0x5.1
#bit A2 = 0x5.2
#bit A3 = 0x5.3
#define BREAK_INPUT PIN_B1
#define F_MODE PIN_B1
#define MODE PIN_B1
#define L_PPS PIN_B1
#define H_PPS PIN_B1
#define CORRECT PIN_B1
// using cycles for delay, each cycle is 476.837 nS with 8.388608 MHz clock
// the same applies to the actual clock cycle for all the calculations
// below.
// Variable Definitions
unsigned int8 i,n;
unsigned int16 count, fsel,pulse, cycles;
unsigned int16 MarkClocks, MarkPulses, SpaceClocks, SpacePulses;
unsigned int16 FillCycles, DummyFill;
int1 op_mode, f,loop_flag,outa =0,outb=1, intflag =0, OutEn =0;
int1 flag_8k;
#int_CCP1
void CCP1_isr()
{
CCP_1 = CCP_1 + fsel;
outa ^=1;
outb ^=1;
A0 = outa && OutEn;
A1 = outb && OutEn;
pulse ++;
}
void init()
{
set_tris_a(0x0); // Set port A I/O pins to all outputs
set_tris_b(0xfe); // Set port B to B0=output, B1-B7= inputport_b_pullups(TRUE);
setup_timer_0(RTCC_INTERNAL);
setup_wdt( WDT_2304MS); // Watchdog timer expires in 2.3 seconds
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_COMPARE_INT);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
port_a = 0; // Set port A low
}
void burst()
{
// Burst generation loop
if (loop_flag) // Check for loop status
{
LED =1; // Loop closed
n = n * 2; // number of interrupt pulses for a cycle of burst freq or # of cycles per burst
port_a = 0;
OutEn = 1; // Make sure both RA0 and RA1 are zero
pulse = 0; //
set_timer1(0);
CCP_1 = fsel;
while( pulse < n ); // Do nothing but toggle RA0 and RA1 for the determined amount of cycles
OutEn = 0;
port_a = 0; // Once again make sure both RA0 and RA1 return to zero
}
}
void hf_op()
{
n = 108; // number of pulse groups
enable_interrupts(INT_CCP1);
do
{ // Do all of these forever
disable_interrupts(INT_CCP1);
//setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
restart_wdt(); // service watchdog timer
port_a = 0; // make sure all lines are low
delay_us(1750); // delay testing loop by 1.8mS
if (input(BREAK_INPUT))
loop_flag = TRUE;
else
loop_flag = FALSE;
if (input(L_PPS) & input(H_PPS)) // Rate delay for 32 PPS OK
{
if (!input(CORRECT))
{
delay_us(9200);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
fsel = HFPTIME;
burst();
}
else
{
delay_us(31000);
enable_interrupts(INT_CCP1);
//setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
fsel = HFPTIME;
burst();
}
}
} while(op_mode);
}
void lf_op(void)
{
}
void main()
{
init();
op_mode = input(MODE); // Read operational mode (RB2)
if(input(F_MODE)) // Read F-Mode jumper (RB3)
{
f = 1;
hf_op();
} // Sets operation frequency to 8192 Hz.
else
{
f = 0;
lf_op();
} // Sets operation frequency to 4096 Hz.
}
|
and using the special feature:
Code: |
#include<16F628.h>
//#include<16F648A.h>
#use delay(clock=8388608)
#fuses HS,NOPROTECT,WDT,PUT,NOLVP
#define LFPTIME 256 // number of half cycles at 4096 Hz
#define HFPTIME 128 //512 // number of half cycles at 8192 Hz
#use fast_io(A)
#byte port_a=5
#byte port_b= 0x6
#bit LED = 0x6.0
#bit A0 = 0x5.0
#bit A1 = 0x5.1
#bit A2 = 0x5.2
#bit A3 = 0x5.3
#define BREAK_INPUT PIN_B1
#define F_MODE PIN_B1
#define MODE PIN_B1
#define L_PPS PIN_B1
#define H_PPS PIN_B1
#define CORRECT PIN_B1
// using cycles for delay, each cycle is 476.837 nS with 8.388608 MHz clock
// the same applies to the actual clock cycle for all the calculations
// below.
// Variable Definitions
unsigned int8 i,n;
unsigned int16 count, fsel,pulse, cycles;
unsigned int16 MarkClocks, MarkPulses, SpaceClocks, SpacePulses;
unsigned int16 FillCycles, DummyFill;
int1 op_mode, f,loop_flag,outa =0,outb=1, intflag =0, OutEn =0;
int1 flag_8k;
#int_CCP1
void CCP1_isr()
{
if ( OutEn )
{
A0 ^= 1;
A1 ^= 1;
}
pulse ++;
}
void init()
{
set_tris_a(0x0); // Set port A I/O pins to all outputs
set_tris_b(0xfe); // Set port B to B0=output, B1-B7= inputport_b_pullups(TRUE);
setup_timer_0(RTCC_INTERNAL);
setup_wdt( WDT_2304MS); // Watchdog timer expires in 2.3 seconds
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_COMPARE_RESET_TIMER);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
port_a = 0; // Set port A low
}
void burst()
{
// Burst generation loop
if (loop_flag) // Check for loop status
{
LED =1; // Loop closed
n = n * 2; // number of interrupt pulses for a cycle of burst freq or # of cycles per burst
port_a = 0;
OutEn = 1; // Make sure both RA0 and RA1 are zero
pulse = 0; //
set_timer1(0);
CCP_1 = fsel;
while( pulse < n ); // Do nothing but toggle RA0 and RA1 for the determined amount of cycles
OutEn = 0;
port_a = 0; // Once again make sure both RA0 and RA1 return to zero
}
}
void hf_op()
{
n = 108; // number of pulse groups
enable_interrupts(INT_CCP1);
do
{ // Do all of these forever
disable_interrupts(INT_CCP1);
//setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
restart_wdt(); // service watchdog timer
port_a = 0; // make sure all lines are low
delay_us(1750); // delay testing loop by 1.8mS
if (input(BREAK_INPUT))
loop_flag = TRUE;
else
loop_flag = FALSE;
if (input(L_PPS) & input(H_PPS)) // Rate delay for 32 PPS OK
{
if (!input(CORRECT))
{
delay_us(9200);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
CCP_1 = HFPTIME;
burst();
}
else
{
delay_us(31000);
enable_interrupts(INT_CCP1);
//setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
CCP_1 = HFPTIME;
burst();
}
}
} while(op_mode);
}
void lf_op(void)
{
}
void main()
{
init();
op_mode = input(MODE); // Read operational mode (RB2)
if(input(F_MODE)) // Read F-Mode jumper (RB3)
{
f = 1;
hf_op();
} // Sets operation frequency to 8192 Hz.
else
{
f = 0;
lf_op();
} // Sets operation frequency to 4096 Hz.
}
|
|
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sun Aug 08, 2004 6:26 am |
|
|
Mark, Thank you for your help!
Although I have not been able to test your changes in the actual hardware, I believe that what you are saying is correct. The dead time I was seeing inside the while loop was very close to your calculation. Furthermore, I had missunderstood the mechanism for the way the compare mode actually works, I thought that the CCP1 registers assumed the current value of the timer1 (this would be the capture mode, NOT compare) Basically my understanding was flawed. This is what usually happens when you don't carefully read the data sheets. |
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Sun Aug 08, 2004 6:27 am |
|
|
Mark, Thank you for your help!
Although I have not been able to test your changes in the actual hardware, I believe that what you are saying is correct. The dead time I was seeing inside the while loop was very close to your calculation. Furthermore, I had missunderstood the mechanism for the way the compare mode actually works, I thought that the CCP1 registers assumed the current value of the timer1 (this would be the capture mode, NOT compare) Basically my understanding was flawed. This is what usually happens when you don't carefully read the data sheets. |
|
|
|
|
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
|