2

我正在做一个项目,让我的计算机与 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);
    }
  }
}

当我试图读取 arduino 放在串行端口上的内容时,我的问题出在 C 代码中。我的 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;
}

n 总是= 0,我不知道是什么问题。提前致谢。

4

5 回答 5

3

我不知道是什么问题

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

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

使用POSIX 串行端口指南此答案获取示例代码。

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

    rc = tcgetattr(fd, &tty);
    if (rc < 0) {
        /* handle error */
    }
    savetty = tty;    /* preserve original settings for restoration */

    spd = B9600;
    cfsetospeed(&tty, (speed_t)spd);
    cfsetispeed(&tty, (speed_t)spd);

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

    tty.c_cflag &= ~CRTSCTS;    /* no HW flow control? */
    tty.c_cflag |= CLOCAL | CREAD;

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

    rc = tcsetattr(fd, TCSANOW, &tty);
    if (rc < 0) {
        /* handle error */
    }

您可能应该删除该行

fcntl(fd, F_SETFL, FNDELAY);  

以及通话 中的O_NONBLOCK选项。open()

于 2013-07-17T00:35:31.860 回答
0

试试这个

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

代替

int n=read(fd,tempbuf,5);
于 2013-07-16T12:12:27.813 回答
0

你不应该终止用'\0'发送的数据吗?哔叽

于 2013-07-16T14:00:54.450 回答
0

阅读 read() 的描述(如下所示)告诉我们,当您到达文件末尾时,n = 0。由于串行没有发送 \0,读取将继续,直到到达文件末尾。因此我认为 n==0 是你想要的结果。

所以,也许你的 if (n>0)

测试应该是 if (n==0)

您可以使用调试器在缓冲区中看到您期望的字符吗?

read() #include int read( int handle, void *buffer, int nbyte );

read() 函数尝试从与句柄关联的文件中读取 nbytes,并将读取的字符放入缓冲区。如果使用 O_TEXT 打开文件,它会删除回车并检测文件的结尾。

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

于 2013-07-16T16:37:43.587 回答
0

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

#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;
}
于 2013-07-18T10:23:37.083 回答