Skip to main content
Added clarification.
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

In response to a comment, I'll just clarify that turning off interrupts just defers the processing of that interrupt until such time as they are turned on again.

In response to a comment, I'll just clarify that turning off interrupts just defers the processing of that interrupt until such time as they are turned on again.

Responded to amended question points.
Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

Would never calling a sleep function and using micros() OR the baudrate affect my time keeping?

A sleep function? What is the purpose of that here?

Unless you disable interrupts, or take other steps (like cancelling Timer 0) then micros will work as it basically returns the contents of the hardware timer (0) plus an overflow count. It would also be reasonably fast. Running the timer itself will cause the occasional interrupt (about every millisecond).

A different baudrate wouldn't affect timing much, except that the interrupts which occur when the sending buffer empties would happen more or less often.

I think micros() and actually transmission uses interrupts. So different baudrates may delay micros() call differently since both needs to disable interrupts?

micros() doesn't use interrupts directly (except as noted below), however the accumulation of timer overflows is done in an interrupt. Note that micros() briefly turns off interrupts in order to obtain the overflow count without it changing during the few clock cycles that it makes a copy of it.

See hardware/arduino/avr/cores/arduino/wiring.c for the actual code in micros() and millis().

Note that because of the way Timer 0 is configured, micros() has a resolution of 4µs. In other words, you won't be able to tell the difference between a 2µs and 3µs interval.


Would never calling a sleep function and using micros() OR the baudrate affect my time keeping?

A sleep function? What is the purpose of that here?

Unless you disable interrupts, or take other steps (like cancelling Timer 0) then micros will work as it basically returns the contents of the hardware timer (0) plus an overflow count. It would also be reasonably fast. Running the timer itself will cause the occasional interrupt (about every millisecond).

A different baudrate wouldn't affect timing much, except that the interrupts which occur when the sending buffer empties would happen more or less often.

I think micros() and actually transmission uses interrupts. So different baudrates may delay micros() call differently since both needs to disable interrupts?

micros() doesn't use interrupts directly (except as noted below), however the accumulation of timer overflows is done in an interrupt. Note that micros() briefly turns off interrupts in order to obtain the overflow count without it changing during the few clock cycles that it makes a copy of it.

See hardware/arduino/avr/cores/arduino/wiring.c for the actual code in micros() and millis().

Note that because of the way Timer 0 is configured, micros() has a resolution of 4µs. In other words, you won't be able to tell the difference between a 2µs and 3µs interval.

Source Link
Nick Gammon
  • 38.9k
  • 13
  • 70
  • 126

I want to send 6 bytes at a time, which takes around ~44 us when I time Serial.write().

You are timing the time it takes for Serial.write to put bytes into an internal buffer (which holds 64 bytes), not the time taken to transmit them. You haven't said what baud rate you are using, but I doubt you are transmitting at 1363652 bits per second.

6 bytes in 44 µs is one byte in 7.3333 µs.
Each byte consists of 10 bits (start bit, 8 data bits, stop bit)
Therefore you are talking about 0.7333 µs per bit.
1/7.333e-6 = 1363652 bits per second.

A quick test shows that it does indeed take 48 µs (on my Uno and my IDE) to put 6 bytes into the serial buffer.

Changing the write to write only one byte improves the time taken from 48 µs to 12 µs so that is less time fiddling with copying data into that buffer.

The actual transmission is done by the hardware, and it fires an interrupt when each byte has been sent, and commences sending the next byte. During the sending of the byte your code is free to continue doing its stuff.

There would be some overhead (I'm not sure the exact amount) for each byte to be pulled from the buffer and sent to the hardware.

I've heard the Serial library processes 16 bits (2 bytes) at a time.

That's nonsense. It would help if you specified what Arduino you have, however.

What happens if I try to send a single byte?

A single byte will get put into the buffer, which will take slightly less time, as I explained above.

If timing is very critical I would be tempted to suggest turning interrupts off, but of course then you can't transmit any bytes at all.

This sounds a lot like an XY problem to me. You are getting bogged down on how long it takes to transmit one byte, but haven't explained:

  • What Arduino you have
  • What baud rate you are using
  • What your code is
  • What is this highly timing-critical thing you are trying to achieve.

As for your question title:

how many bits are actually transmitted at once by UART

One bit would be transmitted "at once" - that's how serial communications work.