У меня возникли некоторые проблемы с функцией 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 (НИЗКОЕ).
Итак, два моих вопроса следующие:
РЕДАКТИРОВАТЬ: я ответил на вопрос 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)
Заявление до расчета периода, и теперь частота измеряется правильно.
Задача ещё не решена.
Других решений пока нет …