【问题标题】:Reading arduino serial in linux using C使用 C 在 linux 中读取 arduino 串行
【发布时间】:2017-04-16 20:19:06
【问题描述】:

我想从 arduino 读取序列。我使用此代码:

#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/ioctl.h>
int main(){
    char data[1024];
    char dev[] = "/dev/ttyACM1";
    int fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY);
    fcntl(fd, F_SETFL, FNDELAY);
    struct termios options;
    tcgetattr(fd, &options);
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
    options.c_cflag |= CS8;
    options.c_cflag |= CS8;
    options.c_cflag &= ~CRTSCTS;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tcsetattr(fd, TCSANOW, &options);
    ioctl(fd, TCFLSH, 2);
    while(1){
        read(fd, data, sizeof(data));
        printf(data);
    }
    //write(fd, data, sizeof(data));
}

我的 arduino 运行非常简单的草图:

int x; 
void setup() {
  Serial.begin(9600);
}
void loop() {
  Serial.println("DO YOU HEAR ME ??");
  delay(1000);
}

这个组合的输出是:

??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??
A¹­þ
??OU HEAR ME ??
DO YOU HEAR ME ??
DO YOU HEAR ME ??

我的问题是如何从混乱中恢复秩序。我发现当缓冲区结束并开始新缓冲区时会出现此问题(更大的缓冲区更少垃圾数据)但我不能拥有无限缓冲区。第一次读取时也有很多垃圾..有没有办法同步它或其他什么?

(另外我不是英语母语,如有错误请见谅。)

【问题讨论】:

  • 尝试检查read的返回值。
  • @DavidCullen 我启用了规范输入,现在垃圾只发生在行首。所以我现在假设输入中有一些额外的位。但我不知道从在哪里(就像 3 个字符,3 个字节)。
  • 附注,尝试提高波特率,看看是否解决问题?
  • @LethalProgrammer 不,我试过了......我认为它必须对标志做一些事情,但我不知道在这一点上是......为什么它不能像发送一样?只写和读?
  • 如果你不检查read的返回值,它可能会返回一个错误值。但是,您的程序仍将打印data 缓冲区。此外,在成功时,read 的返回值将是读取的字节数,您应该使用它来确保 data 以空值结尾。

标签: c linux arduino serial-communication


【解决方案1】:

我找到了自己问题的答案。这次我用c++在课堂上组织它(很差的一个,因为它不处理任何错误,并且最不使用c++..)这是代码:

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

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>

#include <cstring>
#include <iostream>
//Here I define some vars 
#define BAUDRATE B9600
#define MODEMDEVICE "/dev/ttyACM0"
#define _POSIX_SOURCE 1

class serial{
public:
serial(){
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
    if (fd <0) {perror(MODEMDEVICE); exit(-1); } 
    // Improvement No. 1 I save old setting and clean the new one 
    tcgetattr(fd,&oldtio);
    bzero(&newtio, sizeof(newtio));

    // Here I set all the flags to vars at once
    newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR | ICRNL;
    newtio.c_oflag = 0;
    newtio.c_lflag = ICANON;
    //here I set some new flags..
    newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
    newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
    newtio.c_cc[VERASE]   = 0;     /* del */
    newtio.c_cc[VKILL]    = 0;     /* @ */
    newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
    newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
    newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character  arrives */
    newtio.c_cc[VSWTC]    = 0;     /* '\0' */
    newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
    newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
    newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
    newtio.c_cc[VEOL]     = 0;     /* '\0' */
    newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
    newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
    newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
    newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
    newtio.c_cc[VEOL2]    = 0;     /* '\0' */
    // and I finally save the settings 
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);
}
~serial(){
    close(fd);
}

    std::string sread(){
        res = read(fd,buf,255);
        buf[res]=0;
        return buf;
    }
    void swrite(const char* input){
        write(fd,input,std::strlen(input));
    }
private:
    int fd,c,res;
    struct termios oldtio,newtio;
    char buf[255];
};


int main(){
    serial s;
    s.swrite("Light");
    std::string buf = s.sread();
    std::cout << buf;
}

这更像是对“串行编程如何”的抄袭:http://tldp.org/HOWTO/Serial-Programming-HOWTO/(形成示例代码..)

这是新的可怜的 arduino 代码:

int x; 
String buff;
int lpin = A0;
int tpin = A1;
int data;
void setup() {
  Serial.begin(9600);
  pinMode(lpin,INPUT);
  pinMode(tpin,INPUT);
}
void loop() {
  if(Serial.available() == 1)
  {
    buff = Serial.readString();
    if(buff == "Light"){
      data = analogRead(lpin);
      Serial.print(data);
      Serial.print("\n");
    }else if(buff == "Temp"){
      data = analogRead(tpin);
      Serial.print(data);
      Serial.print("\n");
    }else{
      Serial.print("Something went wrong !");
      Serial.print("\n");
    }
  }
  delay(1);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多