2012-02-18 2 views
7

나는이 질문이 인터넷에 흩어져 있다는 것을 알고있다. 나는 프로펠러 보드를 위해 C++ (리눅스)의 시리얼 포트에 데이터를 쓰고 싶다. 프로그램은 콘솔에서 입력을 가져올 때 잘 작동하지만 문자열을 쓸 때는 항상 장치에서 ERROR - Invalid command을 반환합니다. 나는 16 진수 값을 가지고 char 배열을 만들려고 시도했다. 아래에 작업 코드가 있습니다. 하지만 어떻게 명령 문자열 변수를 제공하고 직렬 포트로 보낼 수 있습니까? 아마도, 유일한 방법이라면 어떻게 그것을 16 진수 값으로 변환합니까? 모두에게 감사합니다C++ 리눅스에서 직렬 포트에 문자열을 쓰는 것

참고 : 루프는 콘솔에서 사용자 입력을 사용합니다. 직렬 포트에 문자열 변수를 보내는 방법이 필요합니다.

#include <string.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <termios.h> 

int main(int argc,char** argv){ 
    struct termios tio; 
    struct termios stdio; 
    int tty_fd; 
    fd_set rdset; 

    unsigned char c='D'; 

    printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]); 
    memset(&stdio,0,sizeof(stdio)); 
    stdio.c_iflag=0; 
    stdio.c_oflag=0; 
    stdio.c_cflag=0; 
    stdio.c_lflag=0; 
    stdio.c_cc[VMIN]=1; 
    stdio.c_cc[VTIME]=0; 
    tcsetattr(STDOUT_FILENO,TCSANOW,&stdio); 
    tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio); 
    fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);  // make the reads non-blocking 

    memset(&tio,0,sizeof(tio)); 
    tio.c_iflag=0; 
    tio.c_oflag=0; 
    tio.c_cflag=CS8|CREAD|CLOCAL;   // 8n1, see termios.h for more information 
    tio.c_lflag=0; 
    tio.c_cc[VMIN]=1; 
    tio.c_cc[VTIME]=5; 

    tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);  
    cfsetospeed(&tio,B115200);   // 115200 baud 
    cfsetispeed(&tio,B115200);   // 115200 baud 

    tcsetattr(tty_fd,TCSANOW,&tio); 

    //char str[] = {'V','E','R','\r'}; 
    //the above str[] doesn't work although it's exactly the same as the following 
    char str[] = {0x56, 0x45, 0x52, 0x0D}; 
    write(tty_fd,str,strlen(str)); 
    if (read(tty_fd,&c,1)>0) 
     write(STDOUT_FILENO,&c,1); 

    while (c!='q') 
    { 
      if (read(tty_fd,&c,1)>0)  write(STDOUT_FILENO,&c,1); // if new data is available on the serial port, print it out 
      if (read(STDIN_FILENO,&c,1)>0) 
       if(c!='q') 
        write(tty_fd,&c,1);  // if new data is available on the console, send it to the serial port 
    } 

    close(tty_fd); 
} 
+0

C 또는 C++입니까? C++의 경우'std :: string'을 사용하지 않으시겠습니까? –

+0

@BasileStarynkevitch : 나는 그것을 시도했다 :'std :: string str = "VER \ r"; write (tty_fd, str.data(), str.size()); 여전히 오류가 반환됩니다. 나는 여러 가지 방법을 시도했지만 그 16 진수 만 작동합니다. 너는 어떤 생각이있어? 코드는 C에서 왔지만 내 프로그램은 실제로 C++입니다. –

+1

오류가 실제로 무엇을 말하는지 나에게 말 했니? –

답변

9

나는 내 자신의 해결책을 풀어서 기뻐하지만, 사소한 일을 훨씬 더 빨리 보지 못해서 실망했다. char은 기본적으로 signed이고 범위는 -128에서 127 사이입니다. 그러나 0에서 255까지의 ASCII 값이 필요합니다. 따라서이 값을 unsigned char str[]으로 선언하면 간단합니다. 어리석은 나, 어리석은 나.

여전히 나를 도와 준 모든 분들께 감사드립니다.

+0

이미 가지고 있습니다 : D –

2

'\ r'으로 끝내시겠습니까? 콘솔에서 텍스트를 입력 할 때 리턴 키는 '\ r'이 아닌 '\ n'문자가됩니다. (open(), fcntl() 등) 오류 검사가 없습니다. 아마도 이러한 함수 중 하나가 실패 할 수 있습니다. 오류가 open() 명령에 대한 예를 man 2 open 위해 (man 페이지를 읽어 확인하는 방법을 찾을 수 있습니다. open()의 경우 맨 페이지가 반환 -1 파일/포트를 열 수 없을 때 설명합니다.

을 편집 한 후 당신은 썼다..

char str[] = {0x56, 0x45, 0x52, 0x0D}; 
write(tty_fd,str,strlen(str)); 

잘못이다 strlen는 STR는이 데이터를 전송하고 메모리가 무엇이든 이제 분명하지 않은 '\ 0'종료 문자열을 기대는 '\ 0'당신을 볼 때까지 str 어레이에 0x00을 추가해야합니다.

+0

동의합니다. 오류 검사를 수행하지 않았습니다. 하지만 나는 현재의 명령이 작동하는 문제의 원인이라고 생각하지 않는다. (이것은 연결이 괜찮음을 의미한다). 그러나, 당신이 나에게 점검해야 할 곳을 지적 할 수 있다면 정말 좋을 것입니다.이 모든 저레벨 입출력은 처음으로 완전히 새로운 것입니다. '\ r'에 대해, 나는 그것이 문제라고 생각하지 않는다. 왜냐하면이 코드를 테스트 해보고 여전히 같은 오류를 리턴하기 때문이다. 'char str [] = { 'V', 0x45, 0x52, 0x0D};write (tty_fd, str, strlen (str));'.. 그리고 또한'0x0D'가 정확하게'\ r' –

+0

이라는 ASCII 테이블을 검사했고 테스트 목적으로'\ n'도 시도했습니다. 잘 작동하지 않았다. –

+0

이제 코드를 보지 말아야합니다. 직렬 포트를 다른 상자의 다른 포트에 연결하고 터미널 앱을 사용하여 두 경우 모두 전송중인 내용을 읽습니다 (동일해야하지만 동일하지는 않음). –

관련 문제