Ошибка сегментации при чтении из / dev / ttyACM0 - PullRequest
0 голосов
/ 02 марта 2012

Я пытаюсь провести небольшой эксперимент со связью между Arduino UNO и программой на Си.

Сначала роль 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 ]

2 голосов
/ 02 марта 2012

«ошибка сегментации» - это то, что обычно происходит, только когда вы касаетесь указателя на недопустимую память или передаете в функцию неправильные типы или числа параметров.

Первое, что нужно начинать с нее в каждомcase компилируется с -Wall -Werror и проверяет, есть ли какие-либо предупреждения, с которыми вам следует иметь дело.(На самом деле, вы просто должны всегда делать это.)

В качестве второго шага запустите gdb для полученного дампа ядра и выполните обратную трассировку - посмотрите, какую именно операцию вы выполняли, которая вызвала ошибку сегментации,Тогда может быть очевидно, какая проблема связана с доступом к переменным.

В данном конкретном случае Я думаю, что проблема в вашем вызове scanf - вы используете% u в сочетании свосьмибитное значение, и это, вероятно, растоптало все части памяти, чего не должно быть в результате.Тем не менее, общий принцип отладки этих вещей гораздо важнее, чем конкретная проблема, с которой вы здесь столкнулись - я бы сделал вид, что не сказал вам, что это может быть, и посмотрим, не указывает ли включение предупреждений и использование GDB.Вы в проблеме.Тебе нужно будет когда-нибудь узнать, как это сделать.

2 голосов
/ 02 марта 2012
uint8_t lightval = 0
fscanf(serialport, "%u", &lightval);

Вы должны использовать модификатор длины с u для чтения uint8_t.

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

(макрос определен в inttypes.h)

0 голосов
/ 02 марта 2012

Вы уверены, что можете просто открыть соответствующий файл устройства последовательного порта, не возиться с conio.h? Вот некоторый (Unix) пример кода, который я написал именно для этой цели:

https://github.com/H2CO3/serialtool

затем вы можете использовать getc() для порта.

...