gpt4 book ai didi

c - 如何在 Linux 上正确设置串口通信

转载 作者:IT王子 更新时间:2023-10-29 01:22:25 26 4
gpt4 key购买 nike

我正在尝试从 FPGA 板上读取数据或向其中写入数据。开发板本身带有一个驱动程序,只要插入开发板,它就会创建一个名为 ttyUSB0 的终端设备。在 FPGA 上,实现了一个异步接收器和发送器,它们似乎可以正常工作。

但是,C 端似乎存在问题。我一直在使用一些测试 vector 来测试 FPGA 是否正在输出正确的信息。我注意到了一些事情:

  1. 设备有时无法正常打开
  2. 有时会出现获取或设置终端属性失败的情况。
  3. 读取有时是非阻塞的,并且不会检索到正确的值。

下面是我如何设置终端和文件描述符选项。其中大部分取自此处:http://slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming

关于程序可能失败的原因的任何建议或评论都会非常有帮助。

#include <stdio.h>   // Standard input/output definitions
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions

int open_port(void){

int fd; // File descriptor for the port
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);

if (fd == -1){
fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno));
exit(EXIT_FAILURE);
}

return (fd);
}

int main(void){

int fd = 0; // File descriptor
struct termios options; // Terminal options

fd = open_port(); // Open tty device for RD and WR

fcntl(fd, F_SETFL); // Configure port reading
tcgetattr(fd, &options); // Get the current options for the port
cfsetispeed(&options, B230400); // Set the baud rates to 230400
cfsetospeed(&options, B230400);

options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode
options.c_cflag &= ~PARENB; // No parity bit
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CSIZE; // Mask data size
options.c_cflag |= CS8; // Select 8 data bits
options.c_cflag &= ~CRTSCTS; // Disable hardware flow control

// Enable data to be processed as raw input
options.c_lflag &= ~(ICANON | ECHO | ISIG);

// Set the new attributes
tcsetattr(fd, TCSANOW, &options);

////////////////////////////////////
// Simple read and write code here//
////////////////////////////////////

// Close file descriptor & exit
close(fd)
return EXIT_SUCCESS
}

更新我已经根据第一个答案修改了我的代码。这就是我现在拥有的:

#include <errno.h>      // Error number definitions
#include <stdint.h> // C99 fixed data types
#include <stdio.h> // Standard input/output definitions
#include <stdlib.h> // C standard library
#include <string.h> // String function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <termios.h> // POSIX terminal control definitions

// Open usb-serial port for reading & writing
int open_port(void){

int fd; // File descriptor for the port
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);

if (fd == -1){
fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno));
exit(EXIT_FAILURE);
}

return fd;
}

int main(void){

int fd = 0; // File descriptor
struct termios options; // Terminal options
int rc; // Return value

fd = open_port(); // Open tty device for RD and WR

// Get the current options for the port
if((rc = tcgetattr(fd, &options)) < 0){
fprintf(stderr, "failed to get attr: %d, %s\n", fd, strerror(errno));
exit(EXIT_FAILURE);
}

// Set the baud rates to 230400
cfsetispeed(&options, B230400);

// Set the baud rates to 230400
cfsetospeed(&options, B230400);

cfmakeraw(&options);
options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode
options.c_cflag &= ~CSTOPB; // 1 stop bit
options.c_cflag &= ~CRTSCTS; // Disable hardware flow control
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 2;

// Set the new attributes
if((rc = tcsetattr(fd, TCSANOW, &options)) < 0){
fprintf(stderr, "failed to set attr: %d, %s\n", fd, strerror(errno));
exit(EXIT_FAILURE);
}

////////////////////////////////
// Simple Read/Write Code Here//
////////////////////////////////

// Close file descriptor & exit
close(fd);
return EXIT_SUCCESS;
}

澄清一下,接收器和发送器使用 8 个数据位、1 个停止位且没有奇偶校验位。

最佳答案

我更喜欢 Serial Programming Guide for POSIX Operating Systems .

您应该删除 fcntl(mainfd, F_SETFL) 语句,因为它不是必需的且实现不正确(F_GETFL 之前未完成且缺少第三个参数)。

尝试使用 cfmakeraw设置非规范模式,因为您的初始化代码不完整:

options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
options->c_oflag &= ~OPOST;

对于非规范模式,还需要定义

options.c_cc[VMIN]  = 1;
options.c_cc[VTIME] = 2;

1 和 2 只是建议值。

所有 系统调用后添加返回状态测试。

rc = tcgetattr(mainfd, &options);
if (rc < 0) {
printf("failed to get attr: %d, %s\n", mainfd, strerror(errno));
exit (-3);
}

尝试使用较慢的波特率(例如 115200 甚至 9600)进行测试。

关于c - 如何在 Linux 上正确设置串口通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15890903/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com