我正在尝试编写一个简单的应用程序来读取Keithley 6485皮安表的当前值,该值通过Linux上的串行通信(RS232< - > USB)连接。
目前,可以通过对设备进行所有必要的初始化并发送" READ?"来检索这样的值。它:echo "READ?" > /dev/ttyUSB0
。然后,如果cat /dev/ttyUSB0
一直在监听,我会得到以下输出:-2.250416E-14A,+8.320175E+03,+0.000000E+00
,其中第一个数字是所需的值。
为了能够输出值,我使用termios库使用以下代码:
/*====================================================================================================*/
/* Serial Port Programming in C (Serial Port Read) */
/* Non Cannonical mode */
/*----------------------------------------------------------------------------------------------------*/
/* Program reads a string from the serial port at 9600 bps 8N1 format */
/* Baudrate - 9600 */
/* Stop bits -1 */
/* No Parity */
/*----------------------------------------------------------------------------------------------------*/
/* Compiler/IDE : gcc 4.6.3 */
/* Library : */
/* Commands : gcc -o serialport_read serialport_read.c */
/* OS : Linux(x86) (Linux Mint 13 Maya)(Linux Kernel 3.x.x) */
/* Programmer : Rahul.S */
/* Date : 21-December-2014 */
/*====================================================================================================*/
/*====================================================================================================*/
/* www.xanthium.in */
/* Copyright (C) 2014 Rahul.S */
/*====================================================================================================*/
/*====================================================================================================*/
/* Running the executable */
/* ---------------------------------------------------------------------------------------------------*/
/* 1) Compile the serialport_read.c file using gcc on the terminal (without quotes) */
/* */
/* " gcc -o serialport_read serialport_read.c " */
/* */
/* 2) Linux will not allow you to access the serial port from user space,you have to be root.So use */
/* "sudo" command to execute the compiled binary as super user. */
/* */
/* "sudo ./serialport_read" */
/* */
/*====================================================================================================*/
/*====================================================================================================*/
/* Sellecting the Serial port Number on Linux */
/* ---------------------------------------------------------------------------------------------------*/
/* /dev/ttyUSBx - when using USB to Serial Converter, where x can be 0,1,2...etc */
/* /dev/ttySx - for PC hardware based Serial ports, where x can be 0,1,2...etc */
/*====================================================================================================*/
/*-------------------------------------------------------------*/
/* termios structure - /usr/include/asm-generic/termbits.h */
/* use "man termios" to get more info about termios structure */
/*-------------------------------------------------------------*/
#include <stdio.h>
#include <fcntl.h> /* File Control Definitions */
#include <termios.h> /* POSIX Terminal Control Definitions */
#include <unistd.h> /* UNIX Standard Definitions */
#include <errno.h> /* ERROR Number Definitions */
void main(void)
{
int fd;/*File Descriptor*/
printf("\n +----------------------------------+");
printf("\n | Serial Port Read |");
printf("\n +----------------------------------+");
/*------------------------------- Opening the Serial Port -------------------------------*/
/* Change /dev/ttyUSB0 to the one corresponding to your system */
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */
// fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY | O_NDELAY); /* ttyUSB0 is the FT232 based USB2SERIAL Converter */
/* O_RDWR - Read/Write access to serial port */
/* O_NOCTTY - No terminal will control the process */
/* Open in blocking mode,read will wait */
if(fd == -1) /* Error Checking */
printf("\n Error! in Opening ttyUSB0 ");
else
printf("\n ttyUSB0 Opened Successfully ");
/*---------- Setting the Attributes of the serial port using termios structure --------- */
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
/* Setting the Baud rate */
cfsetispeed(&SerialPortSettings,B19200); /* Set Read Speed as 19200 */
cfsetospeed(&SerialPortSettings,B19200); /* Set Write Speed as 19200 */
/* 8N1 Mode */
SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */
SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag &= ~CRTSCTS; /* No Hardware flow Control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines */
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); /* Disable XON/XOFF flow control both i/p and o/p */
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* Non Cannonical mode */
SerialPortSettings.c_oflag &= ~OPOST;/*No Output Processing*/
/* Setting Time outs */
SerialPortSettings.c_cc[VMIN] = 13; /* Read at least 10 characters */
SerialPortSettings.c_cc[VTIME] = 0; /* Wait indefinetly */
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) /* Set the attributes to the termios structure*/
printf("\n ERROR ! in Setting attributes");
else
printf("\n BaudRate = 19200 \n StopBits = 1 \n Parity = none");
/*------------------------------- Read data from serial port -----------------------------*/
char read_buffer[32]; /* Buffer to store the data received */
int bytes_read = 0; /* Number of bytes read by the read() system call */
int i = 0;
tcflush(fd, TCIFLUSH); /* Discards old data in the rx buffer */
bytes_read = read(fd,&read_buffer,32); /* Read the data */
printf("\n\n Bytes Rxed -%d", bytes_read); /* Print the number of bytes read */
printf("\n\n ");
for(i=0;i<13;i++) /*printing only the needed bytes*/
printf("%c",read_buffer[i]);
printf("\n +----------------------------------+\n\n\n");
close(fd); /* Close the serial port */
}
哪个输出:
+----------------------------------+
| Serial Port Read |
+----------------------------------+
ttyUSB0 Opened Successfully
BaudRate = 19200
StopBits = 1
Parity = none
Bytes Rxed -13
-2.864104E-14
+----------------------------------+
但是,为了能够读取该值,我必须回应&#34; READ?&#34;每当我想知道值时,命令(或使用write()函数写入设备)。
如何以最优雅的方式将写入和读取放在同一个应用程序中(例如,不使用命名管道),因为当前read()函数等待来自设备的任何内容,在此期间我可以不发送&#34; READ?&#34;来自相同C代码的命令?
编辑:显然我的写作程序似乎无法正常运作:
端口设置:
struct termios SerialPortSettings; /* Create the structure */
tcgetattr(fd, &SerialPortSettings); /* Get the current attributes of the Serial port */
cfsetispeed(&SerialPortSettings,(speed_t)B19200); /* Set Read Speed as 19200 */
cfsetospeed(&SerialPortSettings,(speed_t)B19200); /* Set Write Speed as 19200 */
SerialPortSettings.c_cflag &= ~PARENB; /* Disables the Parity Enable bit(PARENB),So No Parity */
SerialPortSettings.c_cflag &= ~CSTOPB; /* CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit */
SerialPortSettings.c_cflag &= ~CSIZE; /* Clears the mask for setting the data size */
SerialPortSettings.c_cflag |= CS8; /* Set the data bits = 8 */
SerialPortSettings.c_cflag = ~CRTSCTS; /* No Hardware flow Control */
SerialPortSettings.c_cflag |= CREAD | CLOCAL; /* Enable receiver,Ignore Modem Control lines */
cfmakeraw(&SerialPortSettings);
tcflush(fd,TCIFLUSH);
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both i/p and o/p
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode
SerialPortSettings.c_oflag &= ~OPOST;//No Output Processing
书写:
char write_buffer[] = "READ?"; /* Buffer containing characters to write into port */
int bytes_written = 0; /* Value for storing the number of bytes written to the port */
bytes_written = write(fd,&write_buffer,sizeof(write_buffer) -1);
printf("%s written to ttyUSB0 \n",write_buffer);
printf("%d Bytes written to ttyUSB0 \n", bytes_written);
printf("+----------------------------------+\n\n");
close(fd);/* Close the Serial port */
每当这个运行时,我得到:
+----------------------------------+
| Serial Port Write |
+----------------------------------+
ttyUSB0 Opened Successfully
Attributes set
READ? written to ttyUSB0
5 Bytes written to ttyUSB0
+----------------------------------+
但cat /dev/ttyUSB0
似乎没有看到任何来自设备的内容。我在以下位置检查了类似的问题:
Linux C Serial Port Reading/Writing
并且在代码中找不到很大的差异 - 这是错误的端口设置的标志还是我错过了什么?
答案 0 :(得分:1)
问题已解决!
显然,设备正在等待终端线终结器,char write_buffer[] = "READ?";
因此,当它收到这样的命令时,公共汽车将会“挂起”。为了让它再次工作,我们必须再次打开这个端口。
这也解释了为什么echo "READ?" > /dev/ttyUSB0
命令有效 - 因为它会自动输出一个终止行终结符。
我附上下面的工作代码 - 谢谢大家的意见和善意的帮助!
int fd; //device file id
//------------------------------- Opening the Serial Port -------------------------------
fd = open("/dev/ttyUSB0",O_RDWR | O_NOCTTY); // ttyUSB0 is the FT232 based USB2SERIAL Converter
if(fd == -1) // Error Checking
printf("Error while opening the device\n");
//---------- Setting the Attributes of the serial port using termios structure ---------
struct termios SerialPortSettings; // Create the structure
tcgetattr(fd, &SerialPortSettings); // Get the current attributes of the Serial port
// Setting the Baud rate
cfsetispeed(&SerialPortSettings,B19200); // Set Read Speed as 19200
cfsetospeed(&SerialPortSettings,B19200); // Set Write Speed as 19200
SerialPortSettings.c_cflag &= ~PARENB; // Disables the Parity Enable bit(PARENB),So No Parity
SerialPortSettings.c_cflag &= ~CSTOPB; // CSTOPB = 2 Stop bits,here it is cleared so 1 Stop bit
SerialPortSettings.c_cflag &= ~CSIZE; // Clears the mask for setting the data size
SerialPortSettings.c_cflag |= CS8; // Set the data bits = 8
SerialPortSettings.c_cflag &= ~CRTSCTS; // No Hardware flow Control
SerialPortSettings.c_cflag |= CREAD | CLOCAL; // Enable receiver,Ignore Modem Control lines
SerialPortSettings.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable XON/XOFF flow control both i/p and o/p
SerialPortSettings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG); // Non Cannonical mode
SerialPortSettings.c_oflag &= ~OPOST;//No Output Processing
// Setting Time outs
SerialPortSettings.c_cc[VMIN] = 13; // Read at least 10 characters
SerialPortSettings.c_cc[VTIME] = 0; // Wait indefinetly
if((tcsetattr(fd,TCSANOW,&SerialPortSettings)) != 0) // Set the attributes to the termios structure
printf("Error while setting attributes \n");
//------------------------------- Read data from serial port -----------------------------
char read_buffer[32]; // Buffer to store the data received
int bytes_read = 0; // Number of bytes read by the read() system call
int bytes_written = 0; // Number of bytes written
int i = 0;
tcflush(fd, TCIFLUSH); // Discards old data in the rx buffer
//Device intialization
char write_buffer[]="READ? \n ";
bytes_written=write(fd,&write_buffer,sizeof(write_buffer));
bytes_read = read(fd,&read_buffer,32); // Read the data
for(i=0;i<13;i++) //printing only the needed characters
printf("%c",read_buffer[i]);
close(fd); // Close the serial port
答案 1 :(得分:0)
在阅读之前使用select()或poll()来检查数据是否可用。如果没有可用的数据,则可以写入&#34; READ?&#34;命令。