从/ dev / ttyACM0读取时出现分段错误

时间:2012-03-01 21:31:18

标签: c segmentation-fault

我正在尝试在arduino UNO和C程序之间进行一些实验。

首先是arduino角色: 我的arduino设置为每隔2秒从光电阻读取一个模拟值,然后将值写入串口(我的系统上的/ dev / ttyACM0)。

这是arduino的草图:

/* 
  This program will read analog data from a photo resistor and
  will write it to the serial port.
*/

#define LIGHTPIN 0
#define DELAY 2000

void setup()
{
  Serial.begin(9600);
  Serial.flush();
}

void loop()
{
  int lightvalue = 0;

  lightvalue = map(analogRead(LIGHTPIN), 0, 1023, 1, 100);

  Serial.println(lightvalue);

  delay(DELAY);
}

arduino的草图很好;它可以很好地读取数据并将其写入串口。我可以使用串行监视器查看它们。

然后是C程序。 程序应该访问/ dev / ttyACM0并读取数据。它将数据存储在变量中并打印出来。我在ArchLinux系统上,所以访问端口,我想将/ dev / ttyACM0作为文件打开。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdint.h>

#define DELAY 2

int main(int argc, char *argv[])
{
    FILE *serialport = NULL;
    uint8_t lightval = 0;
    uint8_t lastval = 0;

    if ( argc < 2 ) {
        fprintf(stderr, "Too few arguments.\n");
        exit(EXIT_FAILURE);
    }

    if ( !(serialport = fopen(argv[1], "r")) ) {
        fprintf(stderr, "Couldn' t open serial port for communication.\n");
        exit(EXIT_FAILURE);
    }

    while ( true ) {
        fscanf(serialport, "%u", &lightval);

        if ( lightval != lastval ) {
           printf("%u\n", lightval);
           lastval = lightval;
        }

        while (getc(serialport) != '\n')
           continue;

        sleep(DELAY);
   }

   fclose(serialport);
}

问题来了。当我运行测试时,它会读取并打印第一个值 很好,但是当读取第二个值时,它会产生分段错误。

我实际上无法理解我做错了什么。这可能是非常愚蠢的,但似乎我无法掌握它。

所以我的问题是:我的测试出了什么问题?

提前感谢谁将帮助我

3 个答案:

答案 0 :(得分:2)

“分段错误”通常仅在您触摸指向无效内存的指针或向函数传递不正确类型或数量的参数时才会发生。

在每种情况下从她开始的第一件事就是使用-Wall -Werror进行编译,看看是否有任何警告你应该处理。 (事实上​​,你应该一直这样做。)

作为第二步,在生成的核心转储上运行gdb并进行回溯 - 查看导致分段错误的正在执行的操作。然后可能很明显变量访问导致了问题。

在这个特定的实例中我认为问题出在你的scanf调用上 - 你将%u与8位值结合使用,它可能会践踏内存的所有部分结果不应该。但是,如何调试这些东西的一般原则远比你在这里遇到的特殊问题重要 - 我假装我没有告诉你它可能是什么,看看是否打开警告和使用gdb没有指向你遇到了问题。你有一天需要知道怎么做。

答案 1 :(得分:2)

uint8_t lightval = 0
fscanf(serialport, "%u", &lightval);

您必须使用u长度修饰符来阅读uint8_t

fscanf(serialport, "%" SCNu8, &lightval);

(宏在inttypes.h中定义)

答案 2 :(得分:0)

您确定只需打开串口的相应设备文件,而不必弄乱conio.h吗?这是我为此目的编写的一些(Unix)示例代码:

https://github.com/H2CO3/serialtool

然后您可以在端口上使用getc()