Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] PIC16F1934 Timer0 and some other stuff

Status
Not open for further replies.

GeorgeAD

Newbie level 4
Newbie level 4
Joined
Nov 14, 2019
Messages
5
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
100
Hello folks,

Being bored with databases and data warehouses I decided to poke around in an area I always liked.

picked up a starter pickit3 with the up mentioned MCU, quickly blinked a LED, then decided I really enjoy this whole stuff and started digging deeper. I am having some difficulties however controlling the blinking LED with a Timer interrupt. I came across https://www.edaboard.com/showthread...-timer0-to-generate-a-1-ms-or-1-sec-interrupt

First and foremost that formula calculating what value should I assign to the TMR0 bit saved my bacon and created some questions.

I came up with the following code

Code:
#include <xc.h>
#define _XTAL_FREQ 20000000 //Specify the XTAL crystall FREQ
#pragma config FOSC = INTOSC // Configure PIC to use internal oscilator

int count = 0;
void timer_isr()
{  
    if(TMR0IF == 1) { // TMR0 overflowed
    TMR0IF = 0;       // Clear timer interrupt flag
    TMR0 = 0;     //This value represents the in ms that will last the interrupt.
    count++;      // stores how many interrupts occurred for instance if you need 30 ms seconds interrupt
                  // TMR0IF has to 
    }
    if (count == 211)
    {
        PORTAbits.RA0 = 1; // LED on
        count=0;
    }
}

/***** MAIN PROGRAM *****/

void main()
{
    OSCCONbits.IRCF0 = 0; // 8 MHz oscilator config
    OSCCONbits.IRCF1 = 1; // 8 MHz oscilator config
    OSCCONbits.IRCF2 = 1; // 8 MHz oscilator config
    OSCCONbits.IRCF3 = 1; // 8 MHz oscilator config
    
    /** TIMER0 setup **/
    
    OPTION_REGbits.TMR0CS = 0; // 8bit Timer mode selected
    OPTION_REGbits.TMR0SE = 0; // Setting low2high edge
    OPTION_REGbits.PSA = 0; // Select prescaler
    OPTION_REGbits.PS0 = 1; // Setting prescaler Rate
    OPTION_REGbits.PS1 = 1; // Setting prescaler Rate
    OPTION_REGbits.PS2 = 0; // Setting prescaler Rate
    
    
    INTCONbits.TMR0IE = 1;       //Enable timer interrupt bit in PIE1 register
    INTCONbits.GIE=1;          //Enable Global Interrupt
    INTCONbits.PEIE=1;        // Emable peripherial Interrupt
    
    TRISA = 0; // Setting PORTA as an output.
    PORTAbits.RA0 = 0; //LED off
    //*** Main loop
    while(1)
    {                   
        timer_isr();
    }
}

first question would be do I correctly set up Timer0 ?

Code:
 OPTION_REGbits.TMR0CS = 0; // 8bit Timer mode selected
 OPTION_REGbits.TMR0SE = 0; // Setting low2high edge
 OPTION_REGbits.PSA = 0; // Select prescaler
 OPTION_REGbits.PS0 = 1; // Setting prescaler Rate
 OPTION_REGbits.PS1 = 1; // Setting prescaler Rate
 OPTION_REGbits.PS2 = 1; // Setting prescaler Rate

second question would be if my oscilator is properly set at 8 Mhz ? -> reason I chose 8 MHz is to have Timer0
'work' at 2 Mhz, according the datasheet Timer0 uses Fosc / 4.

I'd appreciate any comment if the settings bits are fine.

Now to the real struggle based on the above mentioned thread configuring Timer0 shouldn't be that hard.

First question, do I understand this correctly: the value assigned to TMR0 bit, is sort of representation of the cycles needed to reach certain time, the interrupt flag of the timer0 is set up when Timer0 performs enough cycles hitting the value in TMR0. knowing that the value in TMR0 represents lets say 5 ms ?

Looking at my interrupt handling routing, I'd like to get half a second delay.

Oscilator works at 4Mhz, the clock works at 1 Mhz with prescaller set to 1:128 - by the way I am still having huge difficulties understanding what is that prescaller for.

So 1MHz is approx. 1 uSec, my timer should increment once every 1 usec

Now I want 50ms delay or 0.05 seconds

50ms/1uSec = 50000 cycles ? -> is that correct ?

Now knowing Timer0 overflows at 0xFFFF, the value I have to assign to TMR0 is 0xFFFF-0xC350 = 3CAF or for normal people 15535 is that correct ?

So if I put a variable to increment on every interrupt occurrence can I deduce that 2 interrupts should provide me 0.1 seconds delay, and 10 will provide me half a second ?

This my function should light up the LED for half a second ?


Code:
void timer_isr()
{  
    if(TMR0IF == 1) { // TMR0 overflowed
    TMR0IF = 0;       // Clear timer interrupt flag
    TMR0 = 15535;     //This value represents the in ms that will last the interrupt.
    count++;      // stores how many interrupts occurred for instance if you need 30 ms seconds interrupt
                  // TMR0IF has to 
    }
    if (count == 10)
    {
        PORTAbits.RA0 = 1; // LED on
        count=0;
    }
}

Thank you in advance to whoever decides to look into this, my ultimate goal is to build myself a robot (optionally to bring me beer) :D

George
 

Once you are apparently using interruption with just one timer, checking the interrupt flag right after entering into interruption vector seems unnecessary, there it is supposed to be set as 'true' .

Code:
void timer_isr()
{  
    [B]if(TMR0IF == 1)[/B]
    ...


Im obviously assuming you wanted to instantiate timer_isr() called form interruption itself, not called inside the endless loop form main():

Code:
void main()
{
...
    while(1)
    {                   
        [B]timer_isr();[/B]

Another tip, did you check these timer settings with some of the online timer calculator available on the Web? In general it is my first attempt and only after I compare with datasheet:

http://eng-serve.com/pic/pic_timer.html
http://embedjournal.com/pic-timer-calculator-give-away-1/
 

Hi,

while(1)
{
timer_isr();
}

You don´t have to call the timer_isr. The timer_isr is automatically performed after every timer interrupt.


Klaus

Added:
The prescaler is there to adjust timer_range and timer_resolution.

If I got your description correctly: (code#1)
F_OSC (8MHz / 125ns) --> divide by 4 (F_OSC/4) (2MHz, 500ns) --> prescaler "011" = divide by 16 (125kHz, 8us) each timer counter tick.
If you want 500ms then you need 62500 clock ticks. So if you set the value to 65535-62500 the the ISR is performed after 500ms.
(If it is automatically restarted then the ISR runs twice per second = once every 500ms)
Now if you run a SW counter witin the ISR counting from 0 to 211. this means 212 x 500ms = 106 seconds. I don´t think this is what you want.

**
In the second code you used prescaler = "111" which is divide by 256

Klaus
 

Hello and thanks for spending time on this,

Basically I am learning how to operate with this.

I was not aware of this calculator, so I haven not tried it.

If I omit the timer_isr() from the while loop, LED does not blink.

KlausST, I was playing around with both the oscilator and the the prescaler, as for why there is an additional counter, I thought since timer0 is 8bit, I cannot get more than a quarter of a second delay, thus 2 interrupts should provide me this half a second, that is why I had that counter, with the help of that calculator, the function looks like this

Code:
void timer_isr()
{  
    if(TMR0IF == 1){ // TMR0 overflowed
    TMR0IF = 0;       // Clear timer interrupt flag
    TMR0IE = 1;
    TMR0 = 0;     //This value represents the in ms that will last the interrupt.
    PORTAbits.RA0 = 0;
    }
}

I was looking for a clearly explained formula how to calculate the values at which to set the control bits and registers of the Timer0 :) I think I somehow got it, my ADC experiment will show if I understood it correctly or not.

However I noticed in the example code they put TMR0 outside of the interrupt routine for additional setup (can someone explain that) ?

Code:
// code starts here...
void main()
{
....

//Timer0 Registers Prescaler= 256 - TMR0 Preset = 0 - Freq = 30.52 Hz - Period = 0.032768 seconds
OPTION_REG.T0CS = 0;  // bit 5  TMR0 Clock Source Select bit...0 = Internal Clock (CLKO) 1 = Transition on T0CKI pin
OPTION_REG.T0SE = 0;  // bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
OPTION_REG.PSA = 0;   // bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
OPTION_REG.PS2 = 1;   // bits 2-0  PS2:PS0: Prescaler Rate Select bits
OPTION_REG.PS1 = 1;
OPTION_REG.PS0 = 1;
TMR0 = 0;             // preset for timer register -----------------------------> why do they put this here >?


// Interrupt Registers
  INTCON = 0;           // clear the interrpt control register
  INTCON.TMR0IE = 1;        // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
  INTCON.TMR0IF = 0;        // bit2 clear timer 0 interrupt flag
  INTCON.GIE = 1;           // bit7 global interrupt enable


  while(1)  //endless loop
  {
  }
}
 

The missing link here is you are not utilizing the interrupt at all. The interrupt routine (ISR) is called automatically by the timer module, you don't have to read it or put it in your program loop. Think of it as a subroutine that gets magically called whenever something triggers it, in this case the timer reaching maximum value and rolling over back to zero.

The process is:
1. set up the timer prescaler so it counts at the rate you want, if necessary factor in to it that it might take several interrupts to create the delay you want to create. For example, if you want a one second delay it could be from 100 x 10mS interrupts or maybe 50 x 20mS interrupts.

2. Load the number of remaining counts it takes for the timer to overflow. Remember it counts upwards so the value is 256 minus the required counts.

3. Write an ISR (be careful of it's naming, it is a single pre-defined routine) in it you want to reload the value you worked out in step 2 so the timer repeats the same interval. If you are counting interrupts, add one to the count until it reaches the delay time you need then set a variable to say the delay period is finished. Then clear the count so it starts over again.

4. Back in your main program loop, check the variable you set in step 3. If it isn't set, just carry on, if it is set it means the delay you wanted has finished so do whatever you have to do (toggle the LED for example) then reset the variable ready for the next time.

Enable the timer interrupt just before your main program loop starts.

Brian.
 

Hi,

I´m not experienced with PIC. But there are a lot of informations that don´t match.

You say:
Now knowing Timer0 overflows at 0xFFFF, the value I have to assign to TMR0 is 0xFFFF-0xC350 = 3CAF or for normal people 15535 is that correct ?
So this can´t be correct.
Now you say timer0 is an 8 bit counter (and it seems to be correct): Thus valid values are 0...255 or 0x00 ... 0xFF

***
In the ISR of post#1:
* in Main_init: You initialize RA0 =0
* In the ISR you SET RA0.
* but you never clear it afterwards. --> It can´t blink this way. You need to clear it. Or "toggle" it within the ISR

***
You say
TMR0 = 0; //This value represents the in ms that will last the interrupt.
the comment is not correct. In the ISR you will always read tmr0 to be 0 (unless you insert a long delay in the ISR), because it just has overflown from 255 to 0 (and this overflow started the ISR)

***
are you sure the timer restarts automatically? If not, try to restart it within the ISR.

Klaus
 

Unless I overlooked something, you did not mention what compiler you are using. Most often an interrupt vector is defined preceeded with a '#' directive. The way you did, it was nothing else than declaring the ISR function handler, but not instantiating it as such, I mean, assigning to the compiler the task of calling the function itself whenever an interruption happens.
 

betwixt,

Only when you said it's a system routing called automatically I realized void interrupt() is what you were talking about, point taken.

So as far as I understand the steps, there are 2 'steps' setting up the timer.

first one is in the main body of the program, set the timer0 value, and second one is in the ISR to set the same value so you dont get a longer interval (or shorter) from the ISR.

Question for you here, is there I way I can control how long the interrupt to last, for example I want to attach a Sharp IR distance sensor, if I want the analog2digital converter to operate in an interrupt I have to make sure that the interrupt is long enough so the IR is taking its measurements correct, can we control this or it is magic again ? :)

I have reached this point:

Code:
#include <xc.h>
void __interrupt () my_isr_routine (void) {

  // Timer0 Interrupt - Freq = 318.88 Hz - Period = 0.003136 seconds
  if (INTCONbits.TMR0IF == 1) // timer 0 interrupt flag
  {
    PORTAbits.RA0 = 1;      // Toggle PORTB bit0 LED
    INTCONbits.TMR0IF = 0;         // clear the flag
    INTCONbits.TMR0IE = 1;         // reenable the interrupt
    TMR0 = 10;           // reset the timer preset count
  }
}

// code starts here...
void main()
{
  // setup portb to show the interrupts by blibking LEDs
  TRISA = 0x00;    // PORT is all output...to show the interrupts
  PORTA = 0;       // start with all outputs low

//Timer0 Registers Prescaler= 32 - TMR0 Preset = 60 - Freq = 318.88 Hz - Period = 0.003136 seconds
OPTION_REG.T0CS = 0;  // bit 5  TMR0 Clock Source Select bit...0 = Internal Clock (CLKO) 1 = Transition on T0CKI pin
OPTION_REG.T0SE = 0;  // bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
OPTION_REG.PSA = 0;   // bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
OPTION_REG.PS2 = 1;   // bits 2-0  PS2:PS0: Prescaler Rate Select bits
OPTION_REG.PS1 = 0;
OPTION_REG.PS0 = 0;
TMR0 = 60;             // preset for timer register

// Interrupt Registers
  INTCON = 0;           // clear the interrpt control register
  INTCONbits.TMR0IE = 1;        // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
  INTCONbits.TMR0IF = 0;        // bit2 clear timer 0 interrupt flag
  INTCONbits.GIE = 1;           // bit7 global interrupt enable


  while(1)  //endless loop
  {
  }
}

Now since I keep the LED off and only flash it in the ISR, I'd expect a lot of the time the LED to be off, here is what is actually happening, LED is on for nearly 3 seconds then a blink of an eye off stage then on again for nearly 3 second, what do I miss, frankly I expected exactly the opposite. Oscilator is at 8MHz ?

KlausST, indeed only after I posted my initial comment I noticed I coppied from an old thread from the forum here the 16 bit timer while mine was only 8. As for the bits, in the main body I am setting low only the bit the LED is attached to in PORTAbitsRA0, and I am leaving it off, in the ISR I am setting that same bit to high, isn't this how it is done ?

I'd rather use bits from the port than setting the whole port high ?

As for the toggle, my idea is in the main body of the program the LED is off, upon interrupt, it is on then after interrupt 'gone' LED is off again.

With the explanation of betwixt, I understood why do we set value to TMR0 - basically we want TMR0 to cycle up to that value.

I do not know if the timer restarts automatically I thought setting up TMR0IF to low resets it no ?

Andre, I am using MPLAB X v5.30, as for compiler I think XC8-cc(v2.10) - from properties of the main.c file.


-George</xc.h>
 

TMR0IF is a flag (a bit that signifies something happened) in the interrupt register, not the timer itself. The timer runs continuously, counting 0 -> 0xFF repeatedly as long as it is enabled.

You should check the flag is set inside the ISR for the simple reason that the one ISR is used by all the interrupts so you need to establish the source of the interrupt, it could be from other peripherals.

You shouldn't re-enable the interrupt inside the ISR because on PIC16 series processors the ISR is not re-entrant. That means you can't interrupt the ISR itself with a second one. However, before entering the ISR, the PIC hardware disables the GIE bit to prevent it trying and it re-enables it when it leaves the ISR. For normal use you don't have to re-enable it yourself. Note that the GIE stops interrupts being processed but it doesn't stop interrupts being noted. If an interrupt flag is set while you are inside an ISR it will be actioned as soon as the ISR exits. If interrupts have to be prioritized (in PICs that only have one interrupt level) you have to do it by arranging the order you check the interrupt flags inside the ISR code.

A word of caution: for exactly the reason in the paragraph above, don't spend too long inside an ISR and the rules of programming say that anyone deliberately adding a delay in an ISR has to be taken out and shot. Remember there is only one interrupt flag for each peripheral so for example if your TMR0 interrupt was every 10mS and you added a 100mS delay inside the ISR it means you lose the next nine interrupts. Perhaps not disastrous in a timer application but imagine if the interrupts were created by an incoming data stream and most of the data was ignored.

If you want to toggle a bit, for example the one driving your LED, there are two ways to do it:
1. Read it, check it and if set then reset it, otherwise set it,
2. XOR it with itself.

Some PICs, I think yours is OK, have a potential problem with "RMW" (Read, Modify, Write) so it is considered bad practice to do that. It is a problem that can occur when you read the present state of a bit, change it then write it back. It is an electrical issue to do with residual voltage levels on the pin rather than the logic level it was last driven to but it can be a read headache to debug when it happens!

Brian.
 
Hi,


2. XOR it with itself.
XOR with it self = switching OFF
XOR with 1 = toggle

******
As for the bits, in the main body I am setting low only the bit the LED is attached to in PORTAbitsRA0, and I am leaving it off, in the ISR I am setting that same bit to high, isn't this how it is done ?
So far so good. But you want it to blink. Blink means: OFF - wait - ON - Wait ....repeatedly.
But you do: OFF (init, main) - wait (timer) - ON (ISR) - wait (timer) - ON (ISR)- wait (timer) - ON (ISR)....
It never is switched OFF

Thus I recommend: OFF (init, main) - wait (timer) - TOGGLE (ISR) - wait (timer) - TOGGLE (ISR)- wait (timer) - TOGGLE (ISR)....

*****
As for the toggle, my idea is in the main body of the program the LED is off, upon interrupt, it is on then after interrupt 'gone' LED is off again.
There is no "interrupt gone". The interrupt is a flag and it just makes the ISR to run. Once ... unless you don´t restart the timer.

With the explanation of betwixt, I understood why do we set value to TMR0 - basically we want TMR0 to cycle up to that value.
The "timer" is hardware, not software.
When you do nothing... tmr0 is counting up from 0 to 255 then the interrupt flag is set and it starts again from 0.

Let´s imagine the counter frequency is 1kHz. then it takes 1ms to count one step. 0 (1ms later) -> 1 (1ms later) -> 2 (1ms later) -> 3 (1ms later) -> 4 (1ms later) -> 5...
So it takes 256 counts then an overflow happens .. and the ISR runs.
Now let´s imagine you don´t want the ISR run every 256ms but every 5ms.
Then:
*Init: it to (256-5 =) 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
* (1ms later) -> 255
* (1ms later) -> 0 --> ISR trigger. Within the ISR set it to (256-5)= 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
* (1ms later) -> 255
* (1ms later) -> 0 --> ISR trigger. Within the ISR set it to (256-5)= 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
.. and so on

I do not know if the timer restarts automatically I thought setting up TMR0IF to low resets it no ?
TMR0IF is just the INTERRUPT-FLAG. For sure it needs to be cleared to enable a now trigger of the ISR. But it won´t set the TMR0 to the desired value to get the desired delay. (251 in my example)

Klaus
 
TMR0IF is just the INTERRUPT-FLAG. For sure it needs to be cleared to enable a now trigger of the ISR. But it won´t set the TMR0 to the desired value to get the desired delay. (251 in my example)
Just to be clear: with the IF bit set (and also the IE bit set of course) the ISR will be called. You *should* clear the IF flag in the ISR to make sure that the next time it is set by the hardware, the ISR will be called again.
If you DON'T clear it i teh ISR, then as soon as the ISR exists, the hardware will check the IE and IF flags, find them both set and so call the ISR again immediately.
Susan
 
You shouldn't re-enable the interrupt inside the ISR because on PIC16 series processors the ISR is not re-entrant. That means you can't interrupt the ISR itself with a second one. However, before entering the ISR, the PIC hardware disables the GIE bit to prevent it trying and it re-enables it when it leaves the ISR. For normal use you don't have to re-enable it yourself. Note that the GIE stops interrupts being processed but it doesn't stop interrupts being noted. If an interrupt flag is set while you are inside an ISR it will be actioned as soon as the ISR exits. If interrupts have to be prioritized (in PICs that only have one interrupt level) you have to do it by arranging the order you check the interrupt flags inside the ISR code.

Brian.

I decided for a long enough interrupt so my eye can actually see the LED toggled on/off, I do realize interrupts has to be lighting fast (that's the idea huh), and slowing down an interrupt loosing other interrupts is the culprit of a bad program thus bad programmer.

I appreciate marking the specifics of TMR0IF. This is how my ISR looks now:

Code:
if (INTCONbits.TMR0IF == 1) // timer 0 interrupt flag
  {
    PORTAbits.RA0 = 1;  // ON PORTA bit0 LED 
    TMR0 = 60;           // reset the timer preset count
    INTCONbits.TMR0IF = 0;
  }

KlausST,

If I understand you right you imply here must be 1 more line either above or under line PORTAbits.RA0 = 1; putting that bit to 0 correct ?

My initial design was the LED to turn on only during interrupt of Timer0.

The way the code acts currently is LED is ON for quite some time (since I toggle on the LED only in the interrupt I presume interrupt takes THAT long), then a very short and barely noticeable pause (LED barely goes OFF), as if my interrupt length in time is huge. The period the LED is on is quite long and the off state of the LED is barely noticeable as if all the MCU is doing is interrupts... Is that the correct behavior ?

Susan,

the way you say it if I leave TMR0IF outside the ISR (clear it in the main code after IRS), I might never reach it because MCU will endup in an infinte loop servicing one and the same interrupt right ?

My latest code, any advise on the TMR0 and the Oscilator setup, are they correctly set ?

Code:
#include <xc.h>
#define _XTAL_FREQ 20000000 //Specify the XTAL crystall FREQ
#pragma config FOSC = INTOSC // Configure PIC to use internal oscilator
void __interrupt () isr_routine (void) {

  // Timer0 Interrupt - Freq = 30.52 Hz - Period = 0.032768 seconds
  if (INTCONbits.TMR0IF == 1) // timer 0 interrupt flag
  {
    PORTAbits.RA0 = 1;  // ON PORTA bit0 LED 
    TMR0 = 100;           // reset the timer preset count
    INTCONbits.TMR0IF = 0;
  }
}

// code starts here...
void main()
{
     
//  Oscilator set at 8 MHz oscilator config
 OSCCONbits.IRCF0 = 1; 
 OSCCONbits.IRCF1 = 1;  
 OSCCONbits.IRCF2 = 1; 
 OSCCONbits.IRCF3 = 0; 
 
//Timer0 Registers Prescaler= 8 - TMR0 Preset = 100 - Freq = 1602.56 Hz - Period = 0.000624 seconds
OPTION_REGbits.T0CS = 0;  // bit 5  TMR0 Clock Source Select bit...0 = Internal Clock (CLKO) 1 = Transition on T0CKI pin
OPTION_REGbits.T0SE = 0;  // bit 4 TMR0 Source Edge Select bit 0 = low/high 1 = high/low
OPTION_REGbits.PSA = 0;   // bit 3  Prescaler Assignment bit...0 = Prescaler is assigned to the Timer0
OPTION_REGbits.PS2 = 0;   // bits 2-0  PS2:PS0: Prescaler Rate Select bits
OPTION_REGbits.PS1 = 1;
OPTION_REGbits.PS0 = 0;
TMR0 = 100;             // preset for timer register


// Interrupt Registers
  INTCON = 0;           // clear the interrpt control register
  INTCONbits.TMR0IE = 1;        // bit5 TMR0 Overflow Interrupt Enable bit...1 = Enables the TMR0 interrupt
  INTCONbits.TMR0IF = 0;        // bit2 clear timer 0 interrupt flag
  INTCONbits.GIE = 1;           // bit7 global interrupt enable 

  TRISA = 0x00;    // PORT is all output...to show the interrupts
  PORTAbits.RA0 = 0;       // start with all outputs low
  
  while(1)  //endless loop
  {
  }
}

With all the reading today I am reaching a state of mind where (thanks to your explanations) using timer interrupts would not be very useful flashing a LED, due to the fact interrupts are happening quite fast (configurable), and the interrupt length(in time) is quite short, thus actual observation of a LED being OFF, flash it ON for noticeable enough period is not something interrupts should be used for, am I right ?

Tomorrow I plan poking around with a ADC, I hope I have more luck there

- - - Updated - - -

Let´s imagine the counter frequency is 1kHz. then it takes 1ms to count one step. 0 (1ms later) -> 1 (1ms later) -> 2 (1ms later) -> 3 (1ms later) -> 4 (1ms later) -> 5...
So it takes 256 counts then an overflow happens .. and the ISR runs.
Now let´s imagine you don´t want the ISR run every 256ms but every 5ms.
Then:
*Init: it to (256-5 =) 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
* (1ms later) -> 255
* (1ms later) -> 0 --> ISR trigger. Within the ISR set it to (256-5)= 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
* (1ms later) -> 255
* (1ms later) -> 0 --> ISR trigger. Within the ISR set it to (256-5)= 251
* (1ms later) -> 252
* (1ms later) -> 253
* (1ms later) -> 254
.. and so on


Klaus

This is precisely what I don't get: Timer0 ticks once every 1ms, since Timer0 goes from 00 to FF or 0 to 255, when you reach FF(255) it will take 255ms (time) or 255 ticks - is this right ?

How can I adjust a tick to takes place once every 5ms - I know it is hell slow but just asking?

Your example is supreme, you are setting up the ISR to takes place every 5 ms (TMR0 = 251 and it ticks up until 256 and interrupt happens).

btw I fully understood your post while I was writing this reply :D

-George
 

Hi.

If I understand you right you imply here must be 1 more line either above or under line PORTAbits.RA0 = 1; putting that bit to 0 correct ?
No. Definitely not.
Apparently you misunderstand what "toggle" means.
Toggle means
* invert
* in other words: when the LED previously was ON, then you switch it OFF and leave the ISR. When the LED previously was OFF, then you switch it ON and leave the ISR.

...but you don't switch it twice within one ISR.

Read what I have written. You need to run the ISR twice. One for switching the LED ON, one for switching the LED OFF.

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top