Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Trying to setup a 125uS interrupt.

Status
Not open for further replies.

Pommie

Well-Known Member
Most Helpful Member
I'm trying to setup an interrupt to produce 125uS ticks.
I had the following code which doesn't work,
Code:
#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t count;

ISR(TIMER2_COMPA_vect){
  count++;
}

void setup(){
  Serial.begin(115200);
  cli();                //disable interrupts
  OCR2A=249;            //set period
  TCCR2A = (1<<WGM21);  //CTC mode
  TCCR2B = (1<<CS21);   //prescaler = 8
  TIMSK2 = (1<<OCIE2A); //enable timer interrupts
  sei();                //enable all interrupts
  while(1){
    Serial.println(count);
  }
}

void loop(){
}
But, if I move the line OCR2A=249; down to just before the sei() line then it works perfectly.
It also works if I add the line OCR2A=249; to the ISR.

There must be a logical explanation for this but I can't work it out.

Any ideas anyone?

Mike.
 
This has the interrupt configuration I'm using, it's got masses of comments as it's part or a youtube multitasking tutorial I'm working on:

It's using timer 0 rather than 2.


C:
//
// Robert Jenkins Technology Channel
//
// https://www.youtube.com/@RJTC
//
// Real time interrupt example
// Part of my multitasking series
//
// This example has been tested on Arduino Uno R3 and Mega2560 R3 boards,
// and it will likely also work on other AVR based Arduinos
//
// Set the board type appropriately in the Tools > Board menu!
//
// See the "Multitasking_Periodic_Interrupt_ARM" version for ARM based Arduinos.
//

// Standardised variable type includes:
// Adding these allows variable type names to be used the same
// Across different compilers, rather than having to redefine
// for each different compiler.
// intxx_t for signed with xx bit size,
// uintxx_t for unnsigned with xx bit size.
//
#include <stdint.h>
#include <stdbool.h>


// Global variable definitions

// Time / timing related
int8_t t_xsec;            // Fractional mS, used with interrupts >1KHz
int8_t t_msec;            // Millisecond counter
int8_t t_csec;            // 1/100th second counter
int8_t t_dsec;            // 1/10th second counter
int8_t t_ssec;            // second counter

// t_min, t_hour etc. could also be added if time of day tracking is needed,
// though preferably add a section in the main program loop that checks t_secflag
// and increments counters as appropriate each time that is set, to minimise the interrupt duration.

// struct_tm xtime;       // Not used in this program; used with time.h functions for time conversions

uint32_t tick_counter;    // "ticks; count of 1mS incerments since program was started.

bool i_msecflag;          // flag bits used (set) by the interrupt
bool i_csecflag;          // routine at the various intervals
bool i_dsecflag;
bool i_ssecflag;

bool t_msecflag;          // Copies of the above, used in the main program
bool t_csecflag;          // to synchronise timed actions
bool t_dsecflag;
bool t_ssecflag;


// Plus a byte store the demo LED states
uint8_t ledbits;


void setup() {
  // put your setup code here, to run once:

  // Configure ports and any other peripherals etc.
  // Using 8 & 9 as they are close to GND for LED resistor common.
 
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

  // Initialise and configure a timer:
  cli();          // Probably not needed, but keeps things safe if this section is re-used
  TIMSK0 = 0;     // Clear register to disable timer interrupts, also probably not needed

  // TCCR0A and TCCR0B are configuration registers for Timer 0
 
  TCCR0A = _BV(WGM01);    // Sets the counter module in counter (as opposed to PWM) mode.

  // The low three bits of TCCR0B control the prescaler for the counter input,
  // from the CPU I/O clock frequency. 001 = /1 (direct), 010 = /8, 011 = /64, 100 = /256, 101 = /1024.
  // 000 = no input, 110 & 111 set input from an MCU pin.
  // The remaining bits should be zero for a repetitive interrupt use, such as this.
 
  TCCR0B = _BV(CS01) | _BV(CS00);     // Write bit 1 and 0 to 1 = [011]. I/O clock /64 to timer.

  // OCR0A is the value that the count will be compared to, to trigger an interrupt.
 
  // The MCU clock (16MHz on a Mega2560) will be divided by the prescaler value to
  // to increment the timer0 counter & an interrupt will be triggered each time the
  // the count reaches the number in OCR0A
  // With the prescaler bits 011, prescale /64, that timer clock will be 250 KHz.
  // At that, setting OCR0A to 250 would give 1mS interrupts.

  // For approx. 10mS, use TCCR0B = _BV(CS02); giving /256 and set OCR0A to 156
  // Or use the valuse as below and ignore the t_csecflag fo 10mS indication...
 
 
  OCR0A = 250;             // 16KHz / 16 count = 1mS interrupt rate

  // Now enable the interrupt from Timer 0 when there is a compare match.
  // That interrupt is called TIMER0_COMPA_vect
 
  TIMSK0 = _BV(OCIE0A);


  // Finally, after all hardware initialisation etc. is complete,
  // enable the overall MCU interrupts
  sei();
 
}

void loop() {
  // put your main code here, to run repeatedly:

  // As the interrupts could occur at any time in the main program,
  // check and copy the time flag bits here so they are consistent all
  // the way through the main program loop.
  // This can be done a bit more efficiently, but this is a demo
  // to explain the overall methodology!
  // See the Arduino Due example for the faster version

  cli(); // temporarily disable interrupts to nothing changes while testing the bits!

  if(i_msecflag) {
    t_msecflag = true;
    i_msecflag = false;
  }
  else {
    t_msecflag = false;
  }

  if(i_csecflag) {
    t_csecflag = true;
    i_csecflag = false;
  }
  else {
    t_csecflag = false;
  }

  if(i_dsecflag) {
    t_dsecflag = true;
    i_dsecflag = false;
  }
  else {
    t_dsecflag = false;
  }

  if(i_ssecflag) {
    t_ssecflag = true;
    i_ssecflag = false;
  }
  else {
    t_ssecflag = false;
  }

  // The t_ flag bits above will be set for one pass through the main program loop
  // at their respective intervals.
  // eg. If you want to do something ten times per second, check for the t_dsecflag being set
 
  // Or test (t_flags & F_DSEC), in the fast version of the flag update routine as in the Arduino Duo example.

sei(); // Re-enable the interrupts

// The rest of the program from here on.


// This demo is just going to toggle a couple of outputs at 10Hz and 1Hz
// (so flashing cycles at 5Hz and 0.5Hz)

if(t_dsecflag)
 
  // Toggle LED on pin 9, bit 1 of store
  if(ledbits & 0x02) // LED is on
  {
    digitalWrite(9, LOW);
    ledbits &= 0xFD;  // turn off bit 1
  }
  else
  {
    digitalWrite(9, HIGH);
    ledbits |= 0x02;  // turn on bit 1
  }


if(t_ssecflag)
 
  // Toggle LED on pin 8, bit 0 of store
  if(ledbits & 0x01) // LED is on
  {
    digitalWrite(8, LOW);
    ledbits &= 0xFE; // turn off bit 0
  }
  else
  {
    digitalWrite(8, HIGH);
    ledbits |= 0x01; // turn on bit 0
  }


  // Add to the program here, as you wish.


  // End of main program loop
}



// This is the function that will be called each time the timer 0 periodic interrupt occurs:
ISR(TIMER0_COMPA_vect)
{
  // The code in an interrupt routine must be minimal,
  // to do only what is absoluetly essential - no waiting
  // or delays of any type!

  // With the settings above, this will be called at 1KHz, every 1mS.
 

  // Count milliseconds through to seconds
 
  t_msec++;
  i_msecflag = true;
 
  if(t_msec > 9) {
    // 10 counts, reset and increment 1/100sec
    t_msec = 0;

    t_csec++;
    i_csecflag = true;

    if(t_csec > 9) {
      // Same for each decade used
      t_csec = 0;

      t_dsec++;
      i_dsecflag = true;

      if(t_dsec > 9) {
        t_dsec = 0;

        t_ssec++;
        i_ssecflag = true;
      }
    }
  }

  // Counters done, any other stuff such as serial
  // port & buffer checks for up to 9600 baud
  // could also go in here.

  // My software timer library would also be called from here

 
}
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top