Problem in serial programming in linux

Posted on 2004-04-16
Last Modified: 2008-02-01
I am currently writing a serial module for receiving binary data from a micro-controller board. The micro-controller board uses the setting of 9600baud, 8N1 for transfer. Based on various programming-HOW-TO, i wrote a serial module which can be able to receive data. However, I found that the data received is wrong. The error is that the most significant bit of each byte is always equal to 0. It is ok for transferring ASCII character, but all the binary data are wrong. I tried to debug again and again and i still can't figure out the error. As the deadline of my project comes, i urgently need to fix it.
Thanks a lot in advance. I greatly appreciate any help!

Here are the coding:

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>
#include <qobject.h>
#include <string>
#include <vector>

using namespace std;

class SerialData : public QObject
  SerialData(QObject* parent = 0, const char* name = 0, const char* port = 0);
  enum BaudRateEnum { BAUD_50    = B50,
                  BAUD_75    = B75,
                  BAUD_110   = B110,
                  BAUD_134   = B134,
                  BAUD_200   = B200,
                  BAUD_300   = B300,
                  BAUD_600   = B600,
                  BAUD_1200  = B1200,
                  BAUD_2400  = B2400,
                  BAUD_4800  = B4800,
                  BAUD_9600  = B9600,
                  BAUD_19200 = B19200,
                  BAUD_38400 = B38400 };

  enum ParityEnum { PARITY_7E1, PARITY_8N1 };
  enum FlowControlEnum { HARDWARE, SOFTWARE, NONE };
  static const BaudRateEnum DEFAULT_BAUD_RATE;
  static const ParityEnum DEFAULT_PARITY_MODE;
  static const FlowControlEnum DEFAULT_FLOW;
 public slots:
  void setBaudRate(const BaudRateEnum baudRate);
  void setParity(const ParityEnum parityMode);
  void setFlowControl(const FlowControlEnum flowCtrl);
  void readOp();
  void writeByte(unsigned char byte);
  unsigned char readByte();

  bool checkHwBuffer(); // check serial port hardware buffer

  void openPort(const char* port, const BaudRateEnum baudRate,
            const ParityEnum parityMode, const FlowControlEnum flowCtrl);
  int fd;                   // file descriptor
  int bytes;                // number of bytes available for reading in the port
  struct termios settings;  // serial port settings
   char buffer[256];


#include "serialdata.h"
#include <iostream>

const SerialData::BaudRateEnum SerialData::DEFAULT_BAUD_RATE = BAUD_9600;
const SerialData::ParityEnum SerialData::DEFAULT_PARITY_MODE = PARITY_8N1;
const SerialData::FlowControlEnum SerialData::DEFAULT_FLOW   = NONE;

SerialData::SerialData(QObject* parent, const char* name, const char* port)
  : QObject(parent, name)
  bytes = 0;

// set the baud rate
void SerialData::setBaudRate(const BaudRateEnum baudRate)
  cfsetispeed(&settings, baudRate);
  cfsetospeed(&settings, baudRate);

// set the parity mode (7E1, 8N1)
void SerialData::setParity(const ParityEnum parityMode)
  if (parityMode == PARITY_7E1)
      settings.c_cflag |= PARENB;
      settings.c_cflag &= ~PARODD;
      settings.c_cflag &= ~CSTOPB;
      settings.c_cflag &= ~CSIZE;
      settings.c_cflag |= CS7;
  else if (parityMode == PARITY_8N1)
      settings.c_cflag &= ~PARENB;
      settings.c_cflag &= ~CSTOPB;
      settings.c_cflag &= ~CSIZE;
      settings.c_cflag |= CS8;
  settings.c_iflag |= (INPCK | ISTRIP);

// set flow control mode
void SerialData::setFlowControl(const FlowControlEnum flowCtrl)
  if (flowCtrl == HARDWARE)
      settings.c_cflag |= CRTSCTS;
      settings.c_cflag &= ~(IXON | IXOFF | IXANY);
  else if (flowCtrl == SOFTWARE)
      settings.c_cflag &= ~CRTSCTS;
      settings.c_cflag |= (IXON | IXOFF | IXANY);
  else if (flowCtrl == NONE)
      settings.c_cflag &= ~CRTSCTS;
      settings.c_cflag &= ~(IXON | IXOFF | IXANY);


// check serial port hardware buffer
bool SerialData::checkHwBuffer()
  if (ioctl(fd, FIONREAD, &bytes) == -1)
    cerr << "Error in ioctl" << endl;
  return bytes > 0;

// read int(bytes) to the buffer and store to the messages
void SerialData::readOp()

void SerialData::writeByte(unsigned char byte)
  while (true)
      int byteWrite = write(fd, &byte, 1);
      if (byteWrite == -1)
      cerr << "Error in writing" << endl;
      if (byteWrite == 1)

unsigned char SerialData::readByte()
  unsigned char c;
  while (true)
      int byteRead = 0;
      if (ioctl(fd, FIONREAD, &bytes) == -1)
      cerr << "Error in ioctl" << endl;
      if (bytes > 0)
      byteRead = read(fd, &c, 1);
      if (byteRead == -1)
      cerr << "Error in reading" << endl;
      if (byteRead == 1)
  //cout << c << endl;
  return c;

// open the serial port with inputting port name
void SerialData::openPort(const char* port, const BaudRateEnum baudRate,
                    const ParityEnum parityMode, const FlowControlEnum flowCtrl)
  fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
  if (fd == -1)
    perror("Error in opening the port");
    fcntl(fd, F_SETFL, 0);
  tcgetattr(fd, &settings);
  settings.c_cflag |= CLOCAL | CREAD;
  settings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // set raw data mode
  tcsetattr(fd, TCSANOW, &settings);
Question by:mhcnet
1 Comment
LVL 10

Accepted Solution

Mercantilum earned 125 total points
ID: 10848753
One bit is probably taken by parity, handled by the driver if you chose 7E1 or 7O1 in setParity.
In this case after checking parity the MSb is probably set to 0.
1. Try to change your parity settings.

If using 8N1 parity you still get 7 data bits, encode for writing using Base64 or base128.
The algorithm is easy to implement if you don't have one available.

Featured Post

Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question