我一直在寻找并阅读文档,但我正处于需要帮助的地步。用例相对简单,但实现是我被困住的地方。
一端是无线Xbee无线电。该无线电每300ms发送一次信号。该信号的有效载荷包括按钮状态和操纵杆位置。
在接收端是基于Linux的SBC,运行Ubuntu,附带Xbee。为了这篇文章,我将以下内容合并到一个文件中,并添加了一个main以便于阅读:
#include <stdio.h>
#include <stdlib.h>
#include <linux/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <unistd.h>
#include "XbeeReceiver.h"
#define FALSE 0
#define TRUE 1
volatile int STOP = FALSE;
void signal_handler_IO(int status);
int wait_flag = TRUE;
int fileDescriptor = -1;
/* Constants */
const char *DEFAULT_PORT = "/dev/ttyTHS1";
const int DEFAULT_BAUD = B115200;
/* Prototypes */
struct N64_DTO queryController(int fd);
void init(const char *port, const int baud);
void setTermConfig(int fd, const int baud);
void signal_handler_IO(int status);
int openUART(const char *port);
void init(const char *port, const int baud) {
fileDescriptor = openUART(port ? port : DEFAULT_PORT);
setTermConfig(fileDescriptor, baud ? baud : DEFAULT_BAUD);
while (STOP == FALSE) {
if (wait_flag == FALSE) {
struct N64_DTO controller = queryController(fileDescriptor);
printf("\n\n\n Y Joystick:: %i \n", (signed char) controller.y);
printf("X Joystick:: %i \n", (signed char) controller.x);
/* I am supposed to set STOP to TRUE for this loop to stop, however I always want to read from the controller,
which is why this is now blocking */
wait_flag = TRUE;
}
}
}
struct N64_DTO queryController(int fd) {
struct N64_DTO controller;
int byteCount = read(fd, (char *) &controller, sizeof(struct N64_DTO));
if (byteCount == -1) {
printf("I'll handle this error later on");
exit(1);
}
return controller;
}
void signal_handler_IO(int status) {
printf("received SIGIO signal.\n");
wait_flag = FALSE;
}
void setTermConfig(int fd, const int baud) {
struct sigaction saio;
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask);
sigaddset(&saio.sa_mask, SIGINT);
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO, &saio, NULL);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, FASYNC);
struct termios toptions;
tcgetattr(fd, &toptions);
cfsetspeed(&toptions, baud);
/* man termios for individual definitions */
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
toptions.c_cflag &= ~CRTSCTS;
toptions.c_cflag |= CREAD | CLOCAL;
toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
toptions.c_oflag &= ~OPOST;
toptions.c_cc[VMIN] = sizeof(struct N64_DTO);
toptions.c_cc[VTIME] = 0;
tcsetattr(fd, TCSANOW, &toptions);
tcflush(fd, TCIFLUSH);
}
int openUART(const char *port) {
return open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
}
int main(int argc, char *argv[]) {
int i;
init("/dev/ttyTHS1", 115200);
for (i = 0; i < 10; i++) {
printf("This loop never prints..");
}
return 0;
}
虽然它需要更多重构,但这段代码可以正常运行并为我提供预期的输出。然而,现在我有输出,我想用它做一些事情,即作为输入发送到电机控制器等。问题是,由于读取的频率(300ms),程序最终阻止任何其他例程执行。
几周前我回到了绘图板,开始了几条不同的路径。我探索了线程,信号处理程序,利用poll / select API以及创建专用内核模块的可能性。上周,出于不同的原因,我将控制器放在示波器上并设置触发信号的上升沿。那是它袭击我的时候。我想要的是一个事件驱动模型,当特定串行端口上检测到信号时,OS会通知我。我想我会伸手去看看是否有人在这方面有经验,愿意引导我朝着正确的方向前进。我已经在这个问题上待了一个星期,但仍然没有取得任何进展。最后,我们的目标是不断阻止来自端口的串行数据,而不会阻塞我的应用程序的其他部分(驱动电机,移动伺服系统)。