5

im just looking for how to send/ write date to pc over serial port from arduino..vice versa.

I have few Question to ask after taking so much time and couldn't figure it out myself. I hope you guys can guid me please.

First, i found i can use Serial.println() function to send some data then, on the pc side, it just checks and reads the port (/dev/tty..). But, how does this process actually work under the hood? So, if you use serial.println() it knows about where to write?

Second i also found it's something to do with UART communication.. But, inside Hardware.cpp file, i couldn't find any function call to the one for UART.

Third there is the code like extern HardwareSerial Serial; Then where is the definition of this Serial?

Fourth There seem to have ring buffer for serial buffer. So, when data is being sent then, what and who fill the data into this buffer inside Hardware.cpp?

please, forgive my silly question.. i'm just so curious about this..

3
  • See chapter 19 of the datasheet.
    – sachleen
    May 4, 2014 at 16:47
  • 2
    Stackexchange sites are for specific, individual questions. Please edit your post to ask a single question which can have a specific answer - preferably one you are left with after reading the documentation. May 4, 2014 at 17:04
  • You might find this interesting about buffers on both sides of a Nano connected to a Raspian system running a Python data logger, using just a regular USB programming cable between the two: arduino.stackexchange.com/questions/11710/…
    – SDsolar
    Aug 24, 2017 at 23:28

2 Answers 2

2

Serial.println knows where to write because Serial is an object. On boards with more than one port there will also be a Serial1,Serial2,etc. Each object corresponds to a port.

The ring buffers are filled from interrupts. When a new byte comes in, it triggers an interrupt that puts the byte in the buffer. When a byte is finished sending it triggers another interrupt that reads the next byte from the buffer and sends it.

Somewhere there is a source file that sets up the UART. It's full of writing special values to registers and low level things like that. I'm not sure what files things are defined in, but if you use the search feature on github there is tons of interesting stuff.

2
  • Thank you for reply. now that i know serial is an object then when does it get initialised ? And, when the interrupts happens, then somehow the code for that interrupt knows about Serial object so that i can play with that ring buffer ?
    – denis_choe
    May 5, 2014 at 2:40
  • While there is an interrupt for "transmit complete," that's not the one most libraries would be using to fill the ring buffer. Instead they'd use the "USART Data Register Empty" interrupt to indicate that you can load a new values in the transmit register, which holds the next byte that will be sent after the USART has finished sending the current byte in the shift register. In other words, the interrupt happens when the MCU starts sending a byte, which may be important in some applications. (Section 24.7.3 of the datasheet.)
    – cjs
    Apr 4, 2017 at 0:36
2

The first question already got a perfectly good answer. I am answering the other ones.

i couldn't find any function call to the one for UART.

There are no "UART functions" in the MCU. The UART is controlled by reading and writing into special registers. These come by names like UCSR0A, UCSR0B, UCSR0C (USART 0 Control and Status Registers A, B and C), UBRR0L, UBRR0H (Low and High bytes of the USART 0 Baud Rate Register) and UDR0 (USART 0 Data Register). These registers are all referenced in HardwareSerial.cpp. You can check the datasheet for their meaning.

where is the definition of this Serial?

In HardwareSerial.cpp, by the end of the file, right after the comment "Preinstantiate Objects".

There seem to have ring buffer for serial buffer. So, when data is being sent then, what and who fill the data into this buffer inside Hardware.cpp?

There are actually two ring buffers: the receive buffer (_rx_buffer) is filled by an interrupt service routine and is emptied by you calling Serial.read(). The transmit buffer (_tx_buffer) is filled by you calling Serial.write(), Serial.print() or Serial.println() (the line _tx_buffer->buffer[_tx_buffer->head] = c; in HardwareSerial::write()), and is emptied by an interrupt service routine.

These interrupt service routines are defined in HardwareSerial.cpp. They start with lines like ISR(SOMETHING_vect). They are triggered by the hardware UART. The transmit ISR is triggered when the UART is ready to accept a new byte to transmit (when it is done transmitting byte n, it starts transmitting byte n+1 and is ready to accept byte n+2 in its TX buffer). The receive ISR is triggered when a new byte has been received.

when does it get initialised?

When you call Serial.begin().

1
  • Note that if the IDE is on a Raspbian, HardwareSerial.cp is located at /usr/share/arduino/hardware/arduino/cores/arduino - go into HardwareSerial.cpp and look at where it detects it has more than 1000 bytes of memory (The Rpi has 2048) and that is where the ring buffer setting is 64. I haven't found any need to expand it, but it can be done.
    – SDsolar
    Aug 22, 2017 at 8:52

Your Answer

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

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