how to use timer in critical 'no interrupt' code section

How do I use the timer inside the critical code, where interrupts are disabled?

Basically, when a button is pressed, the ISR sets the button, the main loop checks if a number button was set and sends bits high and low on a pin. This high and low is time sensitive so interrupts need to be disabled, but then the timer doesn’t work. Do I really start using micro’s inside the critical section?

// defines and set-up not really relevant

void loop(){

    if(button_pressed != 0){
       
    noInterrupts();

       //BUT IS YOU DISABLE INTERRUPTS, THE DELAY FUNCTION WILL NOT WORK, only micros ...

        switch (button_pressed){
            case BUTTON_TOP_LEFT:
                sendAddress(128);
                break;
        }
        button_pressed = 0;

    interrupts();

    }

    delay(100);
}


void buttonPressedISR(void){  

    if (millis() - last_fire < 200) { // Debounce
        return;
    }
    last_fire = millis();

    cli();
    if(digitalRead(BUTTON_TOP_LEFT) == LOW){
        button_pressed = BUTTON_TOP_LEFT;
    }
    sei();
}

uint8_t sendAddress(uint8_t local_address){

    // ANY DELAY OR USE OF MILLIS WILL NOT WORK
    

}


// EOF

You need to post the complete program. Also provide a good description of the project you want to create.

I can't help thinking that you are approaching the problem in the wrong way. Interrupts should only be paused for a few microsecs which means that timing while they are paused is unlikely to be needed.

...R

How critical is the timing? How long is the sequence? How complex is the sequence?

If the 'button' is pressed by a human it is almost never appropriate to use an interrupt.

You can use delay loops with interrupts disabled.

It’s time sensitive, but you’re going to use millis() to time it?
Anything requiring only millisecond granularity doesn’t seem particularly time sensitive to me....

No idea why you feel the need to disable and re-enable interrupts inside buttonPressedISR().
Perhaps this is part of your attempt to work around the issue, or a genuine misunderstanding.
Regardless interrupts are already disabled when handling an ISR. You should NEVER reenable them.

this is where I want to go:

pseudo code

loop(){

    if(checkButton()){

        cli();   // Can I disable interrupts here and expect delay to still work?
    
         sendByte(){

         delay(50);
         setBit(HIGH);
         delay(50);
         setBit(LOW);
         delay(50);
         setBitHigh(HIGH);
         delay(50);
         setBitHigh(LOW);

         }

    
        sei()

    }

    sleep();


}


ISR_wakeUp(){

     setButton(3);

}

Just a question about your code in the OP.

Why do you disable interrupts in the ISR; they are already disabled.
Why do you enable interrupts at the end of the ISR; they will be enabled when you leave the ISR.

Referring to Reply #4

// Can I disable interrupts here and expect delay to still work?

No. The Arduino needs interrupts functioning to update the timing.

A much more serious issue is that you should NEVER consider pausing interrupts for even one millisec, never mind the 200 millisecs that is in your code snippet. Pausing interrupts for 100 microsecs would be a long time.

Have you read Reply #1 ? It is much easier to give useful advice when we know what the project is. At the moment you have just posed a typical XY problem

...R

What makes you think that you 50 millisecond (800,000-cycle) delays will be off too much if you leave interrupts enabled? Perhaps it is your own interrupt that is causing the problem. Try implementing your sketch without using interrupts.

Using delays more than a few milliseconds will cause your sketch to be unresponsive. Y0ou should strive to use other methods. Maybe a finite state machine, like this:

const byte OutputPin = 2;
boolean ButtonPressed = false;  // Set to 'true' to start sending
enum SendStates {Idle, FirstPause, FirstHigh, FirstLow, SecondHigh} SendState = Idle;


void setup()
{
  pinMode(OutputPin, OUTPUT);
}


void loop()
{
  send();
}


void send()
{
  unsigned long currentTime = micros();
  static unsigned long stateStartTime = 0;
  static enum SendStates sendState = Idle;


  switch (sendState)
  {
    case Idle:
      if (ButtonPressed)
      {
        ButtonPressed = false;
        stateStartTime = currentTime;
        sendState = FirstPause;
      }
      break;


    case FirstPause:
      if (currentTime - stateStartTime >= 50000UL)
      {
        digitalWrite(OutputPin, HIGH);
        stateStartTime = currentTime;
        sendState = FirstHigh;
      }
      break;


    case FirstHigh:
      if (currentTime - stateStartTime >= 50000UL)
      {
        digitalWrite(OutputPin, LOW);
        stateStartTime = currentTime;
        sendState = FirstLow;
      }
      break;


    case  FirstLow:
      if (currentTime - stateStartTime >= 50000UL)
      {
        digitalWrite(OutputPin, HIGH);
        stateStartTime = currentTime;
        sendState = SecondHigh;
      }
      break;


    case SecondHigh:
      if (currentTime - stateStartTime >= 50000UL)
      {
        digitalWrite(OutputPin, LOW);
        sendState = Idle;
      }
      break;
  }
}

Robin2:
Referring to Reply #4

No. The Arduino needs interrupts functioning to update the timing.
...R

so should I use micro's function instead?

No. Describe the problem you want to solve. Always post complete code

hewi:
so should I use micro’s function instead?

Why have only responded to part of my Reply #4, and have ignored what is really the important part?

If you are not prepared to describe the project then I don’t see how I can help you.

…R