GPOS прерывания sysfs

У меня возникли некоторые проблемы с функцией c ++, которую я использую для отслеживания прерываний GPIO на обычном устройстве Linux. Я передаю прямоугольный сигнал известной частоты на вывод GPIO, но результат вывода следующего кода ошибочен. Если я установлю метод определения края на «падение», рассчитанная частота будет правильной. Однако, если я использую обнаружение «повышения», выходная частота является спорадической и неправильной. Я хотел бы иметь возможность использовать «оба» для расчета коэффициента заполнения.

int gpio::interrupts(string gpioNumber)
{
int fd;
int retval;
struct timeval holder;
struct timeval tvCurrent;
double usPrevious;
double usCurrent;
double diff;
struct pollfd pfd;
char buf[64];
int error = -1;

string openD = "/sys/class/gpio/gpio" + gpioNumber + "/value";
error = fd = open(openD.c_str(), O_RDONLY);

while (error < 0) {
error = fd = open(openD.c_str(), O_RDONLY);
}

pfd.fd = fd;
pfd.events = POLLPRI;

lseek(fd, 0, SEEK_SET);

while(1) {
retval = poll(&pfd, 1, -1);
if (pfd.revents & POLLPRI) {

lseek(fd, 0, SEEK_SET);

retval = read(fd, buf, sizeof buf);

//The following std::cout will be discussed in the following section
//std::cout << "Thread: " << std::this_thread::get_id() << " GPIO: " << gpioNumber << " Value : " << retval << std::endl;

gettimeofday(&tvCurrent, NULL);

//tvPrevious is a list of lists declared in the header
if (tvPrevious[std::stoi(gpioNumber)][0] != 0 && tvPrevious[std::stoi(gpioNumber)][1] != 0) {
usPrevious = (tvPrevious[std::stoi(gpioNumber)][0]*1e6) + tvPrevious[std::stoi(gpioNumber)][1];
usCurrent = (tvCurrent.tv_sec*1e6) + tvCurrent.tv_usec;

diff = (usCurrent - usPrevious)/1e6;

//Replace the previous frequency record for this gpio
//in the existing list. The list is declared in the header
//and initialised in another function
gpioFrequencies.replace(std::stoi(gpioNumber), 1/diff);

emit gpioFrequenciesChanged();

tvPrevious[std::stoi(gpioNumber)][0] = tvCurrent.tv_sec;
tvPrevious[std::stoi(gpioNumber)][1] = tvCurrent.tv_usec;

tvCurrent.tv_sec = 0;
tvCurrent.tv_usec = 0;

} else {
gettimeofday(&holder, NULL);
tvPrevious[std::stoi(gpioNumber)][0] = holder.tv_sec;
tvPrevious[std::stoi(gpioNumber)][1] = holder.tv_usec;
holder.tv_sec = 0;
holder.tv_usec = 0;
}
}
}

return 0;
}

Вторая проблема, с которой я столкнулся в приведенном выше коде, заключается в чтении значения gpio из файла / sys / class / gpio / gpioX / value. Комментируемый std::cout в приведенном выше коде используется для проверки того, что каждый gpio работает в отдельном отдельном потоке, и для чтения значения файла / значения gpio. Использую ли я «повышение», «падение» или «оба» для обнаружения края, значение retval всегда 2. Я ожидаю, что значение будет 1 (ВЫСОКОЕ) или 0 (НИЗКОЕ).

Итак, два моих вопроса следующие:

  1. Как я могу изменить вышеприведенный код, чтобы обеспечить не только обнаружение «падения», но и «повышение» и «оба»?
  2. Как я могу изменить приведенный выше код, чтобы обеспечить успешное, правильное чтение файла / значения после срабатывания прерывания?

РЕДАКТИРОВАТЬ: я ответил на вопрос 2 (чтение значения GPIO), добавив следующие строки после retval = read(fd, buf, sizeof buf);:

buf[1]='\0';
string output = string(buf);

output теперь содержит правильное значение 1 (HIGH) или 0 (LOW) указанного GPIO.

РЕДАКТИРОВАТЬ 2: Я только что определил, что причина колебания частоты была из-за моих периодов измерения вычисления частоты и для нарастающего и для падающего фронта. Я добавил if (std::stoi(string(buf) > 0) Заявление до расчета периода, и теперь частота измеряется правильно.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]