gpt4 book ai didi

c - C中的串行通信

转载 作者:太空狗 更新时间:2023-10-29 12:25:34 24 4
gpt4 key购买 nike

我正在尝试编写一个简单的应用程序来从 Keithley 6485 皮安表读取当前值,该表通过 Linux 上的串行通信 (RS232<->USB) 连接。

目前,可以通过对设备进行所有必要的初始化并发送“READ?”来检索这样的值。对它: echo "READ?">/dev/ttyUSB0。然后如果 cat/dev/ttyUSB0 一直在监听,我得到以下输出:-2.250416E-14A,+8.320175E+03,+0.000000E+00,of其中第一个数字是所需的值。

为了能够输出值,我使用以下代码使用 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 代码的命令?


编辑:显然我的写作程序似乎不能正常工作:

端口设置:

    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

并且在代码中找不到大的差异 - 这会是端口设置错误的标志还是我遗漏了什么?

最佳答案

问题已解决!

显然,设备正在等待行尾终止符,这在 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

关于c - C中的串行通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42071068/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com