McGregor80
Posts: 40
Joined: Wed Feb 20, 2013 10:35 am

Uart problem on Baudrates higher than 38400

Mon Jun 03, 2013 10:03 am

Hi

Can someone tell me why i can't successfully use baud-rates higher that 38400?
I have Docklight (uart sniffer) connected to the uart GPIO 14 &15 at Raspberry Pi B v2 with Raspbian on it.
Everything works fine on 9600, 19200, 38400.
When i try exactly the same test at 57600 i just get everything wrong. The number of received characters seems to be correct but not the characters itself.

This is my initialization which i use to choose baudrate. Maybe a bit messy but it was done by try and error.

Code: Select all

uart0_filestream=open("/dev/ttyAMA0",O_RDWR | O_NOCTTY | O_NONBLOCK);
if(uart0_filestream==-1)
	{
	printf("Error with opening UART \n");
	return -1;	
	}
else printf("UART opening OK \n");	

tcgetattr(uart0_filestream, &options);


switch(BaudRate)
	{
	case 0:
		{
		cfsetispeed(&options,B9600);
		cfsetospeed(&options,B9600);
		break;
		}
	case 1:
		{
		cfsetispeed(&options,B19200);
		cfsetospeed(&options,B19200);
		break;
		}
	case 2:
		{
		cfsetispeed(&options,B38400);
		cfsetospeed(&options,B38400);
		break;
		}	
	case 3:
		{
		cfsetispeed(&options,B57600);
		cfsetospeed(&options,B57600);
		break;
		}	
	case 4:
		{
		cfsetispeed(&options,B115200);
		cfsetospeed(&options,B115200);
		break;
		}	
	case 5:
		{
		cfsetispeed(&options,B230400);
		cfsetospeed(&options,B230400);
		break;
		}	
	case 6:
		{
		cfsetispeed(&options,B460800);
		cfsetospeed(&options,B460800);
		break;
		}	
	case 7:
		{
		cfsetispeed(&options,B460800);
		cfsetospeed(&options,B460800);
		break;
		}	
	default:
		{
		cfsetispeed(&options,B921600);
		cfsetospeed(&options,B921600);
		
		break;
		}
	}

options.c_cflag&=~(CS8|PARENB|PARODD|CLOCAL|CREAD|IXON);
options.c_cflag|=(CS8|PARENB|PARODD|CLOCAL|CREAD|IGNPAR|INPCK|ISTRIP|ICRNL);
options.c_iflag&=~IXON;
options.c_iflag&=~INLCR;
options.c_iflag&=~ICRNL;
options.c_oflag=0;
options.c_lflag=0;
tcflush(uart0_filestream, TCIFLUSH);
tcsetattr(uart0_filestream, TCSANOW, &options);
tcgetattr(uart0_filestream, &options);
tcsetattr(uart0_filestream, TCSANOW, &options);
fcntl(uart0_filestream, F_SETFL,O_NDELAY);


Here is the function i use to send messages:

Code: Select all

int a = write(uart0_filestream, StartOfTheMessage, Length);
	if (a < 0) 	{
			perror("Write failed - ");
			ERROR();
			return -1;
			}
tcdrain(uart0_filestream);

The only thing i suspect is that the UART clock is not correct.
But this is only guess.

Thanks for help.

McGregor80
Posts: 40
Joined: Wed Feb 20, 2013 10:35 am

Re: Uart problem on Baudrates higher than 38400

Tue Jun 18, 2013 1:52 pm

I started to diagnose the problem a bit more precisely:
1. When i place jumper between TX and RX pin i receive exactly the same message i send. No garbage.

2. I connected an oscilloscope to the TX pin of raspberry PI and the diagnosed that the baudrate is changing is correct for 9600, 19200 and 38400 further it's not changing

finally i noticed that the problem is in the termios.h library

It doesn't support anything higher than 38400
The input and output baud rates are stored in the termios structure. These are the valid values for objects of type speed_t. The following values are defined, but not all baud rates need be supported by the underlying hardware.

B0
Hang up
B50
50 baud
B75
75 baud
B110
110 baud
B134
134.5 baud
B150
150 baud
B200
200 baud
B300
300 baud
B600
600 baud
B1200
1200 baud
B1800
1800 baud
B2400
2400 baud
B4800
4800 baud
B9600
9600 baud
B19200
19200 baud
B38400
38400 baud
Does anyone knows how to get higher baudrates?
Thanks

McGregor80
Posts: 40
Joined: Wed Feb 20, 2013 10:35 am

Re: Uart problem on Baudrates higher than 38400

Wed Jun 19, 2013 6:10 pm

For all of you who encounter same problem i just write the solution which worked for me.
I'm not sure if this was because of my low programming skills but this code didn't work correctly:

Code: Select all

cfsetispeed(&options,B57600);
      cfsetospeed(&options,B57600);
However if i did like this:

Code: Select all

tcgetattr(uart0_filestream, &options);
options.c_cflag=B57600;
tcsetattr(uart0_filestream, TCSANOW, &options);
...and the rest of the settings
it worked fine on both 57600 and 115200.
It didn't go any higher but that's enough for my needs.

Thanks for help

User avatar
jojopi
Posts: 3232
Joined: Tue Oct 11, 2011 8:38 pm

Re: Uart problem on Baudrates higher than 38400

Wed Jun 19, 2013 8:52 pm

The problem in your original code is that you are putting some input modes in the c_cflag field instead of c_iflag. This has the effect of setting the historical speed bits. Once a speed is set in c_cflag, the modern fields for separate input and output speed accessed by cf[gs]et[io]speed are ignored.

Your method of setting the number of data bits is not strictly correct either. You should mask off CSIZE before setting CS8, in case the latter has any bits clear that are set in other sizes.

Code: Select all

  cfsetispeed(&options, B115200);
  cfsetospeed(&options, B115200);
  options.c_cflag &= ~(CSIZE|CSTOPB|HUPCL);
  options.c_cflag |= (CS8|PARENB|PARODD|CLOCAL|CREAD);
  options.c_iflag &= ~(IXON|IXOFF|IXANY|INLCR|IGNBRK|BRKINT|PARMRK|INLCR|IGNCR);
  options.c_iflag |= (IGNPAR|INPCK|ISTRIP|ICRNL);
  options.c_oflag &= ~OPOST;
  options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);

McGregor80
Posts: 40
Joined: Wed Feb 20, 2013 10:35 am

Re: Uart problem on Baudrates higher than 38400

Thu Jun 20, 2013 9:13 pm

Thank you jojopi.

I must have been blind when i read termios.h description.

Return to “C/C++”