|
|
View previous topic :: View next topic |
Author |
Message |
Forest Guest
|
help with timer1 |
Posted: Wed May 14, 2003 3:35 pm |
|
|
Howdy Picsters
I know this is a well worn subject, I'm probably missing the point but I can't get my 16F877 to count in seconds.
Ive checked out the forum, everyone says you can do it but my timer 1 with a 32kHz watch crystal across RC0 & RC1 doesn't work.
My crystal is not resonating, this could be the problem but I thought this may be something to do with the output of the PIC not being set right.
Am confused on whether to use T1_EXTERNAL, T1_EXTERNAL_SYNC and what exactly does T1_CLK_OUT do??
I calculate that the number of interupts per second should be 0.5 (32768/65536) - is this correct? how would u put this in code as it is not an integer.
My code is attached - any advice would be fantastic.
Forest
#include <16f877.h>
#fuses hs,nowdt,noprotect,put,nowrt,nolvp
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define INTS_PER_SECOND 1 // (32768/65536) not sure about this line
byte seconds=0;
byte int_count;
#int_timer1 // This function is called every time
clock_isr() { // (timer1) overflows (255->0).
// For this program this is apx 0.5 times
if(--int_count==0) { // per second???.
++seconds;
printf("\n\rSeconds: \%d", seconds);
int_count=INTS_PER_SECOND;
}
}
main() {
int_count=INTS_PER_SECOND;
set_timer1(0
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514466 |
|
|
Tomi Guest
|
Re: help with timer1 |
Posted: Thu May 15, 2003 1:06 am |
|
|
A setup example:
setup_timer_1(T1_DIV_BY_1 | T1_EXTERNAL | 0x08);
// the last 0x08 enables the internal oscillator; unfortunately CCS C has a constant T1_DISABLED but doesn't have T1_ENABLED and the default state is to disable the oscillator :)
The 0.5 rate means that you will get Timer1 IT in every 2 seconds. If it is affordable for you then you can simply use:
seconds += 2;
instead of
++seconds;
If you want to get ITs in every 1 second then you can use:
Set_Timer1(32768);
as the first instruction of the IT handler (and additionally you have to check that the IT latency is less than 1/32768 = 30usec)
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514476 |
|
|
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
Re: help with timer1 |
Posted: Thu May 15, 2003 1:23 am |
|
|
:=Howdy Picsters
:=
:=I know this is a well worn subject, I'm probably missing the point but I can't get my 16F877 to count in seconds.
:=Ive checked out the forum, everyone says you can do it but my timer 1 with a 32kHz watch crystal across RC0 & RC1 doesn't work.
:=
:=My crystal is not resonating, this could be the problem but I thought this may be something to do with the output of the PIC not being set right.
:=
:=Am confused on whether to use T1_EXTERNAL, T1_EXTERNAL_SYNC and what exactly does T1_CLK_OUT do??
:=I calculate that the number of interupts per second should be 0.5 (32768/65536) - is this correct? how would u put this in code as it is not an integer.
:=
:=My code is attached - any advice would be fantastic.
:=
:=Forest
First, you didn't say why you are using an external oscillator instead of counting the internal fosc/4, ie 4000000/4 = 1MHz together with the prescaler.
There are several points if you really want to use the external oscillator. Interrupts will only occur every two seconds at best unless you preload the counter with half the maximum count every time an interrupt occurs ie 0x7fff.
Read the timer1 module section of the pdf for the PIC16F87X.
1. Two capacitors of 33pF are needed with the 32.768kHz crystal.
2. The oscillator needs to be enabled with bit T1OSCEN (T1CON.3)
3. The counter needs to be enabled with bit TMR1ON (T1CON.0)
Define these bits as necessary,
#bit timer1_osc_en = 0x10.3
#bit timer1_on = 0x10.0
4. External needs to be selected as the clock source and the prescaler set.
eg.
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
Setup timer 1 overflow interrupts:
enable_interrupts(INT_TIMER1);
enable_interrupts(global);
5. Don't use printf within the interrupt service routine, far too much code to process. Instead, set a flag for main().
short one_sec_fl;
#int_timer1
timer1_isr() {
++seconds;
one_sec_fl = 1;
set_timer1(0x7fff); // Preload half
}
timer1_osc_en = 1;
timer1_on = 1;
main() {
while(1) {
if (one_sec_fl) {
one_sec_fl = 0;
printf("\n\rSeconds: \%d", seconds);
}
}
}
Don't need to worry about T1_EXTERNAL_SYNC unless you need to synchronise the external oscillator with the internal phase clocks. Not sure what T1_CLK_OUT does.
Regards
Kenny
:=#include <16f877.h>
:=#fuses hs,nowdt,noprotect,put,nowrt,nolvp
:=#use delay(clock=4000000)
:=#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
:=
:=#define INTS_PER_SECOND 1 // (32768/65536) not sure about this line
:=
:=byte seconds=0;
:=byte int_count;
:=
:=
:=#int_timer1 // This function is called every time
:=clock_isr() { // (timer1) overflows (255->0).
:= // For this program this is apx 0.5 times
:= if(--int_count==0) { // per second???.
:= ++seconds;
:= printf("\n\rSeconds: \%d", seconds);
:=
:= int_count=INTS_PER_SECOND;
:= }
:=
:=}
:=
:=
:=main() {
:=
:= int_count=INTS_PER_SECOND;
:= set_timer1(0
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514478 |
|
|
Forest Guest
|
Re: help with timer1 |
Posted: Thu May 15, 2003 3:16 am |
|
|
Hi Kenny/Tomy
Thanks for your replies.
I wanted to use an external oscillator in order to achieve a reasonably accurate real time clock relying on the 32kHz crystal - it is supposed to give an exact (supposed!!) non-prescaled interupt interval. I can't see any reason why I can't - I suppose i could implement the internal osc/4 with prescaler - I just thought this would be easier.
The 16F877 data sheet does suggest 33pF but other text has suggested other values (as per manufacturer) - I'm using 12.5pF
I didn't realise you would have to set the register direct - I assumed that the set commands would cover this.
Pre-loading the counter makes sense - TA
The mystery of T1_CLK_OUT continues - I've seen it used in the EX_STWT.C but it relates to RTCC???
Sorry about the multiple posts before - I kept getting errors and thought I was doing something wrong - apparently the server was full up or something.
:=:=Howdy Picsters
:=:=
:=:=I know this is a well worn subject, I'm probably missing the point but I can't get my 16F877 to count in seconds.
:=:=Ive checked out the forum, everyone says you can do it but my timer 1 with a 32kHz watch crystal across RC0 & RC1 doesn't work.
:=:=
:=:=My crystal is not resonating, this could be the problem but I thought this may be something to do with the output of the PIC not being set right.
:=:=
:=:=Am confused on whether to use T1_EXTERNAL, T1_EXTERNAL_SYNC and what exactly does T1_CLK_OUT do??
:=:=I calculate that the number of interupts per second should be 0.5 (32768/65536) - is this correct? how would u put this in code as it is not an integer.
:=:=
:=:=My code is attached - any advice would be fantastic.
:=:=
:=:=Forest
:=
:=First, you didn't say why you are using an external oscillator instead of counting the internal fosc/4, ie 4000000/4 = 1MHz together with the prescaler.
:=There are several points if you really want to use the external oscillator. Interrupts will only occur every two seconds at best unless you preload the counter with half the maximum count every time an interrupt occurs ie 0x7fff.
:=Read the timer1 module section of the pdf for the PIC16F87X.
:=
:=1. Two capacitors of 33pF are needed with the 32.768kHz crystal.
:=2. The oscillator needs to be enabled with bit T1OSCEN (T1CON.3)
:=3. The counter needs to be enabled with bit TMR1ON (T1CON.0)
:=
:=Define these bits as necessary,
:=#bit timer1_osc_en = 0x10.3
:=#bit timer1_on = 0x10.0
:=
:=4. External needs to be selected as the clock source and the prescaler set.
:=eg.
:=setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
:=
:=Setup timer 1 overflow interrupts:
:=enable_interrupts(INT_TIMER1);
:=enable_interrupts(global);
:=
:=5. Don't use printf within the interrupt service routine, far too much code to process. Instead, set a flag for main().
:=
:=short one_sec_fl;
:=
:=#int_timer1
:=timer1_isr() {
:=++seconds;
:=one_sec_fl = 1;
:=set_timer1(0x7fff); // Preload half
:=
:=}
:=
:=timer1_osc_en = 1;
:=timer1_on = 1;
:=
:=main() {
:=while(1) {
:=if (one_sec_fl) {
:=one_sec_fl = 0;
:=printf("\n\rSeconds: \%d", seconds);
:=}
:=}
:=}
:=
:=Don't need to worry about T1_EXTERNAL_SYNC unless you need to synchronise the external oscillator with the internal phase clocks. Not sure what T1_CLK_OUT does.
:=
:=Regards
:=Kenny
:=
:=
:=
:=
:=
:=:=#include <16f877.h>
:=:=#fuses hs,nowdt,noprotect,put,nowrt,nolvp
:=:=#use delay(clock=4000000)
:=:=#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
:=:=
:=:=#define INTS_PER_SECOND 1 // (32768/65536) not sure about this line
:=:=
:=:=byte seconds=0;
:=:=byte int_count;
:=:=
:=:=
:=:=#int_timer1 // This function is called every time
:=:=clock_isr() { // (timer1) overflows (255->0).
:=:= // For this program this is apx 0.5 times
:=:= if(--int_count==0) { // per second???.
:=:= ++seconds;
:=:= printf("\n\rSeconds: \%d", seconds);
:=:=
:=:= int_count=INTS_PER_SECOND;
:=:= }
:=:=
:=:=}
:=:=
:=:=
:=:=main() {
:=:=
:=:= int_count=INTS_PER_SECOND;
:=:= set_timer1(0
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514484 |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Help with RTC |
Posted: Thu May 15, 2003 8:30 am |
|
|
You should look at this. You don't need a second crystle to get an accurate RTC.
<a href="http://www.pic-c.com/forum/general/posts/6403.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/6403.html</a>
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514493 |
|
|
Forest Guest
|
Re: help with timer1 - it works & figured out T1_CLKOUT |
Posted: Fri May 16, 2003 6:14 pm |
|
|
Thanks for all your help guys.
I also wanted to use an external clock for the wakeup facility. Got my circuit going after your tips and tricks got me thinking. I used the flags idea and also realised what T1_CLKOUT does: If you look at the 16F877 file and see the define for T1_CLKOUT is "8". Checked out the data sheet and realised this sets the T1CON bit3 or T1OSCENanble!!. No need to set the register with 0x08, or the set the 10.3 bit (same thing) - just OR (|) T1_CLKOUT.
I've posted my updated code FYI - thanks again fella's
#include <16f877.h>
#fuses hs,nowdt,noprotect,put,nowrt,nolvp
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#define INTS_PER_SECOND 32768 // Load half the TMR1 with for 1sec int
byte count=0;
byte seconds=0;
byte minutes=0;
byte int_count;
short one_sec_fl;
#int_timer1 // This function is called every time
clock_isr()
{ // (timer1) overflows (255->0).
++count;
one_sec_fl = 1;
set_timer1(0x7fff);
}
main() {
setup_timer_1( T1_DIV_BY_1 | T1_EXTERNAL | T1_CLK_OUT ); //setup timer1
enable_interrupts(INT_TIMER1); //setup interupts
enable_interrupts(GLOBAL);
delay_ms(5);
while(1)
{
if (one_sec_fl)
{
++seconds;
if (seconds==60)
{
++minutes;
seconds=0;
}
one_sec_fl = 0;
printf("\n\r\%d:\%d",minutes,seconds);
}
}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 144514517 |
|
|
|
|
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
|