news 2026/6/10 17:22:14

简单理解:USART_IID_THRE、USART_IID_RDA、USART_IID_CTI 都是嵌入式串口 中断类型的标识宏的用法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
简单理解:USART_IID_THRE、USART_IID_RDA、USART_IID_CTI 都是嵌入式串口 中断类型的标识宏的用法

USART_IID_THREUSART_IID_RDAUSART_IID_CTI都是嵌入式串口中断类型的标识宏(对应 IIR 寄存器的低 4 位编码),核心区别在于 “触发场景” 和 “功能用途”—— 分别对应「发送中断」「接收数据中断」「接收收尾中断」,三者分工明确、互补覆盖串口收发的全场景。

下面用 “一句话定义 + 核心区别表 + 实际场景对比”,帮你彻底分清:

一、三者核心定义(一句话讲透)

宏定义中文含义核心作用(触发场景)
USART_IID_THRE发送保持寄存器空中断串口发送寄存器(THR)的数据发完后触发,告诉 CPU:“可以写下一个要发送的数据了”(用于连续发送)
USART_IID_RDA接收数据有效中断串口收到新数据(存入接收寄存器 RHR)后触发,告诉 CPU:“有新数据可以读了”(用于接收数据)
USART_IID_CTI字符超时指示中断串口收到部分数据后,超时未收到下一个数据触发,告诉 CPU:“当前批次数据收完了”(用于不定长接收收尾)

二、关键区别对比(维度拆解)

对比维度USART_IID_THREUSART_IID_RDAUSART_IID_CTI
所属方向发送侧中断接收侧中断接收侧中断(辅助收尾)
触发条件发送寄存器(THR)为空(数据已发完)接收寄存器(RHR)非空(收到新数据)收到部分数据后,超时未收到下一个
核心用途驱动连续发送(从缓冲区读下一个数据)驱动数据接收(把新数据存入缓冲区)不定长数据收尾(通知 CPU 停止等待)
使用场景批量发送、大数据量发送(如传感器批量上传)所有接收场景(固定长 / 不定长数据)仅不定长数据接收(如自定义协议指令)
是否单独使用是(发送逻辑独立)可单独用(固定长数据)否(必须和 RDA 配合)
编码值示例0x02(8250/51 单片机)、0x04(部分 STM32)0x04(8250)、0x01(部分 MCU)0x0C(LPC 系列)、0x08(瑞萨)

三、实际使用场景对比(结合代码逻辑)

用三个典型场景,看三者如何配合工作:

场景 1:批量发送 1000 个数据(用USART_IID_THRE
// 中断服务函数中 if ((USART_GetIntID(XT_UART0) & 0xF) == USART_IID_THRE) { if (发送计数器 < 1000) { USART_SendData(XT_UART0, 缓冲区[计数器++]); // 发下一个数据 } else { 禁用THRE中断;// 数据发完,停止触发 } }
  • 逻辑:THRE 中断反复触发,每次触发都从缓冲区读一个数据发送,直到 1000 个数据发完。
场景 2:接收固定长 8 字节数据(用USART_IID_RDA
// 中断服务函数中 if ((USART_GetIntID(XT_UART0) & 0xF) == USART_IID_RDA) { 缓冲区[接收计数器++] = USART_ReceiveData(XT_UART0); if (接收计数器 == 8) { // 固定长8字节,收满即完成 置位接收完成标志; 接收计数器 = 0; } }
  • 逻辑:每收到 1 个数据触发 RDA 中断,存到缓冲区,收满 8 个字节就通知主函数处理。
场景 3:接收不定长指令(用USART_IID_RDA + USART_IID_CTI
// 中断服务函数中 if (((USART_GetIntID(XT_UART0) & 0xF) == USART_IID_RDA) || ((USART_GetIntID(XT_UART0) & 0xF) == USART_IID_CTI)) { // RDA触发:读新数据存入缓冲区;CTI触发:读剩余数据 while (接收寄存器有数据) { 缓冲区[指针++] = 读数据(); } if (是CTI中断) { // 超时收尾,通知主函数处理不定长数据 置位接收完成标志; } }
  • 逻辑:RDA 负责 “收数据”,CTI 负责 “告诉 CPU 收完了”,完美解决 “不知道数据多长” 的问题。

四、核心总结(3 句话记牢)

  1. 发送用THRE:数据发完了,CPU 快给下一个;
  2. 接收收数据用RDA:收到新数据了,CPU 快读走;
  3. 接收收尾用CTI:好久没新数据了,CPU 别等了,数据收完了。

三者都是 “中断类型的识别标签”,不同厂商编码值可能不同,但功能和分工是行业通用的 ——THRE 管发送连续,RDA 管接收数据,CTI 管接收收尾,共同支撑串口高效收发。


void UART1_IRQHandler(void) // UART1中断处理函数 { u32 RxValidNum = 0; // 接收有效数据数量 //UART发送保持寄存器空中断 // 检查是否为发送保持寄存器空中断 if ((USART_GetIntID(XT_UART1) & 0xF) == USART_IID_THRE) { USART_SendData((XT_UART1), G_USART_SendDataBuf[G_USART_SendDataCount++]); // 发送数据缓冲区中的数据 while(USART_GetLineStatus(XT_UART1, USART_LSR_TE)==RESET); // 等待发送完成 if(G_USART_SendDataCount >= USART_COUNT_MAX){ // 检查是否发送完成 G_USART_SendDataCount = 0; // 重置发送计数 USART_IntConfig((XT_UART1), USART_IER_THREIE, DISABLE); // 禁用发送中断 G_USART_SendCplFlag = TRUE; // 设置发送完成标志 return; // 返回 } } //接收FIFO中断和超时中断 // 检查是否为接收中断或超时中断 if (((USART_GetIntID(XT_UART1) & 0xF) == USART_IID_RDA) || ((USART_GetIntID(XT_UART1) & 0xF) == USART_IID_CTI)) { /**读取FIFO有效数据*/ // 读取FIFO中有效数据数量 RxValidNum = USART_GetFIFOStatus(XT_UART1,USART_FIFO_RX); for(int i = 0; i < RxValidNum; i++){ // 循环读取所有有效数据 G_USART_RecvDataBuf[G_USART_RecvDataCount++] = USART_ReceiveData(XT_UART1); // 读取数据到接收缓冲区 if(G_USART_RecvDataCount >= USART_COUNT_MAX){ // 检查接收缓冲区是否溢出 G_USART_RecvDataCount -= USART_COUNT_MAX; // 重置接收计数(环形缓冲区) } } } NVIC_ClearPendingIRQ(UART0_IRQn); // 清除UART0中断挂起标志(注:此处应为UART1_IRQn,可能是代码bug) }

发送侧无论固定长 / 不定长数据,都只需要考虑USART_IID_THRE(唯一的发送中断);接收侧只有处理 “不定长数据” 时,才需要同时考虑USART_IID_RDA + USART_IID_CTI;如果是 “固定长数据”,只需要USART_IID_RDA就够了 ——USART_IID_CTI是 “不定长接收” 的专属补充,不是接收的 “必选项”。

用更简洁的方式总结,帮你明确适用场景:

工作方向需考虑的中断标识适用场景核心原因
发送USART_IID_THRE固定长、不定长数据都适用发送是 CPU 主动控制,THRE 负责 “连续发下一个”,无需额外中断收尾
接收USART_IID_RDA固定长数据(如每次收 8 字节)数据长度已知,收满预设长度就判定 “收完”,无需超时判断
接收USART_IID_RDA + USART_IID_CTI不定长数据(如自定义指令)RDA 负责 “收数据”,CTI 负责 “超时收尾”,避免漏读或无限等待

再强调两个关键细节,帮你避免误解:

  1. USART_IID_CTI不是接收的 “标配”:比如你接收的是传感器固定格式输出(每次必发 10 字节),只需要RDA中断 —— 每次触发 RDA 就读数据,计数器到 10 就判定收完,完全用不上CTI

  2. 发送不用第二个中断的核心原因:发送时 CPU 知道 “要发多少数据”(比如缓冲区有 500 字节、或发完0x0D 0x0A结束符就停),THRE中断只负责 “上一个发完了,下一个接上”,发送完成的判断靠 “计数器达标” 或 “结束符发送完毕”,逻辑闭环,不需要额外中断帮忙 “收尾”。

结合你贴的代码再印证:

  • 你的发送代码只判断USART_IID_THRE,完全正确(不管发送数据是固定长还是不定长,都够用);
  • 你的接收代码判断RDA + CTI,说明你要处理不定长数据(比如外部设备随机发送的指令),这个搭配是最优解 —— 既保证批量数据高效接收(RDA),又避免收尾数据漏读(CTI)。

最终结论:发送固定只看USART_IID_THRE;接收看数据类型 —— 固定长只看RDA,不定长看RDA+CTICTI是不定长接收的 “专属补充”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 12:45:11

如何用R语言在1小时内完成数据探索全流程?这套工作流请收好

第一章&#xff1a;R语言数据探索的核心价值R语言在现代数据分析领域中扮演着至关重要的角色&#xff0c;尤其在数据探索阶段展现出强大的灵活性与深度。其丰富的统计函数和可视化工具使数据科学家能够快速理解数据分布、识别异常值并发现潜在模式。交互式数据概览 使用R内置函…

作者头像 李华
网站建设 2026/6/4 19:15:16

电影预告片剪辑:紧张悬疑氛围的语音情绪塑造

电影预告片剪辑&#xff1a;紧张悬疑氛围的语音情绪塑造 在一部悬疑电影的预告片中&#xff0c;灯光未亮&#xff0c;画面尚黑——只有一句低语缓缓响起&#xff1a;“他……一直就在你身后。” 声音沙哑、节奏迟滞&#xff0c;尾音微微颤抖。观众还没看清什么&#xff0c;脊背…

作者头像 李华
网站建设 2026/6/10 14:48:35

联想拯救者工具箱:释放笔记本性能潜力的终极解决方案

联想拯救者工具箱&#xff1a;释放笔记本性能潜力的终极解决方案 【免费下载链接】LenovoLegionToolkit Lightweight Lenovo Vantage and Hotkeys replacement for Lenovo Legion laptops. 项目地址: https://gitcode.com/gh_mirrors/le/LenovoLegionToolkit 联想拯救者…

作者头像 李华
网站建设 2026/6/10 9:56:30

【零截断数据分析突围方案】:资深统计专家20年经验倾囊相授

第一章&#xff1a;R语言零截断数据建模概述在统计建模中&#xff0c;零截断数据指观测中完全缺失取值为零的记录&#xff0c;常见于生态学、保险理赔和医学研究等领域。这类数据不能直接使用标准计数模型&#xff08;如泊松或负二项回归&#xff09;进行分析&#xff0c;否则会…

作者头像 李华
网站建设 2026/6/10 9:55:33

LeagueAkari:3大核心功能帮你彻底告别LOL操作烦恼

LeagueAkari&#xff1a;3大核心功能帮你彻底告别LOL操作烦恼 【免费下载链接】LeagueAkari ✨兴趣使然的&#xff0c;功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAkari 你是否曾经因…

作者头像 李华
网站建设 2026/6/10 9:59:12

揭秘R语言中GPT函数的隐藏用法:90%的数据科学家都不知道的3大功能

第一章&#xff1a;R语言中GPT函数的真相揭秘在R语言生态系统中&#xff0c;并不存在名为“GPT”的内置函数或官方支持的包函数。这一名称常被误解或误传&#xff0c;尤其在初学者社区中&#xff0c;容易让人误以为R语言原生集成了生成式预训练变换模型&#xff08;Generative …

作者头像 李华