我正在开发一个项目,让我的计算机与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,我无法弄清楚问题是什么。 提前谢谢。
答案 0 :(得分:3)
我无法弄清楚问题是什么
一个大问题是在“计算机”上运行的C程序是不完整的。
Arduino的程序执行至少波特率的串行端口设置(以及默认情况下可执行的任何其他操作)。
但“计算机”C程序从未正确配置串口。串行端口将使用先前配置的任何属性(波特率,数据长度,奇偶校验设置,规范与原始模式),这将导致不可预测的读取和写入。 (环回测试可能会产生误报结果。)
使用POSIX Serial Port guide或this answer获取示例代码。
对于规范模式,您可能需要添加代码(假设为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()
选项。
答案 1 :(得分:0)
试试这个
int n=read(fd,&tempbuf,sizeof(tempbuf));
而不是
int n=read(fd,tempbuf,5);
答案 2 :(得分:0)
你不应该终止用'\ 0'发送的数据吗? 哔叽
答案 3 :(得分:0)
阅读read()的描述(如下所示)告诉我们当你到达文件末尾时n = 0。由于串行未发送\ 0,因此读取将继续,直到到达文件末尾。因此我认为n == 0是你想要的结果。
所以,也许是你的 if(n> 0)
测试应该是 if(n == 0)
您能否使用调试器在缓冲区中看到您期望的字符?
读() #包括 int read(int handle,void * buffer,int nbyte);
read()函数尝试从与handle相关联的文件中读取nbytes,并将读取的字符放入缓冲区。如果使用O_TEXT打开文件,它将删除回车并检测文件的结尾。
该函数返回读取的字节数。在文件结束时,返回0,如果错误则返回-1,设置errno以指示发生的错误类型。
答案 4 :(得分: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;
}