我正在尝试编写一个简单的应用程序,通过串行通信(RS232<->USB)在Linux上从Keithley 6485皮克安计读取当前值。
目前,可以通过执行所有必需的设备初始化并向其发送"READ?"来检索此类值:
为了能够输出该值,我使用以下代码使用termios库:
每次运行时,我都会得到以下结果:
但是,
目前,可以通过执行所有必需的设备初始化并向其发送"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
+----------------------------------+
但是,为了能够读取值,每次想要知道值时我都需要回显“READ?”命令(或者使用write()函数向设备写入)。
如何以最优雅的方式将写入和读取放在同一个应用程序中(例如,不使用命名管道),因为当前的read()函数会等待来自设备的任何内容,在此期间我不能从同一段C代码发送“READ?”命令?
编辑:显然我的写入过程似乎无法正常工作:
端口设置:
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串行端口读写,并没有在代码上找到太大的区别 - 这是否意味着串口设置错误或我遗漏了些什么?
read
读取答案之前不能调用write
发送查询? - Some programmer duderead
之前调用了write
,那么read
将不能访问到该值 - 我猜测它是实时按字节读取,而不是从缓冲区中读取。 - vastasread
访问”是什么意思?如果在read
之前执行write(fd, "READ?", 5)
,它就无法工作吗?read
返回什么(bytes_read
的值是多少)?如果失败了,errno
是什么?请详细说明。 - Some programmer dude