Of course you can - That's what an interrupt stands for!
I suggest you get some PIC programming book!
https://deepbluembedded.com/interrupts-in-pic-microcontrollers/https://class.ece.uw.edu/475/peckol/doc/8976457-Programming-8Bit-PIC-Micro-Controllers-in-C.pdf#page=112You must configure the peripheral or interrupt source first (The timer), clear any pending flags, enable global interrupts (GIE) and also peripheral interrupts (PEI) depending on the peripheral.
This is all explained in the datasheet.
Also, check the datasheet for the "TCKEZTMR1" parameter.
(TABLE 17-8: TIMER0 AND TIMER1 EXTERNAL CLOCK REQUIREMENTS)
It takes about 7 cpu clock cycles for the timer0 to increment when selecting external clock, so it won't be as instant as you might think.
I simulated it, the best I got was about 12-15uS delay.
- 7 clock cycles for the timer to "read" the clock pulse.
- Another 3-4 clocks of interrupt latency (The time it needs to trigger and jump).
- Few more clocks to save context (W and STATUS registers).
- Actual interrut code starts executing.
Then depending on the compiler you must declare a function as an interrupt.
In XC this is done adding the preamble "__interrupt()" to a void function:
void __interrupt() function_name (void)
So for XC8:
void __interrupt() ISR(void){ // This will be called when an interrupt happens
if(TMR0IF){ // Check if TMR0IF is set
TMR0IF=0; // TMR0 interrupt active, clear TMR0IF
//blah // Do something. Don't make any complex, long operations here.
}
if(other_IF){ // This function must check all the enabled interrupts.
other_IF=0;
//other_blah
}
}
Also, make clear the compiler you're using. "C language" means nothing here, PIC compilers are very different to each other.
Also, still, why you MUST use RA0? Why not any of the PORTB pins that have native interrupt-on-change?
You're basically wasting the timer in this basic function.
Some basic code:
#include <xc.h>
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = ON // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
void __interrupt() Interrupt(void){
if (INTCONbits.TMR0IF) {
INTCONbits.TMR0IF = 0;
TMR0 = 255; // Preload timer with 255, so it overflows on next input clock
PORTAbits.RA1 = PORTAbits.RA1; // Toggle RA1
}
}
void main() {
TRISAbits.TRISA1=0; // RA1 as output
TRISAbits.TRISA2=0; // RA2 as output
TRISAbits.TRISA4=1; // RA4 (TOCK1) as input
TMR0 = 255; // Preload timer with 255, so it overflows on next input clock
OPTION_REGbits.T0CS = 1; // Timer0 clock source = TOCK1 pin.
OPTION_REGbits.T0SE = 0; // Clock edge = low-to-high
OPTION_REGbits.PSA = 1; // Prescaler assigned to WDT
INTCONbits.T0IF = 0; // Clear flag
INTCONbits.T0IE = 1; // Enable Timer 0 interrupt
INTCONbits.GIE = 1; // Enable Global interrupts
while(1) {
for(uint16_t i=0; i<10000L; i++); // Small delay
PORTAbits.RA2 = !PORTAbits.RA2; // Toggle RA2 all the time
}
}