C 在串行端口上写入数据后从串行端口读取数据

C 在串行端口上写入数据后从串行端口读取数据,c,serial-port,arduino,C,Serial Port,Arduino,我正在进行一个项目,该项目使我的计算机与arduino板进行通信,该板读取传感器输出,并仅在收到“t”时将其置于串行端口。如下所示的arduino代码正在工作 const int inputPin = 0; void setup(){ Serial.begin(9600); pinMode(13, OUTPUT);} void loop(){ if (Serial.available() > 0){ char c=Serial.read(); if(c=='t')

我正在进行一个项目,该项目使我的计算机与arduino板进行通信,该板读取传感器输出,并仅在收到“t”时将其置于串行端口。如下所示的arduino代码正在工作

const int inputPin = 0;
void setup(){
  Serial.begin(9600);
  pinMode(13, OUTPUT);}

void loop(){
 if (Serial.available() > 0){
    char c=Serial.read();
   if(c=='t'){
      int value = analogRead(inputPin);
      float celsius = (5.0 * value * 100.0)/1024.0; 
      Serial.println(celsius);
    }
  }
}
我的问题是在C代码中,当我试图读取arduino放在串行端口上的内容时。我的C代码是:

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

int main(){     
    int STATE_OK=0;
    int STATE_WARNING=1;
    int STATE_CRITICAL=2; 
    char tempbuf[10];
    int fd=open("/dev/ttyACM0",O_RDWR | O_NOCTTY | O_NONBLOCK);
    if(fd == -1){
            printf("Unable to open /dev/ttyACM0\n");
            return STATE_WARNING;
    } else {
        fcntl(fd, F_SETFL, FNDELAY);
        int w=write(fd, "t", 1);
        printf("The number of bytes written to the serial port is %d \n",w);
        fprintf(stderr, "fd = %d.\n", fd);
        sleep(10);
        int n=read(fd,tempbuf,5);
        printf("%d,%s \n",n,strerror(errno));
        if(n>0){
            float temp=atof(tempbuf);
            printf("Temperature is: %f Celsius\n", temp);
            if (temp>27){
                return STATE_CRITICAL;
            }else{
                printf("The temperature is %f Celsius and checked 10 seconds ago\n",temp);
                return STATE_OK;
            }
        }
    }
    close(fd);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
int STATE_OK=0;
int STATE_WARNING=1;
int STATE_CRITICAL=2;
char-tempbuf[10];
int fd=open(“/dev/ttyACM0”,O|RDWR | O|NOCTTY | O|NONBLOCK);
如果(fd==-1){
printf(“无法打开/dev/ttyACM0\n”);
返回状态警告;
}否则{
fcntl(fd、F_设置FL、FNDELAY);
int w=写入(fd,“t”,1);
printf(“写入串行端口的字节数为%d\n”,w);
fprintf(标准,“fd=%d.\n”,fd);
睡眠(10);
int n=读取(fd,tempbuf,5);
printf(“%d,%s\n”,n,strerror(errno));
如果(n>0){
浮动温度=atof(tempbuf);
printf(“温度为:%f摄氏度\n”,温度);
如果(温度>27){
返回状态_临界;
}否则{
printf(“温度为%f摄氏度,并在10秒前检查过”,temp);
返回状态_OK;
}
}
}
关闭(fd);
返回0;
}
n总是=0,我不知道问题出在哪里。 提前谢谢。

试试这个

int n=read(fd,&tempbuf,sizeof(tempbuf));
而不是

int n=read(fd,tempbuf,5);

您不应该终止使用“\0”发送的数据吗?
Serge阅读read()的描述(如下所示)告诉我们,当到达文件末尾时,n=0。由于序列号未发送\0,读取将继续,直到到达文件末尾。因此,我认为n==0是您想要的结果

那么,也许你的 如果(n>0)

测试应该是 如果(n==0)

使用调试器可以看到缓冲区中预期的字符吗

读() #包括 int读取(int句柄、void*缓冲区、int字节)

函数的作用是:尝试从与handle关联的文件中读取N字节,并将读取的字符放入缓冲区。如果文件是使用O_文本打开的,它将删除回车符并检测文件的结尾

函数返回读取的字节数。文件末尾返回0,出错时返回-1,设置errno以指示发生的错误类型

我想不出是什么问题

一个大问题是在“计算机”上运行的C程序不完整

Arduino程序的串行端口设置至少为波特率(以及默认情况下可能执行的任何其他设置)。
但是“计算机”的C程序从未正确配置串行端口。串行端口将使用先前配置的任何属性(波特率、数据长度、奇偶校验设置、规范与原始模式),这将导致不可预测的读写。(环回测试可能会产生假阳性结果。)

使用或作为示例代码

对于规范模式,您可能需要添加如下代码(假设为8N1):


以及调用
open()
中的
O\u NONBLOCK
选项

谢谢你的回答。这是我的最终代码:

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

int main() {    

    int STATE_OK=0;
    int STATE_WARNING=1;
    int STATE_CRITICAL=2; 
    char tempbuf[10];
    struct termios tty;

    int fd=open("/dev/ttyACM1",O_RDWR | O_NOCTTY);
    if(fd == -1){
            printf("Unable to open /dev/ttyACM1\n");
            return STATE_WARNING;
    }else {
        if(tcgetattr(fd, &tty)!=0){
            perror("tcgetatt() error");
        }else{
                cfsetospeed(&tty, B9600);
                cfsetispeed(&tty, B9600);

                tty.c_cflag &= ~PARENB;
                tty.c_cflag &= ~CSTOPB;
                tty.c_cflag &= ~CSIZE;
                tty.c_cflag |= CS8;
                tty.c_cflag &= ~CRTSCTS; 
                tty.c_cflag |= CLOCAL | CREAD;

                tty.c_iflag |= IGNPAR | IGNCR;
                tty.c_iflag &= ~(IXON | IXOFF | IXANY);
                tty.c_lflag |= ICANON;
                tty.c_oflag &= ~OPOST;
                tcsetattr(fd, TCSANOW, &tty);

                int w=write(fd, "t", 1);/*printf("%d\n",w);
                fprintf(stderr, "fd = %d.\n", fd);*/
                usleep(1000);
                int n=read(fd,tempbuf,8);/*printf("%d \n",n);*/
                tempbuf[9]=0;
                float temp=atof(tempbuf);

                if (temp>27){
                    printf("CRITICAL: %f celsius\n",temp);
                    return STATE_CRITICAL;
                }else{
                    printf("Everything is OK and the temperature is %f Celsius\n",temp);
                    return STATE_OK;
                }
        }
    }
    close(fd);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
int STATE_OK=0;
int STATE_WARNING=1;
int STATE_CRITICAL=2;
char-tempbuf[10];
结构termios tty;
int fd=打开(“/dev/ttyACM1”,O|RDWR | O|NOCTTY);
如果(fd==-1){
printf(“无法打开/dev/ttyACM1\n”);
返回状态警告;
}否则{
如果(tcgetattr(fd和tty)!=0){
perror(“tcgetatt()错误”);
}否则{
cfsetospeed&tty,B9600);
cfsetispeed(&tty,B9600);
tty.c_cflag&=~PARENB;
tty.c_cflag&=~CSTOPB;
tty.c_cflag&=~CSIZE;
tty.c|u cflag |=CS8;
tty.c_cflag&=~CRTSCTS;
tty.c|u cflag |=CLOCAL | CREAD;
tty.c|U iflag |=IGNPAR | IGNCR;
tty.c|u iflag&=~(IXON | IXOFF | IXANY);
tty.c|lflag |=ICANON;
tty.c_of lag&=~OPOST;
tcsetattr(fd、TCSANOW和tty);
int w=写入(fd,“t”,1);/*printf(“%d\n”,w);
fprintf(标准,“fd=%d.\n”,fd)*/
usleep(1000);
int n=read(fd,tempbuf,8);/*printf(“%d\n”,n)*/
tempbuf[9]=0;
浮动温度=atof(tempbuf);
如果(温度>27){
printf(“临界温度:%f摄氏度\n”,温度);
返回状态_临界;
}否则{
printf(“一切正常,温度为%f摄氏度\n”,温度);
返回状态_OK;
}
}
}
关闭(fd);
返回0;
}

睡眠时间是否足够长以进行响应?我已经尝试将其更改为睡眠(1000),但n仍然=0,我认为这足够了,因为arduino具有快速响应。至少使用Putty之类的程序来验证您的PC是否可以从串行端口接收数据。接线错误当然是一种解释,不注意握手是另一种解释。使用O_NONBLOCK、数字5和不配置端口设置(如波特率)也是让自己陷入麻烦的好方法。我不确定我是否理解你的意思,但当我从串行端口读取数据而不先写后读时,它工作正常,因此我的PC可以从串行端口接收数据。写而不读也是有效的,问题是当我把它们一起使用时。感谢您的帮助。调试想法:回到read工作的地方(不写)。然后将
open()
更改为允许写入,但不执行写入。这样做的目的是确定这是open()调用还是write()调用
fcntl(fd, F_SETFL, FNDELAY);  
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
#include<errno.h>
#include<unistd.h>
#include<fcntl.h>
#include<termios.h>

int main() {    

    int STATE_OK=0;
    int STATE_WARNING=1;
    int STATE_CRITICAL=2; 
    char tempbuf[10];
    struct termios tty;

    int fd=open("/dev/ttyACM1",O_RDWR | O_NOCTTY);
    if(fd == -1){
            printf("Unable to open /dev/ttyACM1\n");
            return STATE_WARNING;
    }else {
        if(tcgetattr(fd, &tty)!=0){
            perror("tcgetatt() error");
        }else{
                cfsetospeed(&tty, B9600);
                cfsetispeed(&tty, B9600);

                tty.c_cflag &= ~PARENB;
                tty.c_cflag &= ~CSTOPB;
                tty.c_cflag &= ~CSIZE;
                tty.c_cflag |= CS8;
                tty.c_cflag &= ~CRTSCTS; 
                tty.c_cflag |= CLOCAL | CREAD;

                tty.c_iflag |= IGNPAR | IGNCR;
                tty.c_iflag &= ~(IXON | IXOFF | IXANY);
                tty.c_lflag |= ICANON;
                tty.c_oflag &= ~OPOST;
                tcsetattr(fd, TCSANOW, &tty);

                int w=write(fd, "t", 1);/*printf("%d\n",w);
                fprintf(stderr, "fd = %d.\n", fd);*/
                usleep(1000);
                int n=read(fd,tempbuf,8);/*printf("%d \n",n);*/
                tempbuf[9]=0;
                float temp=atof(tempbuf);

                if (temp>27){
                    printf("CRITICAL: %f celsius\n",temp);
                    return STATE_CRITICAL;
                }else{
                    printf("Everything is OK and the temperature is %f Celsius\n",temp);
                    return STATE_OK;
                }
        }
    }
    close(fd);
    return 0;
}