我尝试使用C来读取和写入串行端口的数据。我一直在使用我在网上找到的一个小测试程序。这个想法是让它向arduino发送一个字节,然后返回字符串" Hello",由程序读取。我正在使用open函数遇到打开串口的问题。我的代码在这一点上停滞不前,没有进一步。
fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY);
printf("fd opened as %i\n", fd);
printf("Serial Open Passed!\n");
谁能明白为什么?我在open函数后直接添加了一个printf函数来测试它是否正在完成。我正在使用Mac。完整的代码如下。
C:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>
#define DEBUG 1
int main(int argc, char *argv[])
{
printf("start\n");
int fd, n, i;
char buf[64] = "temp text";
struct termios toptions;
printf("start\n");
/* open serial port */
fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY);
printf("fd opened as %i\n", fd);
printf("Serial Open Passed!\n");
/* wait for the Arduino to reboot */
usleep(3500000);
/* get current serial port settings */
tcgetattr(fd, &toptions);
/* set 9600 baud both ways */
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);
/* 8 bits, no parity, no stop bits */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
/* Canonical mode */
toptions.c_lflag |= ICANON;
/* commit the serial port settings */
tcsetattr(fd, TCSANOW, &toptions);
/* Send byte to trigger Arduino to send string back */
write(fd, "0", 1);
/* Receive string from Arduino */
n = read(fd, buf, 64);
/* insert terminating zero in the string */
buf[n] = 0;
printf("%i bytes read, buffer contains: %s\n", n, buf);
if(DEBUG)
{
printf("Printing individual characters in buf as integers...\n\n");
for(i=0; i<n; i++)
{
printf("Byte %i:%i, ",i+1, (int)buf[i]);
}
printf("\n");
}
return 0;
}
Arduino的: void setup() { Serial.begin(9600); }
void loop()
{
if (Serial.available() > 0)
{
Serial.println("Hello");
Serial.read();
}
}
答案 0 :(得分:0)
就open()而言,你的代码对我来说是正确的。
我相信open()会阻塞,直到另一端可用。它正在等待驾驶员承认可以进行通话,直到那时它耐心等待(固执地)。确保您连接的设备已启动并准备好进行通信。
你也可以尝试标记O_NONBLOCK,它可以设置errno来检查open()失败的原因。
答案 1 :(得分:0)
您可能已经找到了解决方法,但是,如果没有找到答案,则可以找到解决方法:
当连接打开时,@ t-johnson指出,open()函数将等待ACK字节。
我修改了您的Arduino代码:
void setup() {
Serial.begin(9600);
Serial.write(0x01); // I just send back 0x01 as a ACK byte
}
void loop() {
if (Serial.available() > 0) {
Serial.println("Hello");
Serial.read();
}
}
我还必须在打开函数中添加O_NONBLOCK
标志。
我希望它能有所帮助!
答案 2 :(得分:0)
您需要添加O_NDELAY
标志才能打开-在某些硬件平台(UART芯片)上,它可以防止在串行open()
行未处于正常状态时“挂起” DCD
调用。不幸的是,该标志会影响非规范模式下的read()
行为,但是也有解决方案:特定的fcntl()
调用。
因此,请尝试以下操作:
// use NDELAY flag
fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY | NDELAY);
if (fd < 0) {
// handle open error here
}
// fcntl() call to get read() working properly in non-canonical mode
fcntl(fd, F_SETFL, 0);