user65866: I want to create a simple program, that responds to me sending a character over the Arduino IDE console. I am using an arduino UNO. Here is my program:
volatile bool MeasReceived=false;

ISR(PCINT2_vect){  
  PCICR = 0b00000000;    // turn off port d
  MeasReceived=true;
}

void setup() {    
  Serial.begin(9600);
  Serial.flush();

  Serial.print("Hello PC");
  delay(1000);
  cli();      
  PCICR |= 0b00000100;    // turn on port d
  PCMSK2 |= 0b0000001;    // turn on pins PD0 , PCINT16
  sei();


}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    inByte = Serial.read();
     
    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
  }
  PCICR = 0b00000001; // re-enable port d
}

What I do is that I set the RX pin as a pin change interrupt. After that, I send a character through the console, for example 'A'. The ISR kicks in, firstly disabling the interrupt, and after that, the flag is set true. That way, I enter the part of the code where I do the Serial.read() command, to find what character was sent to me via the console.
The problem is that, no matter the character I send, the result is always 255. That means that the value of inByte, after the Serial.read() is always 255. What goes wrong?
EDIT: Original question answered by me below. However, one interesting thing occured in the new code posted below. If I put the Arduino to sleep (powerDown Mode), and try to wake it up with the serial interrupt, if I send only one character, then the arduino does wake up, but does not enter the ISR! If I send two characters, then the ISR is accessed and the flags set, with the program working fine. Here is the code, to reproduce the issue:
volatile bool MeasReceived=false;
uint8_t inByte;



ISR(PCINT2_vect){
  PCMSK2 = 0b00000000;    // turn off port d
  MeasReceived=true;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

 
  Serial.begin(9600);
  Serial.flush();
  Serial.print("Hello PC");
  delay(1000);
      
  cli();
  PCICR = 0b00000100;    // turn on port d
  PCMSK2 = 0b00000001;    // turn on pins PD0 , PCINT16
  sei();
}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    delay(2000);
    inByte = Serial.read();        
       
    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
    PCMSK2 = 0b00000001;
    
  }
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    //Set power down mode
  sleep_bod_disable();  //disable brown-out detection
  digitalWrite(LED_BUILTIN, LOW); 
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  digitalWrite(LED_BUILTIN, HIGH); 
  delay(1000);
  //int i=Serial.available();
  //Serial.print(i);
  delay(1000);     
  
}

So, by sending one character, the Arduino wakes up, the LED shines, and after the two seconds, Arduino goes back to sleep, never entering the ISR and as a result not setting the flag. Furthermore, having sent one character, if I uncomment the Serial.available() printing, it prints "0"!
If I send two characters, the Arduino wakes up, and the program works fine.

user7508: Your diagnostic about the interrupt handled too fast is correct. When a
byte arrives at the serial port, the start bit will trigger the
interrupt, but the byte is only available for reading once the UART
receives the stop bit, which is about one millisecond later.

to disable/re-enable the pin-change interrupt, the right way seems to
be to use the PCMSK register and not the PCICR.

The canonical procedure for enabling any edge-triggered interrupt is
to first clear the interrupt flag, then set the interrupt enable bit.
Note that the interrupt flag is cleared by writing a logic one to it.
For the PCINT2 interrupt that would be:
PCIFR =  _BV(PCIF2);  // clear interrupt flag
PCICR |= _BV(PCIE2);  // enable interrupt

This being said, there is no point in using a pin change interrupt in
the first place. You can instead use the canonical idiom
if (Serial.available() > 0) {
    char inByte = Serial.read();
    // ...
}

If you plan to sleep, you will likely want to do it with the serial port
enabled, in order for it not to miss the start bit. This means you will
use the IDLE sleep mode. Then, when the serial port receives a full
byte, it will wake up the CPU with its own interrupt, so you do not have
to take care of this yourself.

Edit 1: The simplest way to put the CPU to sleep until the next
interrupt is received is to call sleep_mode() at the end of loop(),
e.g.:
// Sleep until the next character is received.
set_sleep_mode(SLEEP_MODE_IDLE);
if (!Serial.available()) {
    sleep_bod_disable();
    sleep_mode();
}

There is, however, a race condition here: if the interrupt fires after
you test Serial.available() but before going to sleep, you will sleep
instead of handling the received character. The solution to this problem
is to do the test with interrupts disabled and then enable them right
before issuing the sleep instruction, as explained in the
documentation of the avr-libc:
set_sleep_mode(SLEEP_MODE_IDLE);
cli();
if (!Serial.available()) {
    sleep_enable();
    sleep_bod_disable();
    sei();
    sleep_cpu();
    sleep_disable();
}
sei();

Edit 2: answering the questions in the comments.

Pin change interrupt allows you to sleep deeper than IDLE, but if you
do so, the UART will be stopped and it will miss the start bit, which
could throw off its timing. I would rather stick with IDLE and use the
power_*_disable() functions to turn off the unneeded peripherals.

I have a theory, though I don't know if it's valid. Look at the
schematic of the PCINT detection. If the clock is stopped, a
change in the pin level will make the XOR gate switch to 1, which
presumably wakes up the MCU, but that will not be recorded by the
downstream flip-flops, which rely on the clock. If the pin returns to
its original level before the clock restarts (which takes some time when
coming out of PWR_DOWN), then the flip-flops never see the pin change
condition, and the interrupt flag does not rise.


Edit 3: I made a test that confirms that, when waking up from
PWR_DOWN by a pulse-triggered PCINT event, the ISR does not run if
the pulse is too short. The setup involves two Arduinos:

the “tester” Arduino:

sends pulses of various lengths through digital 8 = PB0
forwards on TX the data received on RX


the “DUT” Arduino:

sleeps in PWR_DOWN mode
wakes up by pin change interrupt on digital 8 = PB0 = PCINT0
reports whether the ISR ran on the serial port



The connections are:
DUT   Tester    PC
───────────────────
        USB --- USB
GND --- GND
+5V --- +5V
  8 --- 8
 TX --- RX

The “tester” program:
const uint32_t PULSE_PERIOD = 500;  // pulses every 500 ms

void setup() {
    DDRB |= _BV(PB0);  // digital 8 = PB0 as output
    Serial.begin(9600);
    Serial.println("Tester: ready");
}

void loop() {
    // Forward the serial communication.
    while (Serial.available())
        Serial.write(Serial.read());

    // Periodically send a pulse.
    static uint32_t last_pulse_time;
    if (millis() - last_pulse_time >= PULSE_PERIOD) {
        last_pulse_time += PULSE_PERIOD;

        // Send a pulse of 2^n microseconds.
        static uint8_t n = 0;
        uint16_t length = 1U << n;
        Serial.print("Tester: sending pulse of ");
        Serial.print(length);
        Serial.println(" us");
        Serial.flush();
        uint32_t now = millis();
        while (millis() == now) ;  // wait for the tick
        PORTB |= _BV(PB0);
        delayMicroseconds(length);
        PORTB &= ~_BV(PB0);

        // Next pulse size.
        if (++n >= 16) n = 0;
    }
}

The “DUT” program:
#include <avr/sleep.h>

// The PCINT ISR only sets a flag.
volatile bool isr_ran;
ISR(PCINT0_vect) { isr_ran = true; }

void setup() {
    // Setup interrupt.
    PCMSK0 = _BV(PCINT0);  // sense PCINT0 = PB0
    PCIFR |= _BV(PCIF0);   // clear interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0 interrupt

    // Avoid other interrupts.
    TIMSK0 = 0;         // avoid timer interrupt
    PORTD |= _BV(PD0);  // pull RX high to prevent USART_RX interrupt
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    Serial.begin(9600);
    Serial.println("DUT: ready");
}

void loop() {
    loop_until_bit_is_clear(PINB, PB0);  // wait for LOW input
    Serial.println("DUT: going to sleep");
    Serial.flush();
    isr_ran = false;
    sleep_mode();
    Serial.print("DUT: woke up, ISR ran: ");
    Serial.println(isr_ran ? "YES" : "NO");
}

And the results:
DUT: going to sleep
Tester: sending pulse of 1 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2 us
...
Tester: sending pulse of 1024 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2048 us
DUT: woke up, ISR ran: YES
DUT: going to sleep
Tester: sending pulse of 4096 us
DUT: woke up, ISR ran: YES
...

Conclusion: a pulse of 1024 µs or shorter wakes up the Arduino but
the ISR does not run. If the pulse is 2048 µs or longer, the ISR
does run.

65866: <p>I want to create a simple program, that responds to me sending a character over the Arduino IDE console. I am using an arduino UNO. Here is my program:</p>
<pre><code>volatile bool MeasReceived=false;

ISR(PCINT2_vect){  
  PCICR = 0b00000000;    // turn off port d
  MeasReceived=true;
}

void setup() {    
  Serial.begin(9600);
  Serial.flush();

  Serial.print(&quot;Hello PC&quot;);
  delay(1000);
  cli();      
  PCICR |= 0b00000100;    // turn on port d
  PCMSK2 |= 0b0000001;    // turn on pins PD0 , PCINT16
  sei();


}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    inByte = Serial.read();
     
    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
  }
  PCICR = 0b00000001; // re-enable port d
}
</code></pre>
<p>What I do is that I set the RX pin as a pin change interrupt. After that, I send a character through the console, for example 'A'. The ISR kicks in, firstly disabling the interrupt, and after that, the flag is set true. That way, I enter the part of the code where I do the Serial.read() command, to find what character was sent to me via the console.</p>
<p>The problem is that, no matter the character I send, the result is always 255. That means that the value of inByte, after the Serial.read() is always 255. What goes wrong?</p>
<p><strong>EDIT: Original question answered by me below. However, one interesting thing occured in the new code posted below.</strong> If I put the Arduino to sleep (powerDown Mode), and try to wake it up with the serial interrupt, if I send only one character, then the arduino does wake up, but does not enter the ISR! If I send two characters, then the ISR is accessed and the flags set, with the program working fine. Here is the code, to reproduce the issue:</p>
<pre><code>volatile bool MeasReceived=false;
uint8_t inByte;



ISR(PCINT2_vect){
  PCMSK2 = 0b00000000;    // turn off port d
  MeasReceived=true;
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

 
  Serial.begin(9600);
  Serial.flush();
  Serial.print(&quot;Hello PC&quot;);
  delay(1000);
      
  cli();
  PCICR = 0b00000100;    // turn on port d
  PCMSK2 = 0b00000001;    // turn on pins PD0 , PCINT16
  sei();
}

void loop() {

  if(MeasReceived==true){
    MeasReceived=false;
    delay(2000);
    inByte = Serial.read();        
       
    if(inByte=='A'){   //A: PC requests measurement data from Arduino
       Serial.print('B');
    }
    else{
      Serial.print(inByte);
    }
    PCMSK2 = 0b00000001;
    
  }
  
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    //Set power down mode
  sleep_bod_disable();  //disable brown-out detection
  digitalWrite(LED_BUILTIN, LOW); 
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  digitalWrite(LED_BUILTIN, HIGH); 
  delay(1000);
  //int i=Serial.available();
  //Serial.print(i);
  delay(1000);     
  
}
</code></pre>
<p>So, by sending one character, the Arduino wakes up, the LED shines, and after the two seconds, Arduino goes back to sleep, never entering the ISR and as a result not setting the flag. Furthermore, having sent one character, if I uncomment the Serial.available() printing, it prints &quot;0&quot;!</p>
<p>If I send two characters, the Arduino wakes up, and the program works fine.</p>
 7508: <p>Your diagnostic about the interrupt handled too fast is correct. When a
byte arrives at the serial port, the start bit will trigger the
interrupt, but the byte is only available for reading once the UART
receives the stop bit, which is about one millisecond later.</p>
<blockquote>
<p>to disable/re-enable the pin-change interrupt, the right way seems to
be to use the PCMSK register and not the PCICR.</p>
</blockquote>
<p>The canonical procedure for enabling <em>any</em> edge-triggered interrupt is
to first clear the interrupt flag, then set the interrupt enable bit.
Note that the interrupt flag is cleared by writing a logic one to it.
For the PCINT2 interrupt that would be:</p>
<pre class="lang-cpp prettyprint-override"><code>PCIFR =  _BV(PCIF2);  // clear interrupt flag
PCICR |= _BV(PCIE2);  // enable interrupt
</code></pre>
<p>This being said, there is no point in using a pin change interrupt in
the first place. You can instead use the canonical idiom</p>
<pre class="lang-cpp prettyprint-override"><code>if (Serial.available() &gt; 0) {
    char inByte = Serial.read();
    // ...
}
</code></pre>
<p>If you plan to sleep, you will likely want to do it with the serial port
enabled, in order for it not to miss the start bit. This means you will
use the IDLE sleep mode. Then, when the serial port receives a full
byte, it will wake up the CPU with its own interrupt, so you do not have
to take care of this yourself.</p>
<hr />
<p><strong>Edit 1</strong>: The simplest way to put the CPU to sleep until the next
interrupt is received is to call <code>sleep_mode()</code> at the end of <code>loop()</code>,
e.g.:</p>
<pre class="lang-cpp prettyprint-override"><code>// Sleep until the next character is received.
set_sleep_mode(SLEEP_MODE_IDLE);
if (!Serial.available()) {
    sleep_bod_disable();
    sleep_mode();
}
</code></pre>
<p>There is, however, a race condition here: if the interrupt fires after
you test <code>Serial.available()</code> but before going to sleep, you will sleep
instead of handling the received character. The solution to this problem
is to do the test with interrupts disabled and then enable them right
before issuing the <code>sleep</code> instruction, as explained in the
<a href="https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html" rel="nofollow noreferrer">documentation of the avr-libc</a>:</p>
<pre class="lang-cpp prettyprint-override"><code>set_sleep_mode(SLEEP_MODE_IDLE);
cli();
if (!Serial.available()) {
    sleep_enable();
    sleep_bod_disable();
    sei();
    sleep_cpu();
    sleep_disable();
}
sei();
</code></pre>
<p><strong>Edit 2</strong>: answering the questions in the comments.</p>
<ol>
<li><p>Pin change interrupt allows you to sleep deeper than IDLE, but if you
do so, the UART will be stopped and it will miss the start bit, which
could throw off its timing. I would rather stick with IDLE and use the
<code>power_*_disable()</code> functions to turn off the unneeded peripherals.</p>
</li>
<li><p>I have a theory, though I don't know if it's valid. Look at <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf#G3.1805575" rel="nofollow noreferrer">the
schematic of the PCINT detection</a>. If the clock is stopped, a
change in the pin level will make the XOR gate switch to 1, which
presumably wakes up the MCU, but that will not be recorded by the
downstream flip-flops, which rely on the clock. If the pin returns to
its original level before the clock restarts (which takes some time when
coming out of PWR_DOWN), then the flip-flops never see the pin change
condition, and the interrupt flag does not rise.</p>
</li>
</ol>
<p><strong>Edit 3</strong>: I made a test that confirms that, when waking up from
PWR_DOWN by a pulse-triggered PCINT event, the ISR <em>does not run</em> if
the pulse is too short. The setup involves two Arduinos:</p>
<ul>
<li>the “tester” Arduino:
<ul>
<li>sends pulses of various lengths through digital 8 = PB0</li>
<li>forwards on TX the data received on RX</li>
</ul>
</li>
<li>the “DUT” Arduino:
<ul>
<li>sleeps in PWR_DOWN mode</li>
<li>wakes up by pin change interrupt on digital 8 = PB0 = PCINT0</li>
<li>reports whether the ISR ran on the serial port</li>
</ul>
</li>
</ul>
<p>The connections are:</p>
<pre><code>DUT   Tester    PC
───────────────────
        USB --- USB
GND --- GND
+5V --- +5V
  8 --- 8
 TX --- RX
</code></pre>
<p>The “tester” program:</p>
<pre class="lang-cpp prettyprint-override"><code>const uint32_t PULSE_PERIOD = 500;  // pulses every 500 ms

void setup() {
    DDRB |= _BV(PB0);  // digital 8 = PB0 as output
    Serial.begin(9600);
    Serial.println(&quot;Tester: ready&quot;);
}

void loop() {
    // Forward the serial communication.
    while (Serial.available())
        Serial.write(Serial.read());

    // Periodically send a pulse.
    static uint32_t last_pulse_time;
    if (millis() - last_pulse_time &gt;= PULSE_PERIOD) {
        last_pulse_time += PULSE_PERIOD;

        // Send a pulse of 2^n microseconds.
        static uint8_t n = 0;
        uint16_t length = 1U &lt;&lt; n;
        Serial.print(&quot;Tester: sending pulse of &quot;);
        Serial.print(length);
        Serial.println(&quot; us&quot;);
        Serial.flush();
        uint32_t now = millis();
        while (millis() == now) ;  // wait for the tick
        PORTB |= _BV(PB0);
        delayMicroseconds(length);
        PORTB &amp;= ~_BV(PB0);

        // Next pulse size.
        if (++n &gt;= 16) n = 0;
    }
}
</code></pre>
<p>The “DUT” program:</p>
<pre class="lang-cpp prettyprint-override"><code>#include &lt;avr/sleep.h&gt;

// The PCINT ISR only sets a flag.
volatile bool isr_ran;
ISR(PCINT0_vect) { isr_ran = true; }

void setup() {
    // Setup interrupt.
    PCMSK0 = _BV(PCINT0);  // sense PCINT0 = PB0
    PCIFR |= _BV(PCIF0);   // clear interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0 interrupt

    // Avoid other interrupts.
    TIMSK0 = 0;         // avoid timer interrupt
    PORTD |= _BV(PD0);  // pull RX high to prevent USART_RX interrupt
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    Serial.begin(9600);
    Serial.println(&quot;DUT: ready&quot;);
}

void loop() {
    loop_until_bit_is_clear(PINB, PB0);  // wait for LOW input
    Serial.println(&quot;DUT: going to sleep&quot;);
    Serial.flush();
    isr_ran = false;
    sleep_mode();
    Serial.print(&quot;DUT: woke up, ISR ran: &quot;);
    Serial.println(isr_ran ? &quot;YES&quot; : &quot;NO&quot;);
}
</code></pre>
<p>And the results:</p>
<pre><code>DUT: going to sleep
Tester: sending pulse of 1 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2 us
...
Tester: sending pulse of 1024 us
DUT: woke up, ISR ran: NO
DUT: going to sleep
Tester: sending pulse of 2048 us
DUT: woke up, ISR ran: YES
DUT: going to sleep
Tester: sending pulse of 4096 us
DUT: woke up, ISR ran: YES
...
</code></pre>
<p>Conclusion: a pulse of 1024 µs or shorter wakes up the Arduino but
the ISR does not run. If the pulse is 2048 µs or longer, the ISR
does run.</p>
