使用C语言从Linux中的串口读取

时间:2016-05-08 10:36:44

标签: c linux serial-port

我是使用C语言在Linux(Fedora 12)中进行serail编程的新手。我有一个简单的设备,它应该以十六进制(wirte)获得3字节命令,如{0x02,0x03,0x0D}并返回4字节响应。

首先我在windows上写了一个简单的java程序,我得到了正确的响应..当我切换到linux时,我无法从串口com端口读取,既不使用java也不使用C语言。

我尝试使用像rs232这样的库..但问题仍然存在。 我可以打开“/ dev / ttyS0”,并在上面写... ..(它们都没有返回任何错误),但是读取是不可能的..

如果我使用规范模式,程序将暂停读取,直到我终止程序。如果使用非规范模式,VMIN = 0且VTIME = 5,则读取函数返回-107725432字节,例如.. (我曾尝试逐字节或同时读取和写入..没有区别..)

rs232.c

#include "rs232.h"

int Cport[6],
    error;

struct termios new_port_settings,
       old_port_settings[6];

char comports[6][16]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2","/dev/ttyS3","/dev/ttyS4","/dev/ttyS5"};

int RS232_OpenComport(int comport_number, int baudrate, const char *mode)
{
  int baudr,
      status;

  if((comport_number>5)||(comport_number<0))
  {
    printf("illegal comport number\n");
    return(1);
  }

  switch(baudrate)
  {
    case    2400 : baudr = B2400;
                   break;
    case    4800 : baudr = B4800;
                   break;
    case    9600 : baudr = B9600;
                   break;
    case   19200 : baudr = B19200;
                   break;

    default      : printf("invalid baudrate\n");
                   return(1);
                   break;
  }

  int cbits=CS8,
      cpar=0,
      ipar=IGNPAR,
      bstop=0;

  if(strlen(mode) != 3)
  {
    printf("invalid mode \"%s\"\n", mode);
    return(1);
  }

  switch(mode[0])
  {
    case '8': cbits = CS8;
              break;
    case '7': cbits = CS7;
              break;
    case '6': cbits = CS6;
              break;
    case '5': cbits = CS5;
              break;
    default : printf("invalid number of data-bits '%c'\n", mode[0]);
              return(1);
              break;
  }

  switch(mode[1])
  {
    case 'N':
    case 'n': cpar = 0;
              ipar = IGNPAR;
              break;
    case 'E':
    case 'e': cpar = PARENB;
              ipar = INPCK;
              break;
    case 'O':
    case 'o': cpar = (PARENB | PARODD);
              ipar = INPCK;
              break;
    default : printf("invalid parity '%c'\n", mode[1]);
              return(1);
              break;
  }

  switch(mode[2])
  {
    case '1': bstop = 0;
              break;
    case '2': bstop = CSTOPB;
              break;
    default : printf("invalid number of stop bits '%c'\n", mode[2]);
              return(1);
              break;
  }


  Cport[comport_number] = open(comports[comport_number], O_RDWR | O_NOCTTY);
  if(Cport[comport_number]==-1)
  {
    perror("unable to open comport ");
    return(1);
  }

  /* lock access so that another process can't also use the port */
  if(flock(Cport[comport_number], LOCK_EX | LOCK_NB) != 0)
  {
    close(Cport[comport_number]);
    perror("Another process has locked the comport.");
    return(1);
  }

  error = tcgetattr(Cport[comport_number], old_port_settings + comport_number);
  if(error==-1)
  {
    close(Cport[comport_number]);
    perror("unable to read portsettings ");
    return(1);
  }
  memset(&new_port_settings, 0, sizeof(new_port_settings));  /* clear the new struct */

  new_port_settings.c_cflag = cbits | cpar | bstop | CLOCAL | CREAD;
  new_port_settings.c_iflag = ipar;
  new_port_settings.c_oflag = 0;
  new_port_settings.c_lflag = 0;
  new_port_settings.c_cc[VMIN] = 0;      /* block untill n bytes are received */
  new_port_settings.c_cc[VTIME] = 5;     /* block untill a timer expires (n * 100 mSec.) */

  cfsetispeed(&new_port_settings, baudr);
  cfsetospeed(&new_port_settings, baudr);

  error = tcsetattr(Cport[comport_number], TCSANOW, &new_port_settings);
  if(error==-1)
  {
    close(Cport[comport_number]);
    perror("unable to adjust portsettings ");
    return(1);
  }

  if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
  {
    perror("unable to get portstatus");
    return(1);
  }

  status |= TIOCM_DTR;    /* turn on DTR */
  status |= TIOCM_RTS;    /* turn on RTS */

  if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
  {
    perror("unable to set portstatus");
    return(1);
  }

  return(0);
}


int RS232_PollComport(int comport_number, unsigned char *buf, int size)
{
  int n;

  n = read(Cport[comport_number], buf, size);

  return(n);
}

int RS232_SendBuf(int comport_number, unsigned char *buf, int size)
{
  return(write(Cport[comport_number], buf, size));
}


void RS232_CloseComport(int comport_number)
{
  int status;

  if(ioctl(Cport[comport_number], TIOCMGET, &status) == -1)
  {
    perror("unable to get portstatus");
  }

  status &= ~TIOCM_DTR;    /* turn off DTR */
  status &= ~TIOCM_RTS;    /* turn off RTS */

  if(ioctl(Cport[comport_number], TIOCMSET, &status) == -1)
  {
    perror("unable to set portstatus");
  }

  tcsetattr(Cport[comport_number], TCSANOW, old_port_settings + comport_number);
  close(Cport[comport_number]);

  flock(Cport[comport_number], LOCK_UN); /* free the port so that others can use it. */
}


 void RS232_flushRXTX(int comport_number)
{
  tcflush(Cport[comport_number], TCIOFLUSH);
}

的main.c

    #include <stdlib.h>
    #include <stdio.h>  
    #include <unistd.h>          
    #include "rs232.h"

    int main()
    {
        int  cport_nr=0,   bdrate=9600;     /* 9600 baud */

        char mode[]={'8','N','1',0},
        str[512];

        unsigned char buf[6000];
        memset(buf, '\0' , 6000);
        int buf_SIZE=sizeof(buf);

        if(RS232_OpenComport(cport_nr, bdrate, mode))
        {
           printf("Can not open comport\n");

           return(0);
        }
        unsigned char wr_buff[5];
        memset(wr_buff, '\0', 5);
        wr_buff[0] = 0x02;
        wr_buff[1] = 0x01;
        wr_buff[2] = 0x0D;

        int cnt = RS232_SendBuf(cport_nr, wr_buff, 3);

        printf("Number of bytes that has been written: %d\n",cnt);

        if (cnt <= 0 )
            return(-1);
        cnt =0 ;

        usleep(100000);
        printf("Start Reading ... \n");


        int i = 0;
        do {
        cnt = RS232_PollComport(cport_nr,(buf+i), 1);
        i++;}
        while(cnt>0);

        printf ("%d bytes have been read\n");

        RS232_CloseComport(cport_nr);

return (1);
}

我真的很困惑..我几乎尝试了互联网上的每一个样本..一个

你的想法好吗?! 我已经使用strace跟踪了该程序。

  

...

     

写(3,“\ 2 \ 3 \ r”,3)= 3

     

fstat64(1,{st_mode = S_IFREG | 0755,st_size = 0,..})= 0

     

mmap2(NULL,4096,PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS,-1,0)= 0Xb78b4000

     

nanosleep({0,1000000},NULL)= 0

     

读(3,“”,1)= 0

     

.....

问题可能与fedora12有关吗?

P.S。 :如果我在Windows中没有响应,我确信它是设备的问题。

1 个答案:

答案 0 :(得分:0)

解决了......

这是我的错... 事实上,每件事都没问题, 问题在于我打印的字节数已被读取。我忘记了放置&#34; cnt&#34;关于%d ......

  

printf(&#34;%d字节已被读取\ n&#34;); - &GT; printf(&#34;%d字节已被读取\ n&#34;,cnt);

根据与我的设备通信的协议,我应该只读取4个字节..