【问题标题】:Read and Write from serial port under Ubuntu for USB scaleUbuntu下串口读写USB scale
【发布时间】:2019-09-10 02:53:13
【问题描述】:

我有一个通过 USB 连接到我的 Ubuntu 笔记本电脑的数字秤,我想从中读取测量值。 串行协议非常简单(9600,8N1, ttyUSB0),我可以通过终端使用 putty (VT100+) 正确读取测量值。

秤需要接收指令

"READ<CR><LF>"

为了发送测量。 每个测量都有这种格式:

01ST,GS,   2.5,kg<CR><LF>

例如,如果我正在测量 2.5 公斤的负载。

现在,我正在尝试从 C 应用程序发送 READ 命令,但我无法得到任何答案。

#include <errno.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error from tcgetattr: %s\n", strerror(errno));
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* fetch bytes as they become available */
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("Error from tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

void set_mincount(int fd, int mcount)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error tcgetattr: %s\n", strerror(errno));
        return;
    }

    tty.c_cc[VMIN] = mcount ? 1 : 0;
    tty.c_cc[VTIME] = 5;        /* half second timer */

    if (tcsetattr(fd, TCSANOW, &tty) < 0)
        printf("Error tcsetattr: %s\n", strerror(errno));
}


int main()
{
    char *portname = "/dev/ttyUSB0";
    int fd;
    int wlen;
    printf("Opening the connection on serial port\n");
    fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        printf("Error opening %s: %s\n", portname, strerror(errno));
        return -1;
    }
    /*baudrate 9600, 8 bits, no parity, 1 stop bit */
    set_interface_attribs(fd, B9600);
    //set_mincount(fd, 0);                /* set to pure timed read */

    /* simple output */
    printf("Sending the command READ\n");
    wlen = write(fd, "READ\n", 5);
    if (wlen != 5) {
        printf("Error from write: %d, %d\n", wlen, errno);
    }
    tcdrain(fd);    /* delay for output */


    /* simple noncanonical input */
    do {
        unsigned char buf[80];
        int rdlen;

        rdlen = read(fd, buf, sizeof(buf) - 1);
        if (rdlen > 0) {

            buf[rdlen] = 0;
            printf("Read %d: \"%s\"\n", rdlen, buf);

        } else if (rdlen < 0) {
            printf("Error from read: %d: %s\n", rdlen, strerror(errno));
        } else {  /* rdlen == 0 */
            printf("Timeout from read\n");
        }               
        /* repeat read to get full message */
    } while (1);
}

你能帮帮我吗?谢谢! 我是初学者,所以可能只是一个我看不到的愚蠢错误。

但是,还有其他更快的方法来完成相同的任务吗?

【问题讨论】:

  • 您最好使用规范模式,然后您的程序将检索每个 read() 系统调用的完整行(假设您提供足够大的缓冲区)。见stackoverflow.com/questions/57152937/…
  • @Marcus Barnet:1) 如果您还没有投票,请点赞并“接受”wallyk 的回复。 2) 锯末是正确的:因为 "\r]n" 已经是设备协议的一部分......您最好保持在“规范”模式,一次只读取一行。 3) 就像秤有“READ”命令一样……它也可能有某种“STOP”命令。看手册:)
  • OT:关于如下语句:printf("Error from tcgetattr: %s\n", strerror(errno)); 错误信息应该输出到stderr,而不是stdout 建议使用:fprintf( stderr, "Error from tcgetattr: %s\n", strerror( errno ));

标签: c ubuntu serial-port putty tty


【解决方案1】:

可能该命令应该以回车符终止(而不是您所写的换行符):

    wlen = write(fd, "READ\n", 5);

改成

    wlen = write(fd, "READ\r", 5);

如果它真的(它可能,但也许不是)必须接收 cr lf:

    wlen = write(fd, "READ\r\n", 6);

【讨论】:

  • 我认为您很可能已经确定了问题所在。并感谢您使用\r\n 更新您的帖子:)
  • 谢谢,\r\n 解决了这个问题,现在我得到了规模答案!当程序收到\r\n时,有什么方法可以停止从秤读取?
  • /* simple noncanonical input */ do { unsigned char buf[80]; int rdlen; rdlen = read(fd, buf, sizeof(buf) - 1); if (rdlen &gt; 0) { buf[rdlen] = 0; printf("%s", buf); } else if (rdlen &lt; 0) { printf("Error from read: %d: %s\n", rdlen, strerror(errno)); } else { /* rdlen == 0 */ printf("Timeout from read\n"); } /* repeat read to get full message */ } while (1);
  • @MarcusBarnet,函数:read() 不返回“int”,而是返回ssize_t
猜你喜欢
  • 2011-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多