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\$ Apr 16, 2014 at 14:18
  • \$\begingroup\$ And another one about programming... stackoverflow.com \$\endgroup\$
    – Kamil
    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\$ 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\$ 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\$
    – gwideman
    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\$ 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\$
    – gwideman
    Apr 17, 2014 at 6:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.