COM포트로 들어오는 데이터를 파일에 쓰기...

leolo의 이미지

리눅스에서 COM포트로 들어오는 데이터를
파일로 쓰고 싶습니다.
COM포트에는 데이터를 받기위한 장비가 설치되어있습니다.
이 경우 open하고 select하면 될꺼 같은데.
보낸 데이터와 받은 데이터가 다릅니다.

com = open("/dev/ttyS1", O_RDONLY);

while(1){

FD_ZERO(&rfd);
FD_SET(com, &rfd);
select(maxfd+1, &rfd, NULL, NULL, (struct timeval*)0);

if(FD_ISSET(com, &rfd)){
    file write....
}
}

대충 이렇게 하니까.. 보낸 데이터와 파일에 써지는 데이터가 다릅니다.
써지는 데이터가 순서가 다르게 라이트 되네요...
원인이 무엇인지 알고 싶습니다.
[/code]
익명 사용자의 이미지

소스 올립니다.
baud는
매크로로 이미 정의되어 있는게 있습니다.

/usr/include/termios.h 에
B9600, B19200 같은식으로 헤더에 있습니다.
더 많은 정보가 termios.h에 친절하게도 잘 되어 있네요.
주석 없어도 한눈에 보이니까 걱정 마시고 한번 보시면 좋을듯 합니다.

이건 제가 쓰는 용도가 고정되어 이렇게 쓰는것뿐이고
더 많은 기능을 알아보세요.

/*
 Copyright (c) 2002 Information Equipment co.,LTD.
 All Right Reserved.

 Code by JaeHyuk Cho <minzkn@infoeq.co.kr> 
*/

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/time.h>

int MZ_OpenSerial(void *s_DeviceName, int s_Baud);
int MZ_CloseSerial(int s_Handle);
int MZ_RecvSerial(int s_Handle, void *s_Buffer, int s_Length, int s_Timeout_Sec, int s_Timeout_uSec);
int MZ_SendSerial(int s_Handle, void *s_Buffer, int s_Length, int s_Timeout_Sec, int s_Timeout_uSec);

int MZ_OpenSerial(void *s_DeviceName, int s_Baud)
{
 int s_Return = (-1);
 if(s_DeviceName == (void *)0)s_DeviceName = "/dev/ttyS0";
 s_Return = open((char *)s_DeviceName, O_RDWR | O_NOCTTY | O_NONBLOCK, 0644);
 if(s_Return >= 0)
 {
  struct termios s_Termios;
  int s_Count;
  if(tcgetattr(s_Return, &s_Termios) == 0)
  {
   s_Termios.c_iflag     = IGNBRK | IGNPAR;
   s_Termios.c_oflag     = 0;
   s_Termios.c_cflag     = CS8 | CLOCAL;
   s_Termios.c_lflag     = 0;
   for(s_Count = 0;s_Count < NCCS;s_Count++)s_Termios.c_cc[s_Count] = 0;
   s_Termios.c_cc[VMIN]  = 1;
   s_Termios.c_cc[VTIME] = 0;
   if((cfsetispeed(&s_Termios, s_Baud) < 0) || (cfsetispeed(&s_Termios, s_Baud) < 0))
   {
    close(s_Return);
    s_Return = (-1);
    fprintf(stderr, "%s: %s - [ERROR] Can not set speed !!!\n", __FILE__, __FUNCTION__);
   }
   else
   {
    if(tcsetattr(s_Return, TCSANOW, &s_Termios) < 0)
    {
     close(s_Return);
     s_Return = (-1);
     fprintf(stderr, "%s: %s - [ERROR] Can not set attr !!!\n", __FILE__, __FUNCTION__);
    }
    else
    {
     if(tcflush(s_Return, TCIOFLUSH) < 0)
     {
      close(s_Return);
      s_Return = (-1);
      fprintf(stderr, "%s: %s - [ERROR] Can not flush tcio !!!\n", __FILE__, __FUNCTION__);
     }
    } 
   }
  }
  else 
  {
   close(s_Return);
   s_Return = (-1);   
   fprintf(stderr, "%s: %s - [ERROR] Can not get termios structure !!!\n", __FILE__, __FUNCTION__);
  }
 }
 else fprintf(stderr, "%s: %s - [ERROR] Can not open serial device \"%s\" !!!\n", __FILE__, __FUNCTION__, (char *)s_DeviceName);
 return(s_Return); 
}

int MZ_CloseSerial(int s_Handle)
{
 if(s_Handle >= 0)close(s_Handle);
 s_Handle = (-1); 
 return(s_Handle);
}

int MZ_RecvSerial(int s_Handle, void *s_Buffer, int s_Length, int s_Timeout_Sec, int s_Timeout_uSec)
{
 int s_Return = (-1);	
 struct timeval s_TimeVal;
 fd_set s_fdread;    
 int s_IsSelect, s_IsFDRead, s_RecvSize;
 if(s_Handle >= 0)
 {
  if(s_Buffer)
  {
   if(s_Length > 0)
   {
    do
    {
     FD_ZERO(&s_fdread);
     FD_SET(s_Handle, &s_fdread);
     s_TimeVal.tv_sec  = (s_Timeout_Sec >= 0 ? s_Timeout_Sec : 1);
     s_TimeVal.tv_usec = (s_Timeout_uSec >= 0 ? s_Timeout_uSec : 1);
     s_IsSelect = select(s_Handle + 1, &s_fdread, (fd_set *)0, (fd_set *)0, &s_TimeVal);
     s_IsFDRead = FD_ISSET(s_Handle, &s_fdread);
     if(s_IsSelect > 0 && s_IsFDRead != 0)
     {
      if(s_Return < 0)s_Return = 0;	     
      s_RecvSize = read(s_Handle, (void *)(((char *)s_Buffer) + s_Return), s_Length);
      if(s_RecvSize > 0)
      {
       s_Return += s_RecvSize;
       s_Length -= s_RecvSize;
      }
      else 
      {
       if(s_RecvSize < 0)fprintf(stderr, "%s: %s - [ERROR] Serial error !!!\n", __FILE__, __FUNCTION__);
       break; 
      }
     }
     else break; 
    }while(s_Length > 0);
   }
   else fprintf(stderr, "%s: %s - [ERROR] s_Length <= 0 !!!\n", __FILE__, __FUNCTION__); 
  }
  else fprintf(stderr, "%s: %s - [ERROR] s_Buffer is null !!!\n", __FILE__, __FUNCTION__); 
 }
 else fprintf(stderr, "%s: %s - [ERROR] s_Handle < 0 !!!\n", __FILE__, __FUNCTION__); 
 return(s_Return);
} 

int MZ_SendSerial(int s_Handle, void *s_Buffer, int s_Length, int s_Timeout_Sec, int s_Timeout_uSec)
{
 int s_Return = (-1);	
 int s_SendSize;
 (void)s_Timeout_Sec, (void)s_Timeout_uSec;
 if(s_Handle >= 0)
 {
  if(s_Buffer)
  {
   if(s_Length > 0)
   {
    do
    {
     if(s_Return < 0)s_Return = 0;	    
     s_SendSize = write(s_Handle, (void *)(((char *)s_Buffer) + s_Return), s_Length);
     if(s_SendSize > 0)
     {
      s_Return += s_SendSize;
      s_Length -= s_SendSize;
     }
     else 
     {
      if(s_SendSize < 0)fprintf(stderr, "%s: %s - [ERROR] Serial error !!!\n", __FILE__, __FUNCTION__);
      break; 
     }
    }while(s_Length > 0);
   }
   else fprintf(stderr, "%s: %s - [ERROR] s_Length <= 0 !!!\n", __FILE__, __FUNCTION__); 
  }
  else fprintf(stderr, "%s: %s - [ERROR] s_Buffer is null !!!\n", __FILE__, __FUNCTION__); 
 }
 else fprintf(stderr, "%s: %s - [ERROR] s_Handle < 0 !!!\n", __FILE__, __FUNCTION__); 
 return(s_Return);
} 

/* End of source */ 
mach의 이미지

leolo wrote:
리눅스에서 COM포트로 들어오는 데이터를
파일로 쓰고 싶습니다.
COM포트에는 데이터를 받기위한 장비가 설치되어있습니다.
이 경우 open하고 select하면 될꺼 같은데.

com 포트, 유닉스 개념상 파일이지요. 파일일지라도 com포트는 단지 open하고 select해서는 안됩니다. 원격지와 통신(IO)하기위해 특별한 조작을 해주어야합니다. 조작은 통신속도, 패리티등인데요. 이 파라메터가 원격지와 일치해야 원하는 값을 가지고 통신할 수 있습니다.
조작하는 방법은 ioctl()을 사용하며, ioctl()에 넣어주는 파라메터는 운영체제별로 다 틀립니다.
이때 파라메터를 맞추는 방법은, 리눅스쪽에서 통신하는 장비쪽으로 스펙 맞추는것이 일반적인 방법입니다. 장비의 능력에 맞춘다고나 할까요?
그리고, 세팅하는 방법의 실질적인 한가지 사례는 minzkn님의 예가 있군요 8)

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

leolo의 이미지

제가 참 어리석었군요..
ㅎㅎ

그럼 한가지 더 질문 드릴께요..
c_cflag 세팅을 해야하는데요..
이 경우 어떻게 하죠..

9600bps, 8 data-bits, Non parity, 1 stop-bit, H/W flow control을
세팅하고 싶은데 어떻게 하죠..

이렇게 하면 되나요..
#define BAUDRATE B9600
newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
이렇게 하면 되나요..

또, 9600bps, 8 data-bits, Non parity, 1 stop-bit, NO flow control을
세팅하고 싶은데 어떻게 하죠..

이렇게 하면 되나요..
#define BAUDRATE B9600
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
newtio.c_cflag &= ~CRTSCTS
이렇게 하면 되나요..

실력이 있으면 삶이 편하다... 영차 영차...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.