View previous topic :: View next topic |
Author |
Message |
kbruin79
Joined: 02 Aug 2010 Posts: 30
|
Timer0 interrupt on pic12f682 |
Posted: Mon Aug 02, 2010 12:29 pm |
|
|
Hello,
I am having trouble with the timer0 interrupt. The code suppose to check port GP2 for a low to high signal and interrupt on timer0 overflow.
When the code jumps to the interrupt service routine the LED suppose to turn on.
It's simply not working. Am i missing something in the code?
Code: |
#include <12f683.h>
#include <math.h>
#include <stdlib.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#use delay (internal=4000000) //(clock=4M)
//address of the TRISIO register
#byte TRISIO = 133
// bit assignment of the TRISIO registers
#bit TRISIO_1= TRISIO.1
#bit TRISIO_2= TRISIO.2
#byte GPIO = 5
//bit assignment for I/O registers
#bit GPIO_1 = GPIO.1
#bit GPIO_2 = GPIO.2
#byte ANSEL=159
#bit ANSEL_1= ANSEL.1
#bit ANSEL_2= ANSEL.2
#byte ADCON0 = 31
#bit ADCON0_0 = ADCON0.0
#bit ADCON0_1 = ADCON0.1
#bit ADCON0_2 = ADCON0.2
#bit ADCON0_3 = ADCON0.3
#bit ADCON0_7 = ADCON0.7
//interrupt variables
#byte TMR0=1
#bit TMR0_0=TMR0.0
#bit TMR0_1=TMR0.1
#byte OPTION_REG=129
#bit OPTION_REG_0=OPTION_REG.0
#bit OPTION_REG_1=OPTION_REG.1
#bit OPTION_REG_2=OPTION_REG.2
#bit OPTION_REG_3=OPTION_REG.3
#bit OPTION_REG_4=OPTION_REG.4
#bit OPTION_REG_5=OPTION_REG.5
#bit OPTION_REG_6=OPTION_REG.6
#bit OPTION_REG_7=OPTION_REG.7
#byte INTCON=11
#bit INTCON_2=INTCON.2 //TOIF Timer0 Overflow Interrupt Flag
#bit INTCON_4=INTCON.4
#bit INTCON_5=INTCON.5 //TOIE Enables the Timer0 interrupt
#bit INTCON_7=INTCON.7 //GIE Global Interrupt Enable bit
//comparator
#byte CMCON=25
//---------------------------------------------------
//function prototypes:
//---------------------------------------------------
// initialize the interrupt registers
void Init(void);
//---------------------------------------------------
// Main
//---------------------------------------------------
void main()
{
//comparator settings
CMCON=0b00000111; //TURN OFF THE COMPARATOR
//Pin input/output settings
TRISIO_2=1; // set GP2 to input
TRISIO_1=0; // set GP1 to output
//Set Analog and digital pins
ANSEL_1=0; // pin GP1 is digital
ANSEL_2=0; // pin GP2 is digital
//-----------------------------------------------------
//main loop
//-----------------------------------------------------
//intitialize timer 0
Init();
//make sure pin GP1 output is zero
GPIO_1=0;
while(1)
{
// do nothing except when there is an interrupt
}
}
Void Init (void)
{
//CLEAR THE TMRO REGISTER
TMR0=0;
// Assign the prescaler to watchdog timer ( 1:1)
//interrupt pin configurations
OPTION_REG_0=0; // 1:1 prescaler
OPTION_REG_1=0; // 1:1 prescaler
OPTION_REG_2=0; // 1:1 prescaler
OPTION_REG_3=1; // ASSIGN prescaler to WATCH DOG TIMER SO THAT //TIMER0 INCREMENTS AT 1:1 RATIO WITH INTERNAL INSTRUCTION CLOCK
OPTION_REG_4=0; //Increment on low to high transition on T0CKI pin
OPTION_REG_5=1;// Transition on T0CKI pin
OPTION_REG_6=0; //Interrupt on falling edge of INT pin
OPTION_REG_7=0; //GPIO pull-ups are enabled
INTCON_5=1; //TOIE enable the TMRO overflow interrupts
INTCON_7=1; //GIE enable the global interrupts
}
#int_timer0 // associates the interrupt with timer0
void timer0interrupt(void)
{
//INTCON_2 : timer0 overflow interrupt flag
//INTCON_5 timer0 overflow interrupt Enable bit
If (INTCON_2 && INTCON_5)
{
INTCON_2=0; //reset timer0 interrupt flag
GPIO_1=1; // light an LED
}
}
|
|
|
|
mkuang
Joined: 14 Dec 2007 Posts: 257
|
|
Posted: Mon Aug 02, 2010 1:13 pm |
|
|
You are not using any of the CCS built-in functions. That makes your code very hard to debug without looking at the datasheets. Search this forum on how to write a simple test program using standard CCS functions. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Aug 02, 2010 3:42 pm |
|
|
Code: | OPTION_REG_4=0; //Increment on low to high transition on T0CKI pin | This causes the Timer0 to count pulses on the external clock input pin, but you have configured the fuses to use the internal clock. Result is the timer0 not counting.
Code: | If (INTCON_2 && INTCON_5) | Not an error, but this line can be removed. The hardware will only enter the interrupt routine when the interrupt is enabled and triggered on overflow, so no need to test these bits.
Code: | INTCON_2=0; //reset timer0 interrupt flag | Another line not needed. CCS automatically adds code to clear this interrupt. The only interrupt you have to clear manually in CCS are the PortB interrupts.
The advantage of using the CCS supplied functions over directly accessing registers yourself is that it makes your program a lot easier to read and it is very easy to port your program to another processor (often only the processor include file has to be changed).
Note that in the converted program below a lot of your original comments can be stripped because the code has become self documenting.
Code: | #include <12f683.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOMCLR
#use delay (internal=4000000) //(clock=4M)
//---------------------------------------------------
//function prototypes:
//---------------------------------------------------
// initialize the interrupt registers
void Init(void);
//---------------------------------------------------
// Main
//---------------------------------------------------
void main()
{
//TURN OFF THE COMPARATOR
setup_comparator(NC_NC_NC_NC);
// Turn off the Capture/Compare module
setup_ccp1(CCP_OFF);
//Pin input/output settings
#use fast_io(A)
set_tris_a(0b111111101);
//Set Analog and digital pins
// pin GP1 is digital
// pin GP2 is digital
setup_adc(ADC_OFF);
setup_adc_ports(sAN0 | sAN3); // or setup_adc_ports(NO_ANALOGS);
//-----------------------------------------------------
//main loop
//-----------------------------------------------------
//intitialize timer 0
Init();
//make sure pin GP1 output is zero
output_low(PIN_A1);
while(1)
{
// do nothing except when there is an interrupt
}
}
void Init(void)
{
// setup Timer 0
set_timer0(0);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_1);
// enable the TMRO overflow interrupts
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
}
#int_timer0 // associates the interrupt with timer0
void timer0interrupt(void)
{
output_high(PIN_A1);
} |
|
|
|
kbruin79
Joined: 02 Aug 2010 Posts: 30
|
|
Posted: Mon Aug 02, 2010 5:07 pm |
|
|
Hi Ckielstra, Thank you for taking the time to look at the code i really appreciated.
You said that "i set the Timer0 to count pulses on the external clock input pin." That's right
Code: |
OPTION_REG_4=0; //Increment on low to high transition on T0CKI pin
|
" but you have configured the fuses to use the internal clock. Result is the timer0 not counting. "
I don't understand this part. Timer0 Clock Source Select bit "TOCS" is set to transistion on the TOCKl pin not the internal clock. Or am i missing something ?
Code: |
OPTION_REG_5=1;// TOSC 1=Transition on T0CKI pin 0=internal instruction cycle clock
|
Thank you |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Aug 02, 2010 5:26 pm |
|
|
My mistake, I didn't read your post very well and assumed you were using the internal clock as a time base for Timer0.
There are too many variables in your setup to make a suggestion for where the problem could be. To reduce the scope I suggest you use the internal clock for the moment.
Use my posted program and modify the timer setup to: Code: | setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256); | And replace the interrupt function by: Code: | #int_timer0 // associates the interrupt with timer0
void timer0interrupt(void)
{
static int count;
if (count++ == 50)
{
output_toggle(PIN_A1);
count = 0;
}
} | These changes should toggle the LED every 0.6 seconds.
If this isn't working than you most likely have a hardware problem related to the PIC not starting up. Otherwise, if the LED is flashing, I suspect a problem with your external applied pulse.
Also post your compiler version number. |
|
|
|