简体   繁体   中英

Serial read write with Baud rate 9600 , parity none, data bits 8 and stop bits 2. Unable to communicate with device

I am working on project which requires to send command in hex with device setting as follows : Baud rate : 9600, Parity : None, Stop bits : 2 , data bits : 8 (9600, 8N2).

I have verified by sending data to device with minicom. I am able to see data on CRO. But when I am sending data via C code and unable to see data on CRO and getting program output as FFFFF always for read function.

Source code for serial read and write :

int32_t Read()
{
   printf("Entering Read function \n");
   int fd;
   fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NDELAY);
   int j=0;

    if (fd == -1)
    {
        perror("open_port: Unable to open /dev/ttyS1\n");
        exit(1);
    }
    else
    {
        printf("Port /dev/ttyS1 opened successfully\n"); 
    }

    //---------- Setting the Attributes of the serial port using termios structure --------- 

        struct termios SerialPortSettings;  // Create the structure                          

        tcgetattr(fd, &SerialPortSettings); // Get the current attributes of the Serial port 

        cfsetispeed(&SerialPortSettings,B9600); // Set Read  Speed as 9600                       
        cfsetospeed(&SerialPortSettings,B9600); // Set Write Speed as 9600                       

        SerialPortSettings.c_cflag &= ~PARENB;   // Disables the Parity Enable bit(PARENB),So No Parity 
        SerialPortSettings.c_cflag &= ~PARODD; // added

        SerialPortSettings.c_cflag |=  CS8;      // Set the data bits = 8    
        SerialPortSettings.c_cflag &= CSTOPB;   // CSTOPB = 2 Stop bits
        SerialPortSettings.c_cflag &= ~CSIZE;    // Clears the mask for setting the data size            


        SerialPortSettings.c_cflag &= ~CRTSCTS;       // No Hardware flow Control                         
        SerialPortSettings.c_cflag |= (CREAD | CLOCAL); // Enable receiver,Ignore Modem Control lines       

        SerialPortSettings.c_lflag =0; /* RAW input */ // added

        SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY);          // Disable XON/XOFF flow control both i/p and o/p 
        SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);  // Non Cannonical mode   

        SerialPortSettings.c_cc[VMIN]  = 0; // added for testing // added 1 sec
        SerialPortSettings.c_cc[VTIME] = 5; // added for testing // added

        SerialPortSettings.c_iflag = 0;            /* SW flow control off, no parity checks etc */ // added

        SerialPortSettings.c_oflag &= ~OPOST;// No Output Processing

        if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure
            printf("\n  ERROR ! in Setting attributes");
        else
                    printf("\n  BaudRate = 9600 \n  StopBits = 2 \n  Parity   = None\n");

     //------------------------------- Write data to serial port -----------------------------

        unsigned char write_buffer[] = {0x28,0x11,0xDF,0xBC};   // Buffer containing characters to write into port       

        int  bytes_written  = 0;    // Value for storing the number of bytes written to the port 

        for(j=0;j<4;j++)
        {
            bytes_written = write(fd,write_buffer[j],sizeof(write_buffer));// use write() to send data to port                                           
                                             // "fd"                   - file descriptor pointing to the opened serial port 
                                            //  "write_buffer"         - address of the buffer containing data              
                                             // "sizeof(write_buffer)" - No of bytes to write  
                                             //
            printf("Byte written : %x\n",write_buffer[j]);                                   
            printf("\n  %d Bytes written to ttyS1", bytes_written);
            printf("\n +----------------------------------+\n\n");

        }

        sleep(2);   

        //------------------------------- Read data from serial port -----------------------------

        tcflush(fd, TCIFLUSH);  //  Discards old data in the rx buffer            

        unsigned char read_buffer[40];  //  Buffer to store the data received              
        int  bytes_read = 0;   //  Number of bytes read by the read() system call 
        int i = 0;


        bytes_read = read(fd,&read_buffer,40); // Read the data                  

        printf("\n\n  Bytes Rxed -%x", bytes_read); // Print the number of bytes read 
        printf("\n\n  ");

        for(i=0;i<bytes_read;i++)    //printing only the received characters
            printf("%x",(int)(*(unsigned char*)(&read_buffer[i])));

        printf("\n +----------------------------------+\n\n\n");

        close(fd); // Close the serial port 



  printf("Exiting Read function \n");   
}   

Output :

Entering Read function 

Port /dev/ttyS1 opened successfully

  BaudRate = 9600 
  StopBits = 2 
  Parity   = None
Byte written : 28

  -1 Bytes written to ttyS1
 +----------------------------------+

Byte written : 11

  -1 Bytes written to ttyS1
 +----------------------------------+

Byte written : df

  -1 Bytes written to ttyS1
 +----------------------------------+

Byte written : bc

  -1 Bytes written to ttyS1
 +----------------------------------+

  Bytes Rxed -ffffffff

 +----------------------------------+
Exiting Read function

1st of all add error checking to this call:

  tcgetattr(fd, &SerialPortSettings); 

like

if (0 > tcgetattr(fd, &SerialPortSettings))
{
  /* log and handle error */ 
}

Then here

  SerialPortSettings.c_cflag |=  CS8;

you set the data bits.

Two lines below you clear it

  SerialPortSettings.c_cflag &= ~CSIZE; 

Do this the other way round.

Also this

  SerialPortSettings.c_cflag &= CSTOPB;

unsets.

If you want to use 2 stop bits set it by doing

  SerialPortSettings.c_cflag |= CSTOPB;

Instead of just doing

  SerialPortSettings.c_oflag &= ~OPOST;

do

  SerialPortSettings.c_oflag = 0;

The code calls write() wrongly. This

   for(j=0;j<4;j++)
   {
     bytes_written = write(fd,write_buffer[j],sizeof(write_buffer));

ought to be

    for(j=0;j<4;j++)
    {
      bytes_written = write(fd, &write_buffer[j], 1)

Or just drop the loop and do

    bytes_written = write(fd, write_buffer, sizeof write_buffer);

The call to read() is wrong as well.

It should be

    bytes_read = read(fd, read_buffer, ...

For some of those mistakes with write and read the compiler should have warned you about.

Please also note that read() and write() return ssize_t not int .


Last not least I doubt flushing the input buffer ( tcflush(fd, TCIFLUSH); ) before reading it makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM