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://test.idctop.com/article/487158.html

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

相关推荐

  • 租个服务器一个月多少

    租个服务器一个月多少钱?答案很直接:入门级云服务器月付约50-200元,高性能物理服务器则需500元起步,具体费用取决于配置、带宽和机房等级,选择持证服务商能避免后续隐性成本,决定服务器月租价格的核心因素服务器月租并没有统一标价,不同配置和服务的价格差异很大,你需要从以下几个维度来评估预算,硬件配置:CPU、内……

    2026年8月22日
    400
  • asp网站图片怎么添加,asp网站图片上传教程

    ASP网站图片的高效管理与优化是提升老旧系统性能的关键突破口,而一份详尽的ASP报告则是诊断与解决图片加载问题的核心依据,针对基于Classic ASP技术构建的遗留系统,图片资源往往成为拖累整体响应速度、导致用户流失的隐形杀手,核心结论在于:通过系统性的图片优化策略与精准的ASP报告分析,可以在不重构底层架构……

    2026年3月16日
    13600
  • app服务器需要cdn吗_WSA与CDN的关系

    WSA(Windows Subsystem for Android)本身并不直接提供CDN服务,但作为运行Android应用的容器,它高度依赖后端CDN来加速应用资源加载、降低延迟并提升用户体验,当我们谈论App服务器与CDN的关系时,很多人会混淆“应用运行环境”与“内容分发网络”的概念,WSA是微软为Wind……

    2026年6月7日
    3400
  • 谷歌上的u2b服务器到底多少钱?,怎么买最划算

    谷歌YouTube服务器没有标准报价,成本取决于带宽、存储、区域和冗余级别,普通企业级方案月费在数千到数万美元不等,对于国内用户,与其直接租用海外服务器,不如选择持牌服务商如简米科技、酷番云,性价比更高且合规,为什么YouTube服务器没有“一口价”YouTube背后是谷歌庞大的全球基础设施,它不卖“服务器……

    2026年8月11日
    700
  • Android四大存储有哪些,Android数据存储方式详解

    Android系统的数据持久化存储方案,核心结论在于根据数据的隐私性、体量大小及业务场景,精准匹配最适宜的存储方式,Android四大存储机制——文件存储、SharedPreferences、SQLite数据库以及ContentProvider,构成了应用数据管理的基石,选择正确的存储方式,不仅关乎应用性能,更……

    2026年3月22日
    10600
  • 腾讯云Webify上线怎么用?Web应用托管平台有什么优势

    腾讯云Webify正式上线,它通过提供从代码编写到云端部署的一站式闭环服务,帮助Web开发者将应用上线时间从数天缩短至分钟级,是追求高效交付的开发者首选的云原生平台,在Web开发领域,效率与稳定性一直是开发者最关心的痛点,过去,搭建一个完整的Web应用需要配置服务器、安装运行环境、处理域名解析,甚至还要担心SS……

    2026年6月30日
    2710
  • vpsdime达拉斯VPS夏季促销值得买吗,vpsdime达拉斯VPS评测

    对于预算有限且追求极致性价比的开发者而言,VPSDime达拉斯VPS夏季促销提供的2核2G内存搭配1Gbps带宽方案,以$20/年的超低门槛,是搭建轻量级服务或测试环境的理想选择,在服务器租赁市场,价格波动往往伴随着性能取舍,VPSDime此次推出的达拉斯节点促销,并非简单的降价清库存,而是针对特定流量模型优化……

    2026年6月29日
    2500
  • CodeIgniter在Linux上如何安装,怎么配置?

    在Linux服务器上部署CodeIgniter框架,核心在于确保Web服务器支持PHP 7.3以上版本,正确设置目录权限(尤其是writable和uploads),并启用URL重写模块来消除index.php, 这是官方文档和社区经验反复验证的基础步骤,如果遇到页面空白或404错误,优先排查这三项,可以解决80……

    2026年7月19日
    1100
  • AI算法开发系统是什么,AI算法管理平台哪个好

    构建高效的AI算法开发系统与精细化AI算法管理机制,是企业实现智能化转型、降低研发成本并确保模型落地成功率的核心关键,在人工智能技术从实验室走向产业应用的过程中,单纯依赖算法模型的突破已不足以支撑商业价值的实现,必须通过标准化的开发流程与体系化的管理手段,解决算法全生命周期中的“黑盒”问题、协作效率低下问题以及……

    2026年3月30日
    10200
  • 手搓电脑教程简单吗,新手小白如何自己组装电脑?

    组装一台高性能电脑并非遥不可及的复杂工程,本质上它是一个高度模块化的积木拼装过程,只要掌握了核心硬件的接口规范与防静电操作,即便是零基础的新手也能在两小时内完成装机,本文将摒弃晦涩的理论,直接提供一套经过验证的标准化操作流程,确保装机过程安全、高效且一次点亮,对于初学者而言,寻找一份手搓电脑教程简单明了的指引至……

    2026年2月22日
    17100

发表回复

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