我正在尝试fgets
在 esp-idf 中使用从 UART 读取整行。
基本参考代码是选择示例。到目前为止,这是我的代码:
#define DLP_RFID2_BUF_SIZE 256
static char buffer[DLP_RFID2_BUF_SIZE];
uart_config_t uart_config =
{
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, DLP_RFID2_BUF_SIZE * 2, 0, 0, NULL, 0));
ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, PIN_DLP_RFID2_TX, PIN_DLP_RFID2_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
if ((fd = open("/dev/uart/1", O_RDWR)) == -1)
{
ESP_LOGE(TAG, "Cannot open UART");
return fd;
}
uart_vfs_dev_use_driver(UART_NUM_1);
这里是循环函数:
int s;
fd_set rfds;
struct timeval tv = {
.tv_sec = 0,
.tv_usec = 20000,
};
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
s = select(fd + 1, &rfds, NULL, NULL, &tv);
if (s < 0)
{
ESP_LOGE(TAG, "Select failed: errno %d (%s)", errno, strerror(errno));
}
else if (s == 0)
{
ESP_LOGI(TAG, "Timeout has been reached and nothing has been received");
}
else
{
if (FD_ISSET(fd, &rfds))
{
if (fgets(buffer, sizeof(buffer), ???))
{
// do something
}
}
else
{
ESP_LOGE(TAG, "No FD has been set in select()");
}
}
fgets函数需要一个FILE *
变量作为第三个参数。但我只有int
s ( fd
, s
) 和fd_set
( rfds
)。
我尝试更改代码以便使用FILE *
:
FILE *f = fopen("/dev/uart/1", "rw");
// ...
if (fgets(buffer, sizeof(buffer) - 1, f))
{
// do something
}
由于fgets
是阻塞的,我需要先检查是否有一些数据。但现在select
需要一个fd_set
而不是一个FILE *
:
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
我怎样才能“转换”FILE *
为fd_set
或?int
FILE *
select
您的问题是您需要对(2)使用文件描述符,但FILE
对fgets
(3) 则需要一个。这里有两种可能性。
给定一个
FILE
对象,您可能能够使用该函数fileno
来获取要在中使用的相应文件描述符select
。或者,如果您最初使用(2)打开文件
open
以获取文件描述符,则您可能能够使用fdopen
(3)从中创建一个FILE
对象。我说两种情况都可能是,因为C 标准中都没有定义
fileno
和,所以如果你处在受限环境中(你提到的 UART 暗示了这一点),它们可能不可用。不过,它们都得到了非常广泛的实施,所以如果你的库足够大,可以有,它肯定会有其中至少一个。fdopen
fgets
请注意,不能保证这些函数一定有效。C 标准 (2018,第 7.21 节) 规定
FILE
结构...因此,它没有提到任何有关文件描述符的内容,并且具体来说,它不要求结构包含任何使
fileno
或fdopen
工作的信息。因此,从理论上讲,这里所有的赌注都是错的,并且 C 库以这种方式实现是相当合法的FILE
。但这在大多数“正常”的 C 环境中是不寻常的。