linux串口中断怎么配置?linux串口中断处理流程详解

在 Linux 系统中,串口(UART/Serial Port)通信通常可以通过轮询(Polling)或中断(Interrupt)方式实现,中断方式效率更高,因为它允许 CPU 在等待数据时执行其他任务,直到硬件触发中断才处理数据。

以下是关于 Linux 串口中断的详细说明,包括:

【北京迅为】嵌入式学习之Linux驱动(第十七期_串口_全新升级)_基于RK3568开发板
加载中
【北京迅为】嵌入式学习之Linux驱动(第十七期_串口_全新升级)_基于RK3568开发板
  1. 用户空间如何通过中断方式读写串口
  2. 内核空间如何实现串口中断驱动
  3. 常见问题与调试技巧

用户空间:使用中断方式读写串口

在用户空间,Linux 提供了两种主要机制来实现“非阻塞”或“事件驱动”的串口通信:

使用 select() / poll() / epoll()

这是最常用、最推荐的方式,虽然它不是真正的“硬件中断”,但它通过内核的事件通知机制模拟了中断行为,避免忙等待。

示例代码(使用 select):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/select.h>
#include <string.h>
int open_serial_port(const char device) {
    int fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0) {
        perror("open");
        return -1;
    }
    return fd;
}
int main() {
    int fd = open_serial_port("/dev/ttyS0");
    if (fd < 0) return 1;
    // 配置串口(略,实际需设置波特率、数据位等)
    struct termios tty;
    tcgetattr(fd, &tty);
    cfsetispeed(&tty, B9600);
    cfsetospeed(&tty, B9600);
    tty.c_cflag &= ~PARENB;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;
    tty.c_cflag &= ~CRTSCTS;
    tty.c_cflag |= CREAD | CLOCAL;
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    tty.c_iflag &= ~(IXO

linux串口中断怎么配置?linux串口中断处理流程详解

N | IXOFF | IXANY); tty.c_iflag &= ~(INLCR | ICRNL | IGNCR); tty.c_oflag &= ~OPOST; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; tcsetattr(fd, TCSANOW, &tty); fd_set readfds; struct timeval timeout; while (1) { FD_ZERO(&readfds); FD_SET(fd, &readfds); timeout.tv_sec = 1; timeout.tv_usec = 0; int ret = select(fd + 1, &readfds, NULL, NULL, &timeout); if (ret < 0) { perror("select"); break; } else if (ret == 0) { printf("Timeoutn"); continue; } if (FD_ISSET(fd, &readfds)) { char buf[256]; ssize_t n = read(fd, buf, sizeof(buf)); if (n > 0) { printf("Received %d bytes: ", n); fwrite(buf, 1, n, stdout); printf("n"); } } } close(fd); return 0; }

✅ 优点:简单、可移植、无需修改内核。
❌ 缺点:不是真正的硬件中断,仍由内核调度。


使用 SIGIO 信号(真实中断通知)

Linux 支持通过 F_SETSIG 和 FASYNC 实现基于信号的中断通知。

示例代码(使用 SIGIO):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <string.h>
volatile sig_atomic_t got_data = 0;
void sigio_handler(int sig) {
    got_data = 1;
}
int main() {
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd < 0) {
        perror("open");
        return 1;
    }
    // 配置串口(同上,略)
    // 设置进程组 ID 以便接收 SIGIO
    fcntl(fd, F_SETOWN, getpid());
    // 启用异步 I/O 和信号通知
    int flags = f

linux串口中断怎么配置?linux串口中断处理流程详解

cntl(fd, F_GETFL); fcntl(fd, F_SETFL, flags | FASYNC); // 设置信号类型为 SIGIO fcntl(fd, F_SETSIG, SIGIO); struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigio_handler; sigaction(SIGIO, &sa, NULL); char buf[256]; while (1) { if (got_data) { got_data = 0; ssize_t n = read(fd, buf, sizeof(buf)); if (n > 0) { printf("Received: "); fwrite(buf, 1, n, stdout); printf("n"); } } usleep(10000); // 避免忙等待 } close(fd); return 0; }

⚠️ 注意:SIGIO 需要内核支持,并且某些嵌入式平台可能未启用。


内核空间:实现串口中断驱动

如果你需要编写 Linux 内核模块来处理串口中断,你需要实现一个字符设备驱动,并注册中断服务程序(ISR)。

基本步骤:

  1. 分配并初始化 uart_port 结构。
  2. 注册中断处理函数。
  3. 实现 uart_ops 中的 .tx_empty、.set_termios 等回调。
  4. 在中断服务程序中读取 FIFO 数据,并通过 tty_flip_buffer_push() 提交给 TTY 层。

示例:简化的中断处理函数

static irqreturn_t my_uart_isr(int irq, void dev_id) {
    struct my_uart_port port = dev_id;
    unsigned int status;
    // 读取状态寄存器
    status = readl(port->membase + UART_REG_LSR);
    if (status & UART_LSR_DR) {
        // 数据就绪,从数据寄存器读取
        unsigned char data = readb(port->membase + UART_REG_DATA);
        // 将数据放入 TTY 翻转缓冲区
        tty_insert_flip_string(&port->tty->port, &data, 1);
        tty_flip_buffer_push(&port->tty->port);
    }
    if (status & UART_LSR_THRE) {
        //

linux串口中断怎么配置?linux串口中断处理流程详解

发送寄存器为空,可以继续发送 if (!uart_circ_empty(&port->tty->port.xmit)) { // 发送下一个字节 unsigned char ch = port->tty->port.xmit[port->tty->port.xmit_head]; writeb(ch, port->membase + UART_REG_DATA); port->tty->port.xmit_head = (port->tty->port.xmit_head + 1) & (UART_XMIT_SIZE - 1); } } return IRQ_HANDLED; }

注册中断:

int ret = request_irq(irq_number, my_uart_isr, IRQF_SHARED, "my_uart", port);
if (ret) {
    dev_err(&pdev->dev, "Failed to request IRQ %dn", irq_number);
    return ret;
}

常见问题与调试

问题 可能原因 解决方案
收不到中断 中断未使能、引脚复用错误 检查设备树(DTS)中 UART 引脚配置
数据错乱 波特率不匹配、FIFO 未清空 检查波特率设置,清除 FIFO
中断频繁触发 噪声干扰、未屏蔽错误中断 检查 LSR 寄存器,屏蔽错误中断
用户空间收不到数据 TTY 层未正确推送 检查 tty_flip_buffer_push() 是否调用

  • 用户空间:推荐使用 select()/poll() 实现高效非阻塞 I/O,或使用 SIGIO 实现信号驱动。
  • 内核空间:需实现完整的 UART 驱动框架,注册中断服务程序,并通过 TTY 层提交数据。
  • 调试工具:stty、minicom、cat /proc/interrupts、dmesg 等。

如需进一步深入某一部分(如设备树配置、DMA 支持、低功耗模式等),欢迎继续提问!

首发原创文章,作者:王坚‌,如若转载,请注明出处:https://idctop.com/article/487158.html

赞 (0)
excel分数函数怎么用?excel求平均分公式
上一篇 2026年7月12日 13:54
linux系统如何查看硬盘?linux检测硬盘命令
下一篇 2026年7月12日 13:56

相关推荐

  • 4U服务器到底支持多少25G网口,该怎么选?

    4U服务器通常支持2到8个25G网口,具体数量取决于PCIe通道数、网卡规格和整机设计,多数主流机型默认配置4个25G端口,高密度扩展型可达8个甚至更多,25G网口不是“想插多少就插多少”,它背后牵涉PCIe通道分配、网卡形态、散热设计和机房网络架构,搞清楚这些,你才能选对4U服务器,而不是被参数表上的“最大支……

    相关资讯 2026年8月9日
    1100
  • 一台PHP服务器能扛多少并发,php高并发最大连接数是多少?

    PHP一台服务器支持多少并发没有统一数字,它取决于服务器硬件、PHP运行模式、数据库和代码质量;一台4核8G的常规PHP-FPM服务器通常能扛住几百到几千并发连接,优化后还可以更高,并发能力到底由什么决定把PHP并发想成一个餐厅:CPU是厨师,内存是备菜台,PHP进程是服务员,数据库是供应链,哪个环节卡住,整体……

    2026年9月15日
    200
  • 5pb服务器一套多少钱,哪个型号性价比高?

    一套5PB存储服务器的价格并非固定数值,通常在几十万到数百万元人民币之间,具体取决于硬件配置、品牌、服务商以及是否包含运维服务,影响5PB服务器价格的核心因素硬件配置差异如何拉高成本5PB容量意味着需要大量硬盘,传统HDD单盘容量目前最高约24TB,按此计算至少需要约210块硬盘,再加上RAID冗余,实际数量更……

    2026年8月20日
    800
  • 一台服务器到底能部署多少个tomcat,如何配置多实例

    一台服务器部署多少个Tomcat,取决于硬件配置、应用负载和运维策略,通过合理规划,多数情况下部署3-5个实例是平衡性能与资源利用的推荐方案,影响Tomcat部署数目的关键因素内存是第一约束每个Tomcat实例需要独立的堆内存,通常建议设置‑Xmx512m到2g,如果服务器有16GB内存,扣除操作系统和预留开销……

    2026年8月18日
    800
  • x99服务器主板现在多少钱一斤,值得买吗

    x99服务器主板并不按斤计价,二手市场行情通常在每斤30元至80元区间,但实际成交价取决于型号、成色、是否点亮等因素,整板评估远高于废料回收价,x99服务器主板为什么会出现“按斤卖”的说法“多少钱一斤”这个问法,大概率是从废品回收场景流传出来的,不少回收商收电子垃圾时习惯按重量估算,x99主板属于洋垃圾和矿渣中……

    2026年8月13日
    2800
  • 4核8G云服务器最大支持多少并发,并发量怎么算?

    对于4核8G的云服务器,并发量并非固定数值,它取决于应用场景和优化程度,在合理优化的Web应用场景下,大致可支撑500-2000的并发连接数,影响并发量的核心因素应用类型与架构静态资源服务:HTML、图片、CSS等文件,Nginx或Caddy等事件驱动服务器能轻松处理数千并发,4核8G可支撑5000以上连接,瓶……

    2026年8月10日
    800
  • 4核4G服务器能开多少个账号,性能怎么样?

    4核4G服务器能开的账号数量没有固定值,取决于业务类型、架构优化和账号资源占用,常规网站场景下可支撑200到2000个有效账号,轻量级应用极限可破万,4核4G服务器可开多少账号?实测场景拆解与选型指南先算一笔账:4核4G的硬件瓶颈到底在哪很多人一上来就问“能开多少账号”,其实这个问题的本质是并发承载能力和存储计……

    2026年8月23日
    200
  • Anaconda在Linux如何安装?Linux系统安装Anaconda详细教程

    在Linux系统上安装Anaconda最稳妥的方式是下载官方Linux Bash脚本并执行,它能自动配置环境变量并创建独立虚拟环境,彻底解决Python依赖冲突问题,为什么Linux用户首选Anaconda而非pip很多刚接触数据科学或高性能计算的开发者,习惯在Windows上使用Anaconda,迁移到Lin……

    2026年7月7日
    10300
  • 一台服务器能连多少TCP连接?,为什么连接数有限?

    一台服务器能建立的TCP连接数没有硬性上限,核心瓶颈在于内存、文件描述符和端口资源,单机支撑百万级长连接是可行的,先拆清楚:TCP连接数的理论边界很多人第一次听说服务器连接数,脑海里冒出的数字是65535,这个数字并非空穴来风,它来自IPv4协议中源端口的取值范围(0-65535),但注意,这个限制说的是“同一……

    2026年8月30日
    800
  • 4m带宽服务器到底能撑多少点,4m带宽能支持多少并发连接

    4M带宽服务器可以支撑多少并发点?4M带宽服务器在常规企业官网、博客或轻量商城场景下,按单页面平均300KB至500KB、用户平均停留30秒计算,大约能同时承载50到150个访问点;如果跑纯文本API、WebSocket或已做CDN回源优化,并发连接数可冲到几百甚至上千,带宽与“点”之间的换算逻辑这里说的“点……

    2026年9月16日
    000

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注