liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

UART receive problem

Fri Feb 01, 2013 3:14 pm

I have tested the code for the UART communication from the link below, however I found the receiving is not working.

http://www.raspberry-projects.com/pi/pr ... g-the-uart

It reports UART RX error. It means the rx_length is -1.
Who can help with this?
The sending part is working.

Thank you a lot.

liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

Re: UART receive problem

Fri Feb 01, 2013 4:02 pm

Here is the test instruction, however I found the receive part does not working


Using the UART

If you are running Raspbian or similar then the UART will be used as a serial console. Using a suitable cable, such as the TTL-232R-3V3-WE, you can connect it to your PC and using some simple terminal software set to 115200-8-N-1 use the command line interface to the Raspberry Pi in the same way as if you we're using a keyboard and screen connected to it. However that's no use if you want to use the UART interface for your own application running on the RPi.

Turning off the UART functioning as a serial console

(This is based on Clayton Smiths nifty guide).

Backup the /boot/cmdline.txt file before you edit it just in case of screw-ups:

sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt

Edit the file:

sudo vi /boot/cmdline.txt

Running "2012-09-18-wheezy-raspbian.img" the file contained the following:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Delete and parameters involving the serial port "ttyAMA0", which in this example is:

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

Which gives:

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Press ESC to return to the vi command mode and then type ":wq" (without the quotation marks) to save and exit (even if it appears vi is still in editing mode just type the ":wq" command). If you need to exit without saving type ":q".

You also need to edit this file:


sudo vi /etc/inittab

Search for the serial port usage by typing:

/ttyAMA0/

This should find the line of the file specifying the serial port (if there is one), move the cursor to the start of the line and press "i" to select insert and cursor and then press "#" to comment out the line. Then press ESC and enter ":wq" to save and exit.

Enter "sudo reboot" to restart the pi and now the UART will be available for another process to use it.
Using The UART In Your C Code

(This is based on the example code given here).
Headers required


#include <stdio.h>
#include <unistd.h> //Used for UART
#include <fcntl.h> //Used for UART
#include <termios.h> //Used for UART

Setting Up The UART


//-------------------------
//----- SETUP USART 0 -----
//-------------------------
//At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
int uart0_filestream = -1;

//OPEN THE UART
//The flags (defined in fcntl.h):
// Access modes (use 1 of these):
// O_RDONLY - Open for reading only.
// O_RDWR - Open for reading and writing.
// O_WRONLY - Open for writing only.
//
// O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
// if there is no input immediately available (instead of blocking). Likewise, write requests can also return
// immediately with a failure status if the output can't be written immediately.
//
// O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
uart0_filestream = open("/dev/ttyAMA0", O_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode
if (uart0_filestream == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}

//CONFIGURE THE UART
//The flags (defined in termios.h - see http://pubs.opengroup.org/onlinepubs/00 ... ios.h.html):
// Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
// CSIZE:- CS5, CS6, CS7, CS8
// CLOCAL - Ignore modem status lines
// CREAD - Enable receiver
// IGNPAR = Ignore characters with parity errors
// ICRNL - Map CR to NL on input
// PARENB - Parity enable
// PARODD - Odd parity (else even)
struct termios options;
tcgetattr(uart0_filestream, &options);
cfsetispeed(&options, B9600); //<Set baud rate
cfsetospeed(&options, B9600); //<Set baud rate
options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; //<Set baud rate
options.c_iflag = IGNPAR | ICRNL;
options.c_oflag = 0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);

Transmitting Bytes


//----- TX BYTES -----
unsigned char tx_buffer[20];
unsigned char *p_tx_buffer;

p_tx_buffer = &tx_buffer[0];
*p_tx_buffer++ = 'H';
*p_tx_buffer++ = 'e';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'l';
*p_tx_buffer++ = 'o';

if (uart0_filestream != -1)
{
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
if (count < 0)
{
printf("UART TX error\n");
}
}

Receiving Bytes


//----- CHECK FOR ANY RX BYTES -----
if (uart0_filestream != -1)
{
// Read up to 255 characters from the port if they are there
unsigned char rx_buffer[256];
int rx_length = read(uart0_filestream, (void*)rx_buffer, 255); //Filestream, buffer to store in, number of bytes to read (max)
if (rx_length < 0)
{
//An error occured
printf("UART RX error\n");
}
else if (rx_length == 0)
{
//No data waiting
}
else
{
//Bytes received
rx_buffer[rx_length] = '\0';
printf("%i bytes read : %s\n", rx_length, rx_buffer);
}
}

Closing the UART if no longer needed


//----- CLOSE THE UART -----
close(uart0_filestream);

Using minicom on the UART

Install minicom:

sudo apt-get install minicom

Running minicom:

minicom -b 115200 -o -D /dev/ttyAMA0

To test the UART is working you can simply link the TX and RX pins to each other and verify minicom receives what you type.

User avatar
daveake
Posts: 184
Joined: Thu Jul 12, 2012 12:07 am

Re: UART receive problem

Fri Feb 01, 2013 4:05 pm

Have you connected the port to something? If so do you know that the baud rate etc. in that code match the device you've connected it to? Are you sure that the other device is sending something?

That code simply sends a short message and then looks, once, for some incoming data. To test that the port is working you should short together the Tx and Rx UART pins on the Pi GPIO header. Once you've done that, and run the program, it should display the message that it's sent.

If you've not connected anything to the port, then what you've seen is exactly what you should see.

liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

Re: UART receive problem

Fri Feb 01, 2013 4:33 pm

Hi
Thank you for your reply
I have connected the GND and Vcc 3.3V from GPIO to my TTL-RS232
Also PIN GPIO14 with the TXD and PIN GPIO15 with the RXD are connected to TTL-RS232 also.
I have coneected the mouse and the keyboard also with the screen to the RPi.
However send works and receive does not work, also reports rx_length is -1 and UART error report.
,
daveake wrote:Have you connected the port to something? If so do you know that the baud rate etc. in that code match the device you've connected it to? Are you sure that the other device is sending something?

That code simply sends a short message and then looks, once, for some incoming data. To test that the port is working you should short together the Tx and Rx UART pins on the Pi GPIO header. Once you've done that, and run the program, it should display the message that it's sent.

If you've not connected anything to the port, then what you've seen is exactly what you should see.

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: UART receive problem

Fri Feb 01, 2013 4:36 pm

And there is something at the other end of the TTL-RS232 ? Can you see if the send actually goes through (see the message on the other end)?
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

Re: UART receive problem

Fri Feb 01, 2013 4:38 pm

The sending is 100% works fine. I can see from another laptop which has RS232 itself
-rst- wrote:And there is something at the other end of the TTL-RS232 ? Can you see if the send actually goes through (see the message on the other end)?

User avatar
daveake
Posts: 184
Joined: Thu Jul 12, 2012 12:07 am

Re: UART receive problem

Fri Feb 01, 2013 4:59 pm

Then you need to send something from the PC to the RPi. That code is simply reporting that it sees no data. It's not an error.

If you can, rewrite the code so it sits in a loop waiting for incoming data, and displays it when it sees it.

Dave

User avatar
rurwin
Forum Moderator
Forum Moderator
Posts: 4258
Joined: Mon Jan 09, 2012 3:16 pm
Contact: Website

Re: UART receive problem

Fri Feb 01, 2013 5:06 pm

There is a "bug" in that code... or rather the two parts of it do not hang together well. The UART is opened with O_NDELAY which means that read will return immediately if there is no data already received. Then it does one read for the data and immediately exits. The result is that there is never any data received.

I suggest that to see it working, you remove the |O_NDELAY from the call to open. You will need to give it 255 characters before it returns, because that is the number you asked for in the read call. Later you might want to put |O_NDELAY back and do periodic calls to read to see if any data has been received.

liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

Re: UART receive problem

Fri Feb 01, 2013 5:45 pm

I have tested the loop and continuously, send the data to the port, however still report UART error
daveake wrote:Then you need to send something from the PC to the RPi. That code is simply reporting that it sees no data. It's not an error.

If you can, rewrite the code so it sits in a loop waiting for incoming data, and displays it when it sees it.

Dave

liuluan002
Posts: 6
Joined: Thu Jan 31, 2013 11:43 pm

Re: UART receive problem

Fri Feb 01, 2013 5:47 pm

I have tested the remove the |O_NDELAY, however there are no print the received the code on the screen. At the same time, I got echo from the laptop screen on the other side. Also, the program in the Pi side can not exit automatically.
rurwin wrote:There is a "bug" in that code... or rather the two parts of it do not hang together well. The UART is opened with O_NDELAY which means that read will return immediately if there is no data already received. Then it does one read for the data and immediately exits. The result is that there is never any data received.

I suggest that to see it working, you remove the |O_NDELAY from the call to open. You will need to give it 255 characters before it returns, because that is the number you asked for in the read call. Later you might want to put |O_NDELAY back and do periodic calls to read to see if any data has been received.

thivtulz
Posts: 56
Joined: Tue Dec 18, 2012 10:05 am

Re: UART receive problem

Mon Mar 18, 2013 4:32 am

How to send data from PC to RPi using python code through the UART?Please help me on this.Thanks on advance. :)

pinball
Posts: 4
Joined: Fri Oct 17, 2014 3:12 pm

Re: UART receive problem

Fri Oct 17, 2014 3:20 pm

Hi LiuLuan, I think I have found the answer here:
http://stackoverflow.com/questions/1725 ... tx-are-con

I had the same problem, TX working ok, RX returning -1 for error, looked everywhere can't find any answer...

I see in the SO post two additional parameters are being set that are not in the tutorial:
serial.c_cc[VMIN] = 0; //Minimum number of characters for noncanonical read (MIN)
serial.c_cc[VTIME] = 0; //Timeout in deciseconds for noncanonical read (TIME).

Once I set these (in particular VMIN seems to be the issue) the UART reads >=0 as expected.

Return to “C/C++”