0

I am trying to port a program to linux from windows.

The problem is i cannot set the baud rate successfully (code for this can be seen below)

I have set up an oscilloscope on the cable connected to the serial port. with the windows version i can see a pattern at 25micro seconds but with the linux version i can see the same pattern at 250micro seconds telling me that the information is correct but it is sending it to slow.

I have tried setting the baud rate to several different values but i still get the same thing on the oscilloscope.

What i am looking for is a program that will set up the serial port at 115200 baud, mark parity, 1 stopbit and 8 databits and send something across the line so i can see it on hyperterminal. A program in c++ would be fantastic because then i could compare it to mine if it works.

I think there is something keeping the baud rate set at a certain value somehow and if i got a program from someone else that is confirmed to work i could say it is out setup of linux. I have tried on different computers but they are all configured the same way by our sysadmin

I have been trying this for 3 weeks and have done literally hundreds of serial port tutorials and being a linux noob i am lost at what to do now.

    idComDev[i] = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (idComDev[i] == -1)
    {
    perror("open_port: Unable to open /dev/ttyS0 - ");
    ret = false;
    }
    else
    {
    fcntl(idComDev[i], F_SETFL, 0);

    struct termios options;

    tcgetattr(idComDev[i], &options); // get current settings

    cfsetspeed(&options, B9600); // set baud rate

    test = tcsetattr(idComDev[i], TCSANOW, &options);// save the settings

    options.c_cflag &= ~CSIZE; // Mask the character size bits 
    options.c_cflag |= CS8; // 8 bit data           
    options.c_cflag &= ~PARENB; // set parity to no 
    options.c_cflag &= ~PARODD; // set parity to no 
    options.c_cflag |= CSTOPB; //set one stop bit

    options.c_cflag |= (CLOCAL | CREAD);

    options.c_oflag &= ~OPOST;

    options.c_lflag &= 0;
    options.c_iflag &= 0; //disable software flow controll
    options.c_oflag &= 0;

    tcsetattr(idComDev[i], TCSANOW, &options);// save the settings

    printw("Seg %d = COM%hd",i,CommNo[i]);
    if(test!= -1)
    printw("test success");
Skeith
  • 2,512
  • 5
  • 35
  • 57
  • After running your program, could you run `stty -F /dev/ttyS0 -a` and check the settings? That should tell you which of your settings hasn't taken. – Adrian Cox Oct 17 '11 at 10:49
  • @Adrian Cox that command gets "no such file or directory" probably because im in the root directory and cannot seem to move up one :( – Skeith Oct 17 '11 at 11:11
  • I'm not sure what being in the root directory has to do with it. Your code references `/dev/ttyS0`, so I'm puzzled why you can't access `/dev/ttyS0` from the command line. What Linux distribution are you using? – Adrian Cox Oct 17 '11 at 11:18
  • @Adrian Cox centos, and because linux is case sensitive that still gets me here and there sorry. it says that the baud is set to 115200 which is what i want but i am setting it to 9600 atm for testing so or though the termios is claiming success nothing is happening – Skeith Oct 17 '11 at 11:23
  • I'm running out of ideas here. Last things to try: call `tcgetattr` after your final `tcsetattr` and compare with the intended values. Try to change the baud rate with `stty`. Look at the `stty` source (in coreutils) to compare. – Adrian Cox Oct 17 '11 at 11:37
  • Out of interest, what are you trying to communicate with - laboratory devices such as oscilloscopes? – Tom Oct 17 '11 at 12:12
  • @Tom it is a flash memory reader for a custom built device with an in house protocol but right now i am just trying to sent the number 1 from a linux computer to a windows computer so i can prove i can control the serial port – Skeith Oct 17 '11 at 12:17
  • Okay, well if you wanted to try my code I included a link to github in my answer. Your just need the coms_manager library - its only a few short files. But you also need to check you are using the right cable with the correct handshaking pins. I have had to make my own cable to communicate between windows and Linux boxes before. – Tom Oct 17 '11 at 12:28

4 Answers4

1

So, I know this question was posted a long time ago, but I think you have your stop bit backwards. If you want to set one stop bit, you have to do this:

options.c_cflag &= ~CSTOPB; //set one stop bit

Not this (what you had):

options.c_cflag |= CSTOPB; //This sets stop bits to 2, since 1 is the default.

My source: http://www.easysw.com/~mike/serial/serial.html

gitarooLegend
  • 11
  • 2
  • 2
  • The project was scrapped and another way was found but the answer is appreciated. – Skeith Aug 13 '12 at 09:35
  • gitarooLegend: Your link now leads to an eCigarette distributor. @Skeith: it may still be worth marking an answer as "accepted". – Kyle Strand Mar 24 '15 at 17:39
1

If you want to port a windows serial port program to linux, I suggest you migrate first to Boost.Asio library - this includes a cross platform interface to your serial port. You can get this working under Windows and then know that the code will work on Linux.

The reason for this is that there can be other than software issues when moving from windows to linux serial ports. For example, the handshaking protocol (RTS/CTS, DTE/DSE) can vary between the two.

For a start with this, have a look at my answer here. If you want the full source code then take a look at github.

Also, this question catologues various serial sniffers, that can help determine exactly what is going on.

Community
  • 1
  • 1
Tom
  • 5,219
  • 2
  • 29
  • 45
0

How about the standard tool setserial. You can set the device parameters with it (in-/output can then be done via the device file). The source code is available, so you can check out how it is implemented.

flolo
  • 15,148
  • 4
  • 32
  • 57
  • I tried this and commented out the baud rate code in my program so it would not interfere and got the same thing :( – Skeith Oct 17 '11 at 09:29
  • @Skeith: one thing that I see is, that you did NOT check the return code of tcsetattr. Maybe you should check that, to see if/what goes wrong (attention: (I cite the man page for tcsetattr): ` Note that tcsetattr() returns success if any of the requested changes could be successfully carried out. Therefore, when making multiple changes it may be necessary to follow this call with a further call to tcgetattr() to check that all changes have been performed successfully`). – flolo Oct 17 '11 at 09:44
  • modified the code to what it is shown in my post like you said and it claims success but is still not working ? – Skeith Oct 17 '11 at 10:22
0

You could try :

getty ttyS0 115200 vt100

and see if a login prompt appears on your windows. Once you have this working for the default baudrate, try changing the baudrate.

getty ttyS0 9600 vt100

And see if it still works. You probably need to be root to do such a thing however. Could you also remove the fcntl call ?

shodanex
  • 14,975
  • 11
  • 57
  • 91