【问题标题】:Communication with Arduino using Linux使用 Linux 与 Arduino 通信
【发布时间】:2015-01-01 10:30:22
【问题描述】:

这是我第一次使用我的电脑与 Arduino 通信。我使用 Ubuntu 14.04。这是用于写入文件的 C 程序。 Arduino 显示 ttyACM0。

使用 gcc 编译时,编译器显示错误提示:

分段错误(核心转储)

我该如何纠正这个错误。

#include<unistd.h>
#include<stdio.h>
int main() {
  char data[] = {'f','b','r'};  //Random data we want to send
  FILE *file;
  file = fopen("/dev/ttyACM0","w");  //Opening device file
  int i = 0;
  for(i = 0 ; i < 3 ; i++) {
    fprintf(file,"%c",data[i]); //Writing to the file
    fprintf(file,"%c",','); //To separate digits
    sleep(1);
  }
  fclose(file);
}

原谅我的无知。我试着研究它。无法让它工作。提前感谢您的帮助。

【问题讨论】:

  • 它看起来不像c++ 代码。那为什么要打标签呢?
  • 这是一个想法 - 你可以尝试调试它。

标签: c++ c linux file arduino


【解决方案1】:

您从fopen() 获得NULL 返回,NULL 被传递给 fprintf(),它期望一个有效的 FILE* 并搞砸导致 SEGV

如果你使用fopen,你应该检查它返回的内容,这样你就可以给用户一个比“分段错误”更有用的东西。

fopen()失败的可能原因是你没有权限玩串口。

通常您需要dialout 组才能访问串行端口。

作为根用户:

usermod -a -G dialout你的用户名

然后注销并重新登录,以便获得新组。

考虑使用 minicom 或 microcom(在其他几个串行终端程序中的任何一个上)来访问串行端口,而不是自己编写。

我还建议你让 Arduino 在启动时发送一个问候消息,这样你就可以确定你有正确的波特率等......

【讨论】:

  • 可能是fopen失败的原因,但不是SIGSEGV的原因。
  • 所以你也应该提一下,忽略fopen的结果是错误的。
【解决方案2】:

您没有对fopen("/dev/ttyACM0","w"); 的返回值进行任何成功检查。如果fopen() 失败,进一步使用file 是未定义的行为,导致分段错误。做类似的事情

file = fopen("/dev/ttyACM0","w");  //Opening device file
if (file)
{
        //do something with file
}
else
     return 0;

另外,在结束 main() 之前添加一个return 0

【讨论】:

  • else 是干什么用的?为什么不返回错误代码而不是0
  • @iharob 其他部分说 文件打开失败。不要使用文件指针。关于返回值,没有标准,你可以使用任何对你有意义的值。 :-)
  • 但是从main返回0意味着没有发生错误,并且else不是必需的,如果file != NULL可以返回0和一些默认值。
  • @iharob 好吧,这取决于。大多数情况下,对于 API,您是对的。但是,IMO 失败 fopen() 通常不意味着 main() 失败。一条错误消息就足够了。
  • 我不同意你的观点。
【解决方案3】:
// the following code:
//  compiles cleanly
//  performs appropriate error checking
//  has proper return statement

#include <unistd.h> // sleep()
#include <stdio.h>  // fopen(), fclose(), fprintf(), perror()
#include <stdlib.h> // exit() and EXIT_FAILURE

int main()
{
    char data[] = {'f','b','r'};  //Random data we want to send
    FILE *file;
    if( NULL == (file = fopen("/dev/ttyACM0","w") ) )  //Opening device file
    { // then fopen failed
        perror("fopen failed for ttyACM0" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    int i = 0;
    for(i = 0 ; i < 3 ; i++)
    {
        if( 0 >= fprintf(file,"%c",data[i]) ) //Writing to the file
        { // fprintf failed
            perror("fprintf data failed" );
            exit( EXIT_FAILURE );
        }

        // implied else, fprintf successful for data

        if( 0 >= fprintf(file,"%c",',') ) //To separate digits
        { // then, fprintf failed
            perror( "fprintf for comma failed");
            exit( EXIT_FAILURE );
        }

        // implied else, fprintf successful for comma

        sleep(1);
    } // end for
    fclose(file);
    return(0);
} // end function: main

【讨论】:

  • 这段代码,经过适当的错误检查,应该通过 stderr 告诉 OP 问题的根源。
  • 显然“ttyACM0 的 fopen 失败:访问被拒绝”
【解决方案4】:

失败时fopen 返回NULL,因此您可能会取消引用NULL 指针,这样做的正确方法是检查fopen 的结果。但是,我建议为这种事情使用低级 IO,例如

#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

int main()
{
    char data[] = {'f','b','r'};  //Random data we want to send
    int fd;
    int i;

    fd = open("/dev/ttyACM0", O_WRONLY);  //Opening device file
    if (fd == -1)
    {
        perror("cannot open /dev/ttyACM0");
        return -1;
    }

    for(i = 0 ; i < 3 ; i++)
    {
        write(fd, &(data[i]), 1);
        write(fd, ",", 1);

        sleep(1);
    }
    close(fd);

    return 0;
}

在错误open 返回一个特殊值-1 所以你应该中止写入它。

我很确定在你的情况下会有一个permission denied 错误,因为通常/dev/tty* 属于组dialout 并且默认情况下它们具有组写权限,但是因为可能你的用户不属于对该组您没有对/dev/ttyACM0 的写入权限。

【讨论】:

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