linux C 中的串行读取()问题 [英] Serial read() issues in linux C

查看:71
本文介绍了linux C 中的串行读取()问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个仪器需要通过 RS232 与它通话.我正在使用 C,以下是代码.问题是,当我尝试读取 11 字节长的字段值(从仪表读取)时,一个读取命令仅读取 8 个字节,随后我必须发出另一个读取命令,该命令给我最后 3 个字节.最后,我将两个读取缓冲区连接起来以获得最终有意义的值.

#include #include #include #include #include #include #include #define MAXWAIT 30#define 波特率 B9600#define TESLAMETER "/dev/ttyS0"#define _POSIX_SOURCE 1/* POSIX 兼容源 */#定义假0#define TRUE 1#define NOREAD 255易失性INT STOP = FALSE;国际金融;struct termios oldtp, newtp;int openComPort(void){fd = open(TESLAMETER, O_RDWR | O_NOCTTY |O_NDELAY);如果(fd <0){误差(特斯拉计);返回 fd;}别的fcntl(fd,F_SETFL,0);tcgetattr(fd,&oldtp);/* 保存当前串口设置 */bzero(&newtp, sizeof(newtp));newtp.c_cflag = 波特率 |CS8 |本地 |面包;newtp.c_iflag = IGNPAR |ICRNL;newtp.c_oflag = 0;newtp.c_lflag = 0;//ICANON;newtp.c_cc[VINTR] = 0;/* Ctrl-c */newtp.c_cc[VQUIT] = 0;/* Ctrl-\ */newtp.c_cc[VERASE] = 0;/* 删除 */newtp.c_cc[VKILL] = 0;/*@*/newtp.c_cc[VEOF] = 4;/* Ctrl-d */newtp.c_cc[VTIME] = 1;/* 字符间定时器未使用,0.5 秒读取超时 */newtp.c_cc[VMIN] = 0;/* 阻塞或非阻塞读取直到 1 个字符到达 */tcflush(fd, tciflush);tcsetattr(fd,TCSANOW,&newtp);返回 fd;}浮动 readMagField(){无符号字符 cmd[]="FA0\r";//读取字段字符 buff2[11] = {0x00};字符 buff3[11] = {0x00};浮动字段浮动 = 0.00;int n_written = 0, 点 = 0, res;做{n_written = write( fd, &cmd[spot], 1 );现货 += n_written;} while (cmd[spot-1] != '\r' && n_written > 0);如果 (n_written <0){printf("write() 4 个字节失败!\n");返回假;}别的{//printf("字段读取命令发送成功%d\n",n_written);res = read(fd,buff2,11);//读取 8 个字节res = read(fd,buff3,11);//读取剩余的 3 个字节fieldFloat = atof(strcat(buff2,buff3));//这里有 11 个字节的最终字符串返回字段浮动;}}

我做错了什么或设置有问题吗?因为,我可以使用 Python 串行模块一次性读取完整的字符集,但不能使用 C.我正在使用 Ubuntu 12.04 LTS.

解决方案

read() 可能不读取指定长度就返回.

read(2) - Linux 手册页<块引用>

返回值

 成功时返回读取的字节数(零表示结束文件),文件位置按此数字前进.这是如果此数字小于字节数,则不是错误要求;这可能会发生,例如因为较少的字节现在实际可用(也许是因为我们即将结束-文件,或者因为我们正在从管道或终端读取),或因为 read() 被信号中断了.另见注释.

重试直到读取了所需长度的数据如何?

ssize_t read2(int fd, void *buf, size_t count) {ssize_t read_length = 0;while (read_length < count) {ssize_t delta = read(fd, buf + read_length, count - read_length);如果 (delta == -1) 返回 -1;read_length += delta;}返回读取长度;}

I have an instrument which I need to talk to by RS232. I am using C and following is the code. The problem is that, when I try to read field value (reading from meter) which is 11 byte long, one read command is reading only 8 bytes and subsequently I have to issue another read command which gives me final 3 bytes. Finally I am concatenating both read buffers to make final meaningful value.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#define MAXWAIT         30
#define BAUDRATE        B9600 
#define TESLAMETER      "/dev/ttyS0"
#define _POSIX_SOURCE   1 /* POSIX compliant source */
#define FALSE           0
#define TRUE            1
#define NOREAD          255

volatile int STOP = FALSE;
int fd;
struct termios oldtp, newtp;

int openComPort(void)
{
    fd = open(TESLAMETER, O_RDWR | O_NOCTTY |O_NDELAY );
    if (fd <0)
    {
        perror(TESLAMETER);     
        return fd;   
    }
    else
        fcntl(fd,F_SETFL,0);
    tcgetattr(fd,&oldtp); /* save current serial port settings */
    bzero(&newtp, sizeof(newtp));
    newtp.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
    newtp.c_iflag = IGNPAR | ICRNL;
    newtp.c_oflag = 0;
    newtp.c_lflag = 0;//ICANON;
    newtp.c_cc[VINTR]    = 0;     /* Ctrl-c */
    newtp.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
    newtp.c_cc[VERASE]   = 0;     /* del */
    newtp.c_cc[VKILL]    = 0;     /* @ */
    newtp.c_cc[VEOF]     = 4;     /* Ctrl-d */
    newtp.c_cc[VTIME]    = 1;     /* inter-character timer unused, 0.5 seconds read timeout */
    newtp.c_cc[VMIN]     = 0;     /* blocking or non blocking read until 1 character arrives */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtp);
    return fd;
}
float readMagField()
{
    unsigned char cmd[]="FA0\r"; // Read Field
    char buff2[11] = {0x00};
    char buff3[11] = {0x00};
    float fieldFloat = 0.00;
    int n_written= 0, spot = 0, res;
    do
    {
        n_written = write( fd, &cmd[spot], 1 );
        spot += n_written;
    } while (cmd[spot-1] != '\r' && n_written > 0);
    if (n_written < 0)
    {
            printf("write() of 4 bytes failed!\n");
        return FALSE;
    }
    else
    {
        //printf("Field Read Command sent successfully %d\n",n_written);
        res = read(fd,buff2,11);   // Reads 8 bytes
        res = read(fd,buff3,11);   // Reads remaining 3 bytes
        fieldFloat = atof(strcat(buff2,buff3)); // Final string of 11 bytes here
        return fieldFloat;
    }
}

Is there something that I am doing or setting wrong? Because, I can read the complete set of characters in one go using Python serial module, but not in C. I am working on Ubuntu 12.04 LTS.

解决方案

read() may return without reading the specified length.

read(2) - Linux manual page

RETURN VALUE

   On success, the number of bytes read is returned (zero indicates end
   of file), and the file position is advanced by this number.  It is
   not an error if this number is smaller than the number of bytes
   requested; this may happen for example because fewer bytes are
   actually available right now (maybe because we were close to end-of-
   file, or because we are reading from a pipe, or from a terminal), or
   because read() was interrupted by a signal.  See also NOTES.

How about retrying until the desired length of data have been read?

ssize_t read2(int fd, void *buf, size_t count) {
    ssize_t read_length = 0;
    while (read_length < count) {
        ssize_t delta = read(fd, buf + read_length, count - read_length);
        if (delta == -1) return -1;
        read_length += delta;
    }
    return read_length;
}

这篇关于linux C 中的串行读取()问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆