|
|
View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
Very weird RTCC, InT_RDA, and delay_ms problem |
Posted: Mon Feb 23, 2009 4:46 pm |
|
|
I'm wondering if someone else can duplicate this error.
I'm using PCH 4.030, 18F2620.
If I put a delay in the INT_RDA ISR, or a delay in main's while loop, then timing for timer0 is messed up by a factor of about 18 or 20.
Here's the code. I tried to strip out everything that wasn't needed, but it's still sort of long. Basically, I just have the RTCC ISR turning on and off a LED. You're probably saying "don't put a delay in an ISR you dummy!" ... I know, I'm not looking for code guidance, just trying to understand why the delay is affecting the timing, especially when INT_RDA isn't even turned on! What's more interesting is that if *either* delay (in INT_RDA or main) is commented out, then the timing works correctly. Very weird!
Code: |
#include <18f2620.h>
#device ADC=10 // use 10 bit ADC reading
#fuses HS,WDT256,NOMCLR,NOWDT,NOPROTECT,NOBROWNOUT,BORV21,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7, errors)
#int_rda
void serial_isr() {
delay_ms(100); // comment this out, and timing for timer0 works correctly
}
/* !!!!!!!! LED functions, defines, and variables !!!!!!!! */
#define SLOW_FLASH 1 // transition every second
#define NO_FLASH 0
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
#define BLUE_LED_PIN PIN_C4
void blue_LED_on(int1);
void toggle_blue_LED();
void check_LEDs(int);
// Number of interrupts left before a second has elapsed
BYTE int_count1;
// variables to store current state of LED
int1 blue_LED;
int blue_flashrate;
#int_rtcc
void clock_isr() {
if(--int_count1==0) {
check_LEDs(SLOW_FLASH);
int_count1=INTS_PER_SECOND;
}
}
/* !!!!!!!! END LED functions, defines, and variables !!!!!!!! */
void main() {
setup_adc( ADC_CLOCK_INTERNAL );
setup_adc_ports( ALL_ANALOG );
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
/* setup counter parameters */
int_count1=INTS_PER_SECOND;
setup_timer_0( RTCC_INTERNAL | RTCC_8_BIT | RTCC_DIV_256);
set_timer0(0);
/* end setup on counter parameters */
blue_LED = FALSE;
blue_LED_on(FALSE);
blue_flashrate = SLOW_FLASH;
setup_wdt(WDT_ON); // WDT on in software
while(1) {
printf("Hi\r\n");
// delay_ms(500); // comment this out, and timing for timer0 works correctly
restart_wdt();
}
}
/********************* Functions **************************/
void check_LEDs(int rate) {
if(blue_flashrate == rate) {
toggle_blue_LED();
}
}
void blue_LED_on(int1 on) {
if(on) output_low(BLUE_LED_PIN);
else output_high(BLUE_LED_PIN);
}
void toggle_blue_LED() {
blue_LED = !blue_LED;
blue_LED_on(blue_LED);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 23, 2009 5:26 pm |
|
|
If you have both delay_ms() statements in your program, you'll get a
"re-entrancy" warning message. To fix that, you can create another
instance of the delay library code by adding the line shown in bold below
just above main():
Quote: | #use delay(clock=20000000)
void main() { |
Then the interrupt routine will have it's own dedicated delay routine,
and the main code will another it's own routine. Their won't be any
re-entrancy issues and the compiler won't disable interrupts while the
delay_ms() statement in main() is running. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Mon Feb 23, 2009 6:02 pm |
|
|
Also, if the #int_rda is enabled you will have another
problem. Without a getc() in the interrupt routine to clear
the interrupt, the interrupt will not be cleared and it will be
called repeatedly which will cause the program to stay in the
#int_rda delay_ms() almost continously. |
|
|
|
|
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
|