View previous topic :: View next topic |
Author |
Message |
kamillas
Joined: 24 Oct 2011 Posts: 50
|
routine interrupt |
Posted: Fri Nov 11, 2011 3:33 pm |
|
|
I want to configure the TIMER0, so that every one second, it triggers the interrupt routine;
can you help me please. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Nov 11, 2011 3:58 pm |
|
|
You have to do a few simple calculations as it depends on your clock frequency.
How to do this has been explained numerous times before on this forum and the Microchip forum. Use Google or the search function of this forum. If you don't know how to find the answer to this simple question then you have a major problem.
O yes, I also suggest you have a look at the example programs supplied with the CCS compiler. In the CCS manual there is a chapter at the end of the document giving a short description of each program. It is a very good source of information for beginners on the PIC programming and I'm sure the answer to your question is there listed as well. |
|
|
SSR
Joined: 09 Nov 2011 Posts: 14
|
|
Posted: Sat Nov 12, 2011 2:06 pm |
|
|
Some thing like that.
Code: |
#include <18f452.h>
#use delay(clock=20M)
#define a 80
byte b;
#int_RTCC
void isr_timer0(void)
{
if(--b==0)
{
output_toggle(PIN_C0);
b=a;
}
}
void main(void)
{
b=a;
disable_interrupts(GLOBAL); // all interrupts OFF
disable_interrupts(INT_RTCC);
set_rtcc(50006);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
enable_interrupts(INT_timer0);
enable_interrupts(GLOBAL);
while(TRUE);
} |
Calculation:
20M/4=5M/256=19531
1/19531=51.2us
51.2usx256x80=1. 05s |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Sat Nov 12, 2011 9:42 pm |
|
|
20Mhz is the clock frequency....for most PIC's it takes 4 clocks to have an instruction executed. This means the timer module will do something at 5Mhz. The something it does is increment an internal register. When that register fills it rolls over. The register for an 8 bit timer will roll over every 256 instructions. When the register rolls over it triggers the interrupt.
The interrupt is then triggered 5Mhz/256 times per second assuming the scaler is 1...it is 256 so a further delay by a factor of 256 is introduced. Now if every time the interrupt is triggered it also increments a global variable counter or decrements a counter then the counter can be given a value to count to or down from. If this value is 80 then the global variable counter reaches zero every 1.05 secs. It gets a little more complex since timers can have prescalers and post scalers and an initial count to start from. These are additional registers the PIC has to adjust the number of instruction cycles before the interrupt is triggered. The purpose is to provide as much flexibility in setting the frequency the timer interrupts and executes the code in the ISR. While the timer is being incremented. every 4 cycles of the clock you code in main is at the same time having one of its instructions executed. When the timer rolls over the main code is suspended and the interrupt code executed. Remember a line of C code often requires many instructions so the interrupt often will occur in the middle of a line of main code. After the interrupt code is completed the main routine resumes exactly where it left off. |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
7 segment seconds |
Posted: Sun Nov 13, 2011 3:08 am |
|
|
thank you, my program has become like her, but to no avail
Code: | #include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#define a 80
byte b;
int un=0,dec=0;
int CONST tab[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#int_RTCC
void isr_timer0(void)
{
if(--b==0)
{
b=a;
un++;
if (un==10){
un=0 ;
dec==1;}
if ((dec==1)&&(Un>0))
dec++;
}
}
void main(void)
{
b=a;
disable_interrupts(GLOBAL); // all interrupts OFF
disable_interrupts(INT_RTCC);
set_rtcc(50006);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
enable_interrupts(INT_timer0);
enable_interrupts(GLOBAL);
WHILE (1) ;
{
OUTPUT_A(0x01);
OUTPUT_B(tab[un]);
delay_ms(50);
OUTPUT_A(0x02);
OUTPUT_B(tab[dec]);
delay_ms(50);
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
Re: 7 segment seconds |
Posted: Sun Nov 13, 2011 3:54 am |
|
|
kamillas wrote: | thank you, my program has become like her, but to no avail
Code: | #include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#define a 80
byte b;
int un=0,dec=0;
int CONST tab[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
#int_RTCC
void isr_timer0(void)
{
if(--b==0)
{
b=a;
un++;
if (un==10){
un=0 ;
dec==1;}
if ((dec==1)&&(Un>0))
dec++;
}
}
void main(void)
{
b=a;
disable_interrupts(GLOBAL); // all interrupts OFF
disable_interrupts(INT_RTCC);
set_rtcc(50006);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_BIT);
enable_interrupts(INT_timer0);
enable_interrupts(GLOBAL);
WHILE (1) ;
{
OUTPUT_A(0x01);
OUTPUT_B(tab[un]);
delay_ms(50);
OUTPUT_A(0x02);
OUTPUT_B(tab[dec]);
delay_ms(50);
}
}
|
|
First, I repeat my comment from another thread - learn to indent...
Then avoid problems for yourself in the future. Stick to the old 'standard', and when you #define something use capitals, to distinguish it from a variable.
Then study your interrupt code. Are you using '==' in one spot where you want to use '='......
Interrupts _all_ wake up disabled.
Setup the timer, _before_ setting the value.
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Nov 13, 2011 5:29 am |
|
|
This line is copied from SSR's example code but makes no sense. The timer is configured as an 8-bit timer, meaning a maximum value of 255...
And as TTelmah wrote, you have to set the timer value after configuring it because the instructions for configuring the timer will change its values.
But then again, why set the timer value anyway? You can not predict when the user will switch on your hardware, so who cares for the timer to start up a few miliseconds sooner or later?
In my opinion it is best to leave this line out.
This is one of my most favorite 'common C programmers errors'.
The ';' is interpreted as an 'empty statement' and terminates the while-loop statement. The { at the next line is never reached and the while-loop is running forever, doing nothing. |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
routine interrupt |
Posted: Sun Nov 13, 2011 12:44 pm |
|
|
So I understand that the TIMER0 does not take a value greater than 256 (the value 50006 is false?) and value (50 006) how it is calculated, and is what we can do that will trigger an interrupt every 1 second? or not
and really thank you |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sun Nov 13, 2011 3:23 pm |
|
|
How about looking at the example that CCS supplies?
I think it's ex_stwt.c if memory serves me right... |
|
|
kamillas
Joined: 24 Oct 2011 Posts: 50
|
ex_stwt |
Posted: Sun Nov 13, 2011 4:27 pm |
|
|
Thank you for the answer. I saw the ex_STWT example, in the latter the TIMER0 is initialized by zero (set_timer0 (0);), then we cannot put a value greater than 256 in TIMER0. |
|
|
SSR
Joined: 09 Nov 2011 Posts: 14
|
|
Posted: Mon Nov 14, 2011 7:45 am |
|
|
There is a confusion in the program which i posted. The
has no effect on the output pulse. The timer shows the same 1sec pulse despite of what ever value has been loaded in the timer reg. I have tried it by putting this line before the timer initiation as well after the initiation but still has no effect. Why is it so? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Nov 14, 2011 11:16 am |
|
|
Quote: | So I understand that the TIMER0 does not take a value greater than 256 | The Timer0 can be used as 8 or 16 bit timer, this is what the RTCC_8_BIT parameter defines in the setup_timer_0() function. No parameter means 16-bit, with parameter 8-bits.
It is your choice to choose either option.
Quote: | (the value 50006 is false?) | The example program is configured for 8-bit, a maximum of 256. So yes, 50006 is false. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Nov 15, 2011 5:29 pm |
|
|
This is code extracted from an older product I did that need to track how many seconds a given piece of equipment had been running.
May it help you ?
Code: |
// using an external oscillator on the T1 external input
// INIT
unsigned int32 expsecs=0; unsigned int8 MS125=0;
setup_timer_1( T1_external|T1_DIV_BY_8 ); // 4.194304 mHz osc.
........
#int_timer1
void htm(void){
++MS125; // 125 ms recurrent flag 8x /sec
if ( 8==MS125) { // new second
MS125=0;
++expsecs;
}
}
// call to setup/ enable
//
void time_INIT(void){
clear_interrupt( int_timer1); // setup ISR
expsecs=0;
int8 MS125=0;
enable_interrupts(int_timer1);
enable_interrupts(global);
}
// retrieve total seconds
// this code almost NEVER makes a secons pass of the do/while
unsigned int32 elapsed_seconds(void){
unsigned int32 temp;
do { temp=expsecs; }while (temp!=expsecs);
return temp;
}
|
|
|
|
|