2012-03-01 67 views
0

我試圖做一個arduino UNO和C程序之間的通信的小實驗。從/ dev/ttyACM0讀取時出現分段錯誤

首先是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); 
} 

問題出現在這裏。當我運行測試時,它會讀取並打印第一個值 ,但在讀取第二個值時會出現分段錯誤。

我實際上不能理解我做錯了什麼。這可能很愚蠢,但似乎我無法把握。

所以我的問題是:我的測試有什麼問題?

在此先感謝誰幫我

回答

2

「分段錯誤」通常只在您觸摸指向無效內存的指針或將不正確類型或數量的參數傳遞給函數時發生。

在任何情況下,首先與她開始的第一件事情就是用-Wall -Werror進行編譯,看看是否有任何應該處理的警告。 (實際上,你應該總是這樣做。)

第二步,對生成的核心轉儲運行gdb並執行回溯 - 查看導致分段錯誤的確切操作。這可能很明顯什麼變量訪問導致了這個問題。

在這種特定情況我認爲這個問題是您的通話scanf函數 - 你使用%U與八位值相結合,並且它可能踐踏各地的內存不應該作爲零件結果。然而,如何調試這些東西的一般原則比你在這裏遇到的特定問題重要得多 - 我會假裝我沒有告訴你它可能是什麼,並且看看是否打開警告並使用gdb並沒有指出你在這個問題上。總有一天你需要知道如何做到這一點。

+0

謝謝您的幫助!我不知道核心轉儲和-Wall -Werror,這真的很有用。最後,它解決了這個問題,所以你也是這樣。 – Animamorta 2012-03-02 16:21:12

0

你確定你可以簡單地打開串口的對應的設備文件而不conio.h亂搞?這是我寫的正是爲了這個目的一些(UNIX)的示例代碼:

https://github.com/H2CO3/serialtool

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

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

你必須使用一個長度修飾符u用於讀取uint8_t

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

(宏在inttypes.h定義)

+0

這是解決方案。謝謝! – Animamorta 2012-03-02 16:22:06