View previous topic :: View next topic |
Author |
Message |
sjharris
Joined: 11 May 2006 Posts: 78
|
Timer 1 as interrupt |
Posted: Wed Aug 22, 2007 3:05 am |
|
|
Hello all,
I have never used an external peripheral as an interrupt source and I would like to use timer1, with an external 4MHz crystal as an interrupt source.
I would like to create a counter to count the number of interrupts (so that I can make a timer to wake the PIC).
I am using the PIC 16F688.
Can anyone tell me what I need to do to:-
1) Set timer1 as an external clock source
2) Enable timer1 as an interrupt source
3) Service the interrupt (I assume a flag set then return to code).
Any help would be very helpful.
Steve |
|
|
Guest
|
|
Posted: Wed Aug 22, 2007 7:49 am |
|
|
bmp |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: Timer 1 as interrupt |
Posted: Wed Aug 22, 2007 10:54 am |
|
|
sjharris wrote: | Any help would be very helpful.
Steve |
I agree the help is very helpful.
The thing you should do is read the help file for the compiler. Read each entry about timers. Then you will have the answers you seek or at least be able to ask better question. |
|
|
sjharris
Joined: 11 May 2006 Posts: 78
|
|
Posted: Tue Aug 28, 2007 1:17 am |
|
|
Thats the thing with this Forum, has anyone actually given a response that is usable to this problem??
I have read many, many times people ask this question but I have yet to find anyone who has given a solution as to how to set this up. If anyone out there knows why make it so difficult to get to the solution?!?!?!?!?
I have asked a very general question, with only the bare minimal of information, why is it so hard to provide a solution?
HAS NO ONE DONE THIS BEFORE??
I do not belive that no one has made an external interrup source from a crystal!!
There is no code to show in my program as I do not have a program yet. So why is it so difficult to provide a solution??
I thought that by coming on this forum that someone would be abel to help, if someone had done this before maybe. But obviously not!!
Quote: | The thing you should do is read the help file for the compiler. Read each entry about timers. |
I have read the help for the compiler. It has no specific help to set up external interrupt for this PIC.
Quote: | Then you will have the answers you seek or at least be able to ask better question. |
Or I will ask a question YOU can answer.
If you cant provide any help then just say so, or better say nothing at all!! |
|
|
sjharris
Joined: 11 May 2006 Posts: 78
|
|
Posted: Tue Aug 28, 2007 7:13 am |
|
|
Can anyone just give me some code for any pic where they have got an external oscilator working to wake the PIC up from sleep.
I Just cant get it to work.
Thanks
Stephen |
|
|
sjharris
Joined: 11 May 2006 Posts: 78
|
|
Posted: Tue Aug 28, 2007 7:38 am |
|
|
Here is some of the code that I have got so far:-
This is for a 16F688. I think I have referenced the bits correctly.
Code: |
//******************************************************************************
// Global Variables
//******************************************************************************
int8 timer1_upper = 0;
int8 timer1_lower = 0;
int16 timer1_counter = 0;
int16 timer1=0;
int t1_fired = 0;
#BIT PEIE = 11.6
#BIT GIE = 11.7
#BIT TMR1IF = 12.0
#BIT TMR1IE = 140.0
#BIT TMR1CS = 16.1
#BIT TMR1SY = 16.2
//******************************************************************************
// Interrupt Routines
//******************************************************************************
#INT_EXT
void ext_isr()
{ //Routine for waking up with button
//output_high(PIN_C1);
}
#INT_TIMER1
void clock_isr()
{
timer1_counter ++;
puts("Int");
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
PEIE = 1;
TMR1IF = 0;
TMR1IE = 1;
TMR1CS = 1;
TMR1SY = 1;
GIE = 1;
timer1_upper=read_eeprom(0);
timer1_lower=read_eeprom(1);
timer1_counter = (timer1_upper * 256) + timer1_lower;
puts("Start");
output_a(0);
output_c(0);
while(1)
{
sleep();
}
|
The bits to do with the timer upper, lower and counter are for handling 16 bit counter for timer1. I have some more stuff that counts the number of interrrupts and then does some stuff, but when I use timer1 as an external source it doesnt do anything.
Output:-
Start
Why wont this wake from sleep at all?
Thanks |
|
|
SET
Joined: 15 Nov 2005 Posts: 161 Location: Glasgow, UK
|
|
Posted: Tue Aug 28, 2007 8:34 am |
|
|
Code: | puts("Start");
output_a(0);
output_c(0);
while(1)
{
sleep();
// wakes up here, around the loop and back to sleep
// so add this?
// puts("Wakeup!");
} |
I see your printing other messages in Timer ISR, but put the above in as a sanity check that your actualy waking up.
Last edited by SET on Tue Aug 28, 2007 8:36 am; edited 1 time in total |
|
|
kevcon
Joined: 21 Feb 2007 Posts: 142 Location: Michigan, USA
|
|
Posted: Tue Aug 28, 2007 8:34 am |
|
|
I just happen to be working on the same thing at the moment
Here is some code that works on a PIC18, it should work on your chip.
I'm using compiler version 4.038
Code: |
#include "18F65J10.h"
#pragma device ADC = 10
#pragma case
#pragma fuses DEBUG //Enable Dedicated Debugger Pins
#pragma fuses NOWDT //Disable Watchdog Timer
#pragma fuses STVREN //Enable Stack Over/Underflow Reset
#pragma fuses NOXINST //Disable Extended Instructions
#pragma fuses NOPROTECT //Disable Code Protection
#pragma fuses NOIESO //Disable Two Speed Start-up
#pragma fuses FCMEN //Enable Fail Safe Clock Monitor
#pragma fuses PRIMARY //Set Defaul Clock as PRIMARY
#pragma fuses H4_SW //High Speed Crystal and PLL
#pragma fuses WDT32768 //Set WDT Postscaler to MAX
#pragma fuses CCP2C1 //ECCP2/P2A is Multiplexed with RC1
#pragma use delay( clock = 36,864,000, crystal = 9,216,000 )
#pragma byte OSCCON = getenv( "SFR:OSCCON" )
#pragma bit IDLEN = OSCCON.7
#define EXT_OSC_SPEED 1843200
#define LED PIN_E5
//unsigned int32 cycleCount = getenv( "clock" ) / 4;
unsigned int32 cycleCount = EXT_OSC_SPEED;
unsigned int8 seconds = 0;
#pragma INT_TIMER1
void RTC( void )
{
#pragma use fast_io( E )
cycleCount -= 65536; // Decrement cycleCount by "cycles per interrupt"
if ( cycleCount < 65536 ) { // If second has expired
// cycleCount += getenv( "clock" ) / 4; // Increment cycleCount by clocks per second
cycleCount += EXT_OSC_SPEED;
if ( seconds == 0 ) {
seconds = 1;
output_low( LED );
}
else {
seconds = 0;
output_high( LED );
}
}
}
void main( void )
{
#pragma use standard_io( E )
// IDLEN = 1; //Enable IDLE mode
// setup_timer_1( T1_INTERNAL | T1_DIV_BY_1 );
setup_timer_1( T1_EXTERNAL | T1_DIV_BY_1 );
output_high( LED );
enable_interrupts( INT_TIMER1 );
enable_interrupts( GLOBAL );
for( ; ; ) {
sleep( );
}
}
|
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Aug 28, 2007 8:46 am |
|
|
1) Fortunately CCS Compiler has built in functions to setup timers and interrupts which
are by far more readable that the assembler way you used.
2) It is not necessary to add any counter, clocking in the expected PIN (OSC2/T1G)
with a proper signal the internal Timer1 counter will increase. When it overflow, it
will generate and interrupt that would wake up the PIC, at least is what we hope
3) It is not a good practice to use any print out function inside an interrupt handler.
Following code had not been tested.
Code: |
#include <16F688.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES MCLR //Master Clear pin enabled
#FUSES NOCPD //No EE protection
#FUSES PUT //Power Up Timer
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES INTRCIO //This is the only way to keep PIN_A4 free for
//external T1 clocking
#use delay(clock=??????) SEE NOTE
#use rs232(baud=9600,parity=N,xmit=PIN_A3,rcv=PIN_A2,bits=8)
#define LED PIN_xx // Connect a LED + 470 Ohms in the selected PIN
#int_TIMER1
void TIMER1_isr(void)
{
output_low(LED);
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_oscillator(****) // ( 8 Mhz or 31 Khz); // NOTE ******
printf("I´m going to sleep");
output_high(LED);
while(1)
{
sleep();
printf("Believe it or not, I just wake up !!!");
delay_ms(5000);
}
}
|
Humberto
Last edited by Humberto on Tue Aug 28, 2007 10:06 am; edited 1 time in total |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Aug 28, 2007 9:32 am |
|
|
Stephen got angry for not receiving a response over a week time. He posted some code and got 3 responses in one hour...
Still, Stephen hasn't told us what is connected to the timer1 inputs. Is it a crystal or an external oscillator?
The #fuse lines are missing in his code so I can't tell if he is running from the internal oscillator or from an external clock source.
What goal does Stephen want to achieve? Save power or count cycles from an external source or ....?
For example if Stephen wants to achieve the lowest possible power consumption I would connect a 32kHz crystal for waking up from sleep and have the processor run from the internal clock. This requires a slightly different configuration from the given examples. I don't know and without more details I'm not going to waste time posting example code. |
|
|
sjharris
Joined: 11 May 2006 Posts: 78
|
|
Posted: Wed Aug 29, 2007 2:28 am |
|
|
Humberto,
thank you for your reply. I have tested your code and unfortunately it does not wake from sleep.
I need to clear a few things up when it comes to timers etc.
In your code you set up both timer0 and timer1. Are they synched so that timer 1 will increment timer 0?
I have a 1 MHz external crystal, will that work with your code?
Any more pointers would be very appreciated.
Thanks
Stephen |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Wed Aug 29, 2007 5:26 am |
|
|
Quote: |
In your code you set up both timer0 and timer1.
| Is true but it doesn´t mater. Timer0 i armed but never enabled.
Quote: | Are they synched so that timer 1 will increment timer 0?
| NOP.
Quote: |
I have a 1 MHz external crystal, will that work with your code?
| NOP.
Looking in the availables pin-outs of the 16F688, you will see that PIN3 share
5 different functionalities, which are mutually exclusive, that is: if you set that pin
as an analog input, your hardware should treat such pin as an analog input.
PIN3 could have the following functionalities:
Code: |
- RA4 Digital input/output TTL w/compatible levels.
- AN3 Analog Input (A/D channel 3)
- T1G Timer 1 Gate
- OSC2 Crystal/Resonator
- CLKOUT Fosc/4 output
|
If you want to wake up the PIC with Timer1, it is necessary to clock-in in this PIN
from an external source. This is mandatory, hence you loose the hability to clock
the PIC with a crystal as you done.
That is why I selected as main clock source, the internal RC oscillator wich is
very flexible, all you need is to give to the function setup_oscillator(); one of
the following parameters:
Code: |
#define OSC_31KHZ
#define OSC_125KHZ
#define OSC_250KHZ
#define OSC_500KHZ
#define OSC_1MHZ
#define OSC_2MHZ
#define OSC_4MHZ
#define OSC_8MHZ
|
I made some changes (add T1_GATE) in the following code, not tested.
Code: |
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_GATE);
setup_comparator(NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
setup_oscillator(****) // ( see previous )
printf("I´m going to sleep");
output_high(LED);
while(1)
{
sleep();
printf("Believe it or not, I just wake up !!!");
delay_ms(5000);
}
}
|
First goal must be that it will be able to print the first string, if you can, life will smile you.
Humberto |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Aug 29, 2007 5:46 am |
|
|
Quote: | If you want to wake up the PIC with Timer1, it is necessary to clock in in this PIN from an external source. | Timer1 has a low power oscillator circuit so besides an external clock you can connect a crystal rated up to 32 kHz. This requires the processor to run from the internal RC oscillator. Code: | setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1|T1_CLK_OUT); |
|
|
|
kevcon
Joined: 21 Feb 2007 Posts: 142 Location: Michigan, USA
|
|
Posted: Wed Aug 29, 2007 6:32 am |
|
|
I'm using a 1.8432 MHz Oscillator in my setup and it wakes from sleep no problem |
|
|
sjharris
Joined: 11 May 2006 Posts: 78
|
|
Posted: Wed Aug 29, 2007 6:38 am |
|
|
The PIC does output the first string, then goes to sleep.
I have a 1 MHz crystal on pins 2 and 3 of the PIC with 2 caps to ground, do I need anything else or would this crystal suffice??
Thanks
Stephen |
|
|
|