【问题标题】:serial programming on linux in C用 C 语言在 linux 上进行串行编程
【发布时间】:2013-10-09 02:43:54
【问题描述】:

我想在我的串口上发送一个特定的字符串并将答案读入缓冲区以进行进一步分析。我想出了一些代码,但即使外壳上的屏幕 /dev/ttyUSB0 19200 对我来说也很好,我也无法阅读任何答案。 decive 需要 8 个数据位、1 个起始位、1 个停止位,并且没有奇偶校验。 19200 波特。 现在我的代码看起来像这样,它一直在计时::(

/////////////////////////////////////////////////
// Serial port interface program               //
/////////////////////////////////////////////////
#include <stdio.h> // standard input / output functions
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitionss
#include <time.h>   // time calls


int open_port(void)
{
int fd; // file description for the serial port

fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if(fd == -1) // if open is unsucessful
{
perror("open_port: Unable to open /dev/ttyUSB0");
}
else
{
fcntl(fd, F_SETFL, 0);
}

return(fd);
}

int configure_port(int fd)      // configure the port
{
struct termios port_settings;      // structure to store the port settings in

cfsetispeed(&port_settings, B19200);    // set baud rates
cfsetospeed(&port_settings, B19200);

port_settings.c_cflag &= ~PARENB;    // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;

cfmakeraw(&port_settings);
tcsetattr(fd, TCSANOW, &port_settings);    // apply the settings to the port
return(fd);

}

int query_modem(int fd)   // query modem with an AT command
{
int n;
fd_set rdfs;
struct timeval timeout;
ssize_t retval;
char bufptr[100];
char chr;
int cnt = 0;
int i = 0;

// initialise the timeout structure
timeout.tv_sec = 2; // ten second timeout
timeout.tv_usec = 0;

if (FD_ISSET(fd, &rdfs)){
  FD_ZERO(&rdfs);
  FD_CLR(fd,&rdfs);
}

retval = write(fd, "TEST\r", 5);  // send an AT command followed by a CR
/*usleep(50);
while (read(fd, &chr, 1))
{
printf("0x%x\n",chr);
usleep(10);
}*/

// do the select
n = select(fd + 1, &rdfs, NULL, NULL, &timeout);

// check if an error has occured
if(n < 0)
{
perror("select failed\n");
}
else if (n == 0)
{
printf("Timeout\n");
}
else
{
printf("\nBytes detected on the port!\n");
}

}

int main(void)
{
int fd = open_port();
configure_port(fd);
query_modem(fd);
return(0);
}

我期望得到的是一个字符串说 “TEST”与我按回车时屏幕中的相同。 任何帮助,将不胜感激! 非常感谢!

罗恩

【问题讨论】:

  • 您对 FD_ISSSET() 和 FD_ZERO() 和 FD_CLR() 的使用毫无意义。您无条件地需要 FD_ZERO() 加上 FD_SET()。请参阅下面的@ott-- 答案。

标签: c linux io serial-port


【解决方案1】:

我的建议是您没有将 fd 添加到 rfds。检查 FD_* 宏以清除集合,添加 fd 并检查 fd 是否有输入。

更新

您确实需要将 fd 添加到 fdset:

write(...
FD_ZERO(&rdfs);
FD_SET(fd, &rfds);
n = select(...
if (n > 0) {
    if (FD_ISSET(fd, &rfds)) {
        // this fd has input waiting to be read

当你选择多个 fd 时,n 可以变成 > 1。

【讨论】:

  • 我不明白,“你还没有将fd添加到rfds”是什么意思?我如何设置fd?我不确定...请指教!谢谢!
  • 查看手册页以选择 FD_ZERO、FD_SET 和 FD_ISSET (man 3 select)。
  • 好的,谢谢奥特!我添加了这个,但结果并没有真正改变。在 write() 之前添加以下行: if (FD_ISSET(fd, &rdfs)){ FD_ZERO(&rdfs); FD_CLR(fd,&rdfs); }
  • 好的,我现在正确地弄清楚了发送和接收!我可以确认发送的数据是正确的,我可以用 read() 读回数据,但是选择没有启动....这是为什么呢?感谢您提供的任何提示或建议!
  • @cerr 你能把你的代码更新到当前状态吗? select() 返回什么?还是只是超时?
【解决方案2】:

简单的c代码

char types[25];    
char buffu[256];   
int fd:

strcat(types,"speed 115200 -parenb cs8 cstopb -ixon -ixoff -crtscts clocal cread raw");   
fd=open("dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);   
ioctl(fd, F_SETFL, 0);   

.....

write (fd, buffu, 255);   
usleep(400);   
read (fd,buffu,255);   

【讨论】:

    猜你喜欢
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2014-08-11
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多