чтение значения порта (GPIO) в C (beagleboard-xm)

У меня есть встроенная плата (beagleboard-xm), на которой работает Ubuntu 12.04. Мне нужно постоянно читать GPIO, чтобы увидеть, изменится ли значение порта. Мой код ниже:

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

FILE *fp;

int main(void)
{
    //linux equivalent code "echo 139 > export" to export the port
    if ((fp = fopen("/sys/class/gpio/export", "w")) == NULL){
            printf("Cannot open export file.\n");
            exit(1);
        }
        fprintf( fp, "%d", 139 );
        fclose(fp);
      //  linux equivalent code "echo low > direction" to set the port as an input 
        if ((fp = fopen("/sys/class/gpio/gpio139/direction", "rb+")) == NULL){
            printf("Cannot open direction file.\n");
            exit(1);
        }
        fprintf(fp, "low");
        fclose(fp);

       // **here comes where I have the problem, reading the value**
        int value2;
        while(1){
        value2= system("cat /sys/class/gpio/gpio139/value");
        printf("value is: %d\n", value2);
        }
    return 0;
}

приведенный выше код непрерывно считывает порт (0 по умолчанию), однако, когда я меняю порт как 1, system вызов выводит правильное значение, однако printf по-прежнему печатает 0 в качестве вывода. В чем проблема с value2, который не сохраняет значение, которое выводит system().

Если я использую приведенный ниже код вместо цикла while выше, я получаю сообщение об ошибке об открытии файла value (Не удается открыть файл значений.), если я помещаю строку fopen вне цикла while, он не показывает изменения в файле value .

char buffer[10];
while(1){
    if ((fp = fopen("/sys/class/gpio/gpio139/value", "rb")) == NULL){
            printf("Cannot open value file.\n");
            exit(1);
        }
    fread(buffer, sizeof(char), sizeof(buffer)-1, fp);
    int value = atoi(buffer);
    printf("value: %d\n", value);

    }

Мой вопрос: как мне исправить код? или как мне прочитать файл value? В качестве дополнительной информации мне интересно: в чем разница, например. экспортировать порт system("echo 139 > /sys/class/gpio/export") и fp = fopen("/sys/class/gpio/export","w"); fprintf(fp,"%d",139); какой метод вы предлагаете мне использовать? Почему?

Заранее спасибо.


person johan    schedule 07.07.2012    source источник
comment
Вызов system(3) очень затратен — ваш процесс сначала выполняет fork(2), а затем /bin/sh выполняется над дочерним элементом для обработки команды.   -  person Hristo Iliev    schedule 07.07.2012


Ответы (2)


Функция system() возвращает возвращаемое значение cat, равное 0. Она не возвращает стандартный вывод функции cat, которого вы ожидали.

Я думаю, что проблема с вашим вторым фрагментом кода заключается в том, что вы не вызываете fclose(). Поскольку вы работаете в жестком цикле, вы почти сразу же превышаете разрешенное количество открытых файлов.

Итак, позвоните fclose() и подумайте о том, чтобы добавить туда еще и sleep().

person cha0site    schedule 07.07.2012

При чтении файла на C ваша позиция в файле меняется по мере его чтения. Например, если вы должны были открыть файл с содержимым:

First Line
Second Line
Third Line

и запустите эту программу:

char buffer[1024];
while(fgets(buffer, sizeof(buffer), theFile))
{
    printf("Buffer: %s", buffer);
}

Он будет печатать:

First Line
Second Line
Third Line

Когда вы читаете каждую строку, позиция в файле меняется на следующую строку.

В вашей программе, прочитав значение в первый раз, вы пытаетесь прочитать пустое место в файле вместо желаемого значения.

Решение вашей проблемы состоит в том, чтобы переместить fopen за пределы цикла while, но вызывать fseek для сброса вашей позиции в начало файла каждый раз в цикле.

Чтобы использовать fseek, вам нужно передать ему указатель на файл, смещение в байтах и ​​точку поиска. Здесь вы вызываете его в своем файле со смещением 0 байт от путевой точки SEEK_SET, которая указывает на начало файла.

fseek(theFile, 0, SEEK_SET); 
person charliehorse55    schedule 07.07.2012
comment
Вы уверены, что поиск в начале псевдофайла, такого как в /sys, обновляет содержимое, которое доставит ядро? - person Hristo Iliev; 07.07.2012
comment
Не уверен, зависит от того, как это было реализовано. Вы просто должны попробовать это. - person charliehorse55; 07.07.2012