|
|
View previous topic :: View next topic |
Author |
Message |
Rollo Guest
|
How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Sun Mar 16, 2003 7:10 am |
|
|
People on this board seem to know much about RTCC ( Timer0 ).
I was just wondering how to flash an LED using RTCC (Timer0)?
I've read the various messages on this board, and tried out some of the code found here. I only get partial success...
The LED either turns on and stays on, or, if I am flashing two LEDs, one from main and one from the interrupt function, I only see the interrupt LED flash once and then the main one flashes.
I tried modifying the codes in the Examples directory, but so far, I still only get partial success.
Finally, I typed in the code from the CCD manual, page 159, with some minor modifications -- the LED goes on and stays on, and it doesn't flash.
What's wrong with the code below?
My modifications are:
1- Include is for 16F84A instead of 16cxx.h
2- I added my usual fuses
3- I changed HIGH_START to 153 from 114 due to 20Mhz PIC
4- I changed B0 for B3 where my LED is
5- I increased delay from 5 us to 100ms, since the system is supposed to flash only once per second ( according to the book ) I figured 100ms would be safe to have the LED on, and is long enough for me to see it.
6- I had to change...
ennable interrupts( RTCC_ZERO );
... because there's no RTCC_ZERO variable in 16F84A.h I used INT_RTCC, but am unsure if that's right.
Here's the code:
#include <16F84A.h>
#fuses HS,NOWDT
#use delay(clock=20000000)
#define HIGH_START 153 // (20000000/(4*256*256))
byte seconds, high_count;
#int_rtcc
clock_isr() {
if(--high_count== 0) {
output_high( PIN_B3 );
delay_ms(200);
output_low( PIN_B3);
high_count = HIGH_START;
}
}
main() {
high_count=HIGH_START;
set_rtcc(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_128 );
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
while (TRUE);
}
Thanks,
Rol
___________________________
This message was ported from CCS's old forum
Original Post ID: 12734 |
|
|
Rollo Guest
|
16F84A - interrupt RTCC in one secs. |
Posted: Sun Mar 16, 2003 10:49 am |
|
|
For other beginners...
Played around with an example in the Examples directory, EX_STWT.c, and made modifications - added a 7-seg-LED for output. The interrupt seems to work perfectly well.
It has the main method outputting to a seven segment led, while the interrupt method counts up to second to 255. Using a stopwatch, it seems to be very close after 1 minute, if not dead on.
Here's the code:
#include <16F84A.h>
#fuses HS,NOWDT
#use delay(clock=20000000)
#define INTS_PER_SECOND 76 // (20000000/(4*256*256))
byte seconds;
byte int_count;
#int_rtcc
clock_isr() {
if(--int_count==0) {
++seconds;
int_count=INTS_PER_SECOND;
}
}
byte CONST segs[12] = { 0b10000001, 0b10110111, 0b11000100, 0b10010100, 0b10110010, 0b10011000,0b10001000, 0b10110101, 0b10000000, 0b10010000, 0b01111111, 0b11111111 };
void poz(){
delay_ms(125);
}
char numstring[5]="";
main() {
byte count=0;
int16 number = 0;
int_count=INTS_PER_SECOND;
set_timer0(0);
setup_counters( RTCC_INTERNAL, RTCC_DIV_256);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
do {
sprintf( numstring, "\%03u", seconds );
for( count=0;count<=2; count++)
{
output_B(segs[(numstring[count]) - '0']);
poz();
output_B(segs[11]);
poz();
}
output_b(segs[10]);
poz();
poz();
} while (TRUE);
}
I hope this helps someone...
Rol
___________________________
This message was ported from CCS's old forum
Original Post ID: 12740 |
|
|
R.J.Hamlett Guest
|
Re: How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Sun Mar 16, 2003 11:35 am |
|
|
:=People on this board seem to know much about RTCC ( Timer0 ).
:=
:=I was just wondering how to flash an LED using RTCC (Timer0)?
:=
:=I've read the various messages on this board, and tried out some of the code found here. I only get partial success...
:=
:=The LED either turns on and stays on, or, if I am flashing two LEDs, one from main and one from the interrupt function, I only see the interrupt LED flash once and then the main one flashes.
:=
:=I tried modifying the codes in the Examples directory, but so far, I still only get partial success.
:=
:=Finally, I typed in the code from the CCD manual, page 159, with some minor modifications -- the LED goes on and stays on, and it doesn't flash.
:=
:=What's wrong with the code below?
:=
:=My modifications are:
:=1- Include is for 16F84A instead of 16cxx.h
:=2- I added my usual fuses
:=3- I changed HIGH_START to 153 from 114 due to 20Mhz PIC
:=4- I changed B0 for B3 where my LED is
:=5- I increased delay from 5 us to 100ms, since the system is supposed to flash only once per second ( according to the book ) I figured 100ms would be safe to have the LED on, and is long enough for me to see it.
:=6- I had to change...
:=ennable interrupts( RTCC_ZERO );
:=... because there's no RTCC_ZERO variable in 16F84A.h I used INT_RTCC, but am unsure if that's right.
:=
:=Here's the code:
:=
:=#include <16F84A.h>
:=#fuses HS,NOWDT
:=#use delay(clock=20000000)
:=#define HIGH_START 153 // (20000000/(4*256*256))
:=
:=byte seconds, high_count;
:=
:=#int_rtcc
:=clock_isr() {
:=
:= if(--high_count== 0) {
:= output_high( PIN_B3 );
:= delay_ms(200);
:= output_low( PIN_B3);
:= high_count = HIGH_START;
:=
:= }
:=}
Try this instead.
#int_rtcc
clock_isr() {
if (high_count==0) {
output_low(PIN_B3);
high_count==HIGH_START;
}
else if(--high_count== 0) {
LEDflag=TRUE;
output_high( PIN_B3 );
}
}
or
#int_rtcc
clock_isr() {
static int LEDtoggle;
if (--high_count==0) {
if (LED_toggle^=1) output_low(PIN_B3);
else output_high(PIN_B3);
high_count==HIGH_START;
}
}
Though it shouldn't really cause you code not to work, use of long delays in the interrupt handler can cause major problems. The first version, turns on the LED, when the count gets to zero, and leaves it turned on, till the next interrupt, then resets, and restarts the counter (you would need to set HIGH_START to 152 for a reasonably accurate result).
The second version, toggles the LED when the counter gets to zero.
:=main() {
:=
:= high_count=HIGH_START;
:= set_rtcc(0);
:= setup_counters( RTCC_INTERNAL, RTCC_DIV_128 );
:= enable_interrupts(INT_RTCC);
:= enable_interrupts(GLOBAL);
:=
:= while (TRUE);
:=
:=}
Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12744 |
|
|
Rollo Guest
|
Re: How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Sun Mar 16, 2003 12:03 pm |
|
|
Thanks very much for that advice. Works great!
You say weird things can happen if you place too long a delay in the interrupt handler. What kind of weird things?
Much appreciated,
Rol
You Wrote:
:=Try this instead.
:=
:=#int_rtcc
:=clock_isr() {
:= if (high_count==0) {
:= output_low(PIN_B3);
:= high_count==HIGH_START;
:= }
:= else if(--high_count== 0) {
:= LEDflag=TRUE;
:= output_high( PIN_B3 );
:= }
:=}
:=
:=or
:=
:=#int_rtcc
:=clock_isr() {
:= static int LEDtoggle;
:= if (--high_count==0) {
:= if (LED_toggle^=1) output_low(PIN_B3);
:= else output_high(PIN_B3);
:= high_count==HIGH_START;
:= }
:=}
:=
:=Though it shouldn't really cause you code not to work, use of long delays in the interrupt handler can cause major problems. The first version, turns on the LED, when the count gets to zero, and leaves it turned on, till the next interrupt, then resets, and restarts the counter (you would need to set HIGH_START to 152 for a reasonably accurate result).
:=The second version, toggles the LED when the counter gets to zero.
:=
:=:=main() {
:=:=
:=:= high_count=HIGH_START;
:=:= set_rtcc(0);
:=:= setup_counters( RTCC_INTERNAL, RTCC_DIV_128 );
:=:= enable_interrupts(INT_RTCC);
:=:= enable_interrupts(GLOBAL);
:=:=
:=:= while (TRUE);
:=:=
:=:=}
:=
:=Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12746 |
|
|
hillcraft Guest
|
Re: How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Mon Mar 17, 2003 5:19 am |
|
|
If the delay is longer than the period of the interrupt, then the interrupt will interrupt itself. So the delay code will leave off and the device jump back into the ISR.
:=Thanks very much for that advice. Works great!
:=
:=You say weird things can happen if you place too long a delay in the interrupt handler. What kind of weird things?
:=
:=Much appreciated,
:=Rol
:=
:=
:=You Wrote:
:=:=Try this instead.
:=:=
:=:=#int_rtcc
:=:=clock_isr() {
:=:= if (high_count==0) {
:=:= output_low(PIN_B3);
:=:= high_count==HIGH_START;
:=:= }
:=:= else if(--high_count== 0) {
:=:= LEDflag=TRUE;
:=:= output_high( PIN_B3 );
:=:= }
:=:=}
:=:=
:=:=or
:=:=
:=:=#int_rtcc
:=:=clock_isr() {
:=:= static int LEDtoggle;
:=:= if (--high_count==0) {
:=:= if (LED_toggle^=1) output_low(PIN_B3);
:=:= else output_high(PIN_B3);
:=:= high_count==HIGH_START;
:=:= }
:=:=}
:=:=
:=:=Though it shouldn't really cause you code not to work, use of long delays in the interrupt handler can cause major problems. The first version, turns on the LED, when the count gets to zero, and leaves it turned on, till the next interrupt, then resets, and restarts the counter (you would need to set HIGH_START to 152 for a reasonably accurate result).
:=:=The second version, toggles the LED when the counter gets to zero.
:=:=
:=:=:=main() {
:=:=:=
:=:=:= high_count=HIGH_START;
:=:=:= set_rtcc(0);
:=:=:= setup_counters( RTCC_INTERNAL, RTCC_DIV_128 );
:=:=:= enable_interrupts(INT_RTCC);
:=:=:= enable_interrupts(GLOBAL);
:=:=:=
:=:=:= while (TRUE);
:=:=:=
:=:=:=}
:=:=
:=:=Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12762 |
|
|
R.J.Hamlett Guest
|
Re: How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Mon Mar 17, 2003 11:36 am |
|
|
:=If the delay is longer than the period of the interrupt, then the interrupt will interrupt itself. So the delay code will leave off and the device jump back into the ISR.
:=
Not really.
If you are inside an ISR, the interrupts are all disabled (unless you have a chip with hardware priority interrupts). What will happen, depends on the way the interrupt handler is written, and the interrupt concerned.
You could reset the individual interrupt flag on entry, in which case the flag will get set, and you will get an immediate interrupt on the routine exit.
Alternatively you can reset the flag on exit (which is the way the CCS code works), and then any 'events' that may have happened in between will have been missed. Normally this is not a problem, but (for instance), the UART, can become locked up, in this case, since the hardware buffer has a limited depth, and this will set a 'comm overrun' errorm which if not cleared then effectively disables the receive...
On the RTCC, it shouldn't cause a problem, but in general it is a dangerous way to code, unless you know exactly how the interrupt enable is coded.
There are actually two interrupt flags involved (the GIE, and the seperate enable for the timer interrupt). The GIE, should disable everything, and is only reset by the RETFIE at the end of the global interrupt handler. It is the other individual flag that changes how the events would behave.
So unless the code internally accidentally results in another RETFIE, there should not be a problem, except for events being missed, with the potential for hardware overruns...
The behaviour is odd really.
Best Wishes
:=:=Thanks very much for that advice. Works great!
:=:=
:=:=You say weird things can happen if you place too long a delay in the interrupt handler. What kind of weird things?
:=:=
:=:=Much appreciated,
:=:=Rol
:=:=
:=:=
:=:=You Wrote:
:=:=:=Try this instead.
:=:=:=
:=:=:=#int_rtcc
:=:=:=clock_isr() {
:=:=:= if (high_count==0) {
:=:=:= output_low(PIN_B3);
:=:=:= high_count==HIGH_START;
:=:=:= }
:=:=:= else if(--high_count== 0) {
:=:=:= LEDflag=TRUE;
:=:=:= output_high( PIN_B3 );
:=:=:= }
:=:=:=}
:=:=:=
:=:=:=or
:=:=:=
:=:=:=#int_rtcc
:=:=:=clock_isr() {
:=:=:= static int LEDtoggle;
:=:=:= if (--high_count==0) {
:=:=:= if (LED_toggle^=1) output_low(PIN_B3);
:=:=:= else output_high(PIN_B3);
:=:=:= high_count==HIGH_START;
:=:=:= }
:=:=:=}
:=:=:=
:=:=:=Though it shouldn't really cause you code not to work, use of long delays in the interrupt handler can cause major problems. The first version, turns on the LED, when the count gets to zero, and leaves it turned on, till the next interrupt, then resets, and restarts the counter (you would need to set HIGH_START to 152 for a reasonably accurate result).
:=:=:=The second version, toggles the LED when the counter gets to zero.
:=:=:=
:=:=:=:=main() {
:=:=:=:=
:=:=:=:= high_count=HIGH_START;
:=:=:=:= set_rtcc(0);
:=:=:=:= setup_counters( RTCC_INTERNAL, RTCC_DIV_128 );
:=:=:=:= enable_interrupts(INT_RTCC);
:=:=:=:= enable_interrupts(GLOBAL);
:=:=:=:=
:=:=:=:= while (TRUE);
:=:=:=:=
:=:=:=:=}
:=:=:=
:=:=:=Best Wishes
___________________________
This message was ported from CCS's old forum
Original Post ID: 12770 |
|
|
Rollo Guest
|
Re: How to use TMR0 ( RTCC ) on 16F84A to flash LED? |
Posted: Mon Mar 17, 2003 6:17 pm |
|
|
Thanks to all those who replied. I've been able to get a couple of applications going with interrupts now, and I'm pleased with the results. Also, I can see that I've got lots of reading up to do to understand what's going on under the hood. All the advice is appreciated...
Thanks,
Rol
___________________________
This message was ported from CCS's old forum
Original Post ID: 12779 |
|
|
|
|
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
|