0
\$\begingroup\$

I have this code:

int data=0;

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

void loop(){
    Serial.write(data);
    delay(50);
}

void serialEvent() {
    data = Serial.read();
}

This example should update the data variable when serial data is received. But for some reason it does not work that way, nothing gets printed in the serial monitor.

But when I move the Write method to serialEvent function, I have my data printed as expected. Why is this happening? If I'm correct, the data variable should be printed with the last value I got from Serial.read().

\$\endgroup\$
4
  • 3
    \$\begingroup\$ Just FYI. There is now a stack dedicated to Arduino arduino.stackexchange.com \$\endgroup\$ Commented Apr 16, 2014 at 14:18
  • \$\begingroup\$ And another one about programming... stackoverflow.com \$\endgroup\$ Commented Apr 16, 2014 at 14:30
  • 2
    \$\begingroup\$ @Kamil On average, the folks at Arduino.SE are more versed in Arduino code than the folks on SO or here on EE.SE. \$\endgroup\$ Commented Apr 16, 2014 at 14:54
  • \$\begingroup\$ Agreed. People on SO are more likely to complain about a missing main() than be of actual use. \$\endgroup\$ Commented Apr 16, 2014 at 20:51

1 Answer 1

3
\$\begingroup\$

The compiler sees that you read data each time through the loop, but never update it anywhere that can be directly reached. It therefore has optimized the code such that the initial value of data (0) is used instead of reading the actual value.

You can disable this optimization by declaring the variable volatile. This will force the compiler to generate code that reads the actual value each time instead.

volatile int data=0;
\$\endgroup\$
3
  • \$\begingroup\$ It would be very interesting to see a spelled-out explanation of why the compiler doesn't know that the data variable referenced in serialEvent() is intended to be the same one referenced in the outer context... and why volatile fixes that. (Though I suspect we get further into arduino-specific territory there.) \$\endgroup\$ Commented Apr 17, 2014 at 0:00
  • \$\begingroup\$ It's not so much that the compiler doesn't know that they're the same, it's that the compiler doesn't realize that serialEvent() will be called asynchronously. It's exactly the same thing as, say, Linux kernel code and system calls. Could that be fixed by causing ISR() to disable that sort of optimization? Sure, but not without much more work than just telling the compiler to not optimize via volatile. \$\endgroup\$ Commented Apr 17, 2014 at 0:48
  • \$\begingroup\$ I would buy your line of argument if serialEvent() was called from an ISR. However, it appears to be called from the main loop. \$\endgroup\$ Commented Apr 17, 2014 at 6:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.