2017-07-22 80 views
0

我想从我的BananaPi(Debian jessie)的串行端口读取数据。我写了这样的代码:串行端口(AT命令)不断流单个字节或错误

typdef struct write_args { 
    int fd; 
} write_args; 

/* Thread to wait for user input */ 
void* serial_write_fn(void* args) 
{ 
    write_args* wargs = (write_args*)args); 
    char buf[256]; 
    while (1) { 
     memset(buf, 0, sizeof(buf)); 
     fgets(buf, sizeof(buf), stdin); 

     n = write(wargs->fd, buf, strlen(buf)); 
     if (n < 0) { 
      fputs("write() failed.\n", stderr); 
      return NULL; 
     } 
    } 
    return NULL; 
} 

void serial() 
{ 
    int fd = open("/dev/ttyACM0", O_RDWR | O_NOCCTY | O_NDELAY); 
    if (fd == -1) { 
     perror("open port failed."); 
     return; 
    } 

    fcntl(fd, F_SETFL, 0); 

    /* Create write thread */ 
    write_args wargs; 
    wargs.fd = fd; 
    pthread_t tid; 
    int err = pthread_create(&tid, NULL, &serial_write_fn, &wargs); 
    if (err != 0) 
     perror("Failed to create thread."); 

    char buffer[512]; 
    while (1) { 
     memset(buffer, 0, 512); 
     ssize_t bytes = read(fd, buffer, 512); 

     if (bytes > 1) /* Try to remove this line */ 
      printf(buffer); 
    } 

    close(fd); 
} 

所以当我运行程序时,自然创建了写入线程,等待输入。然后,我键入ATAT+VCID=1,我得到两次OK一个答案:

AT 
OK 
AT+VCID=1 
OK 

于是,我试着拨打该号码,看输出和我

RING 
DATE = 0722 
TIME = 0441 
NMBR = 6982311133 
ERROR 
ERROR 
ERROR 
ERROR 
ERROR 
ERROR 
ERROR 
... 

这是第一个问题。第二个问题是当我试图删除最后一个时(if (bytes > 1)),read函数永远不会停止读取数据。它总是返回1个字节。

我做错了什么?为什么我总是收到ERROR,为什么read函数总是有1个字节读取?

编辑#1

所以MartinJames的评论之后,我决定调查多一点。

我改变了我的读循环,这样的:

while (1) { 
    memset(buf, 0, sizeof(buf)); 
    bytes = read(fd, buf, sizeof(buf)); 
    if (bytes == 0) { 
     printf("Read 0 bytes.\n"); 
     break; 
    } else if (bytes == -1) { 
     printf("Read -1 bytes.\n"); 
     break; 
    } else if (bytes == 1) { 
     printf("Read 1 bytes.\n"); 
    } else { 
     printf(buf); 
    } 
} 

程序运行,等待我写的命令。我写了,正如你所看到的,read函数每次返回1个字节,现在和之后除了几个OK外。

[email protected]:~/serial$ sudo make run 
Executing bin/Debug/serial.out ... 
at <--- I typed that and clicked Enter 
at 
Read 1 bytes. 
Read 1 bytes. 
OK 
Read 1 bytes. 
Read 1 bytes. 
atat 
Read 1 bytes. 
Read 1 bytes. 
Read 1 bytes. 
Read 1 bytes. 
Read 1 bytes. 
Read 1 bytes. 
Read 1 bytes. 
OK 
Read 1 bytes. 
Read 1 bytes. 
... 
+0

“?为什么读取功能总是有1个字节读” - 你怎么知道?如果read()返回0或-1会怎么样?如果-1,那么errno/GetLastError()会显示什么问题?真的,你需要在调试时比这更好:(( –

+0

'ERROR'正在被调制解调器返回。 –

+0

@MartinJames我将调查read()语句并更新我的答案。至于“ERROR”,我知道它是由我的调制解调器返回,但我不知道为什么。当我使用不同的客户端的AT命令(minicom开源程序),我没有得到这些错误。 – TheCrafter

回答

0

原来,锯屑是正确的指出我应该更仔细地阅读Serial Programming Guide for POSIX Operating Systems

是固定我的问题的配置:

struct termios opt; 
tcgetattr(fd, &opt); 
opt->c_cflag  |= (CLOCAL | CREAD); 
opt->c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG); 
opt->c_oflag  &= ~OPOST; 
opt->c_cc[VMIN] = 1; 
opt->c_cc[VTIME] = 10; 
tcsetattr(fd, TCSADRAIN, &opt); 
+1

初始化不完整。它仅将终端配置为非规范模式。成帧参数(即波特率,帧大小,奇偶校验,停止位数)仍然有可能。 – sawdust

+0

@sawdust在你提供的链接中说:“接下来你需要建立与MODEM的通信。做到这一点的最佳方法是向MODEM发送“AT”命令。这也允许智能MODEM检测您正在使用的波特率。当MODEM正确连接并通电时,它将响应“OK”。“所以我认为它足以使用该配置。如果不是,我怎么才能找到正确的波特率,分数等等。? – TheCrafter

+1

*“我如何找到正确的波特率,分数等?” - - 必须匹配连接设备的配置。通常情况下,这些信息记录在手册中,或者可以从设备或设置人员中检索。在你的情况下,因为你似乎有一个工作连接,使用'stty -a -F/dev/ttyACM0' shell命令获取配置报告。 – sawdust