UART高级功能实战:硬件流控制、9位多机模式与FIFO深度优化

📅 2026/7/22 14:31:40
UART高级功能实战:硬件流控制、9位多机模式与FIFO深度优化
1. 项目概述与核心价值搞嵌入式开发尤其是涉及到串口通信UART绝对是个绕不开的老朋友。但很多人对它的理解可能还停留在“配置波特率、数据位、停止位”的初级阶段一旦遇到数据量大、速率高或者需要多机通信的场景就容易抓瞎。数据丢失、通信卡死、CPU被频繁中断占用……这些问题背后往往是对UART高级功能的理解不够深入。今天我就结合自己这些年踩过的坑和积累的经验把UART里几个关键但容易被忽略的“硬核”功能——硬件流控制、9位多机模式以及FIFO的深度操作——掰开揉碎了讲清楚。这些功能不是摆设而是你构建稳定、高效、可靠串行通信系统的基石。无论你是在做工业控制、智能家居网关还是复杂的传感器网络吃透这些机制能让你在调试时少掉几根头发让系统运行得更稳。简单来说硬件流控制RTS/CTS就是给数据流动装上“红绿灯”防止接收方缓冲区溢出导致数据被冲掉9位模式则是为了一根总线上挂多个设备时实现精准的“点名呼叫”而FIFO操作和中断配置直接关系到你的CPU是轻松惬意还是疲于奔命。这篇文章我会从原理、寄存器操作到实战配置和避坑指南带你彻底掌握这些技术。我会假设你已经有基本的UART使用经验知道如何配置波特率所以我们会直奔这些高级主题目标是让你看完就能用用了就见效。2. 硬件流控制RTS/CTS深度解析与实战2.1 硬件流控制的核心原理为什么需要它想象一下用漏斗往瓶子里灌水。如果水龙头开得太大而漏斗下方的出水口又很细水很快就会从漏斗边缘溢出来。在UART通信中发送端就是水龙头接收端的缓冲区比如FIFO就是那个漏斗。当发送速度持续高于接收方的处理速度时接收缓冲区满了新来的数据无处可放就会被直接丢弃这就是“数据溢出”Overrun Error。硬件流控制就是为解决这个问题而生的物理层“握手”协议。它不依赖于数据内容而是通过额外的两根信号线——RTSRequest To Send请求发送和CTSClear To Send清除发送——来实时协调双方的收发节奏。这是一种带外Out-of-band的信令方式效率高且可靠。其工作逻辑是一个典型的“反压”机制接收方视角接收方通过UnRTS输出引脚告知对方自己的缓冲区状态。当接收FIFO快满了例如达到预设的3/4或7/8水位它就拉低UnRTS信号注意通常是低电平有效相当于对发送方说“我快吃不消了你慢点发。”发送方视角发送方持续监测自己的UnCTS输入引脚。只有当UnCTS信号被对方置为有效通常为低电平时它才被允许发送数据。一旦发现UnCTS无效变高它必须立即停止发送当前字节如果正在发送并在完成后暂停等待UnCTS再次有效。这相当于发送方在问“我现在能发吗”只有收到“可以发送CTS有效”的答复后才行动。这里有一个关键点在常见的UART控制器如TI的Tiva系列中UnRTS是输出反映自身接收FIFO状态UnCTS是输入控制自身发送权限。两个设备连接时需要交叉连接设备A的UnRTS接设备B的UnCTS设备B的UnRTS接设备A的UnCTS。很多人第一次接硬件流控制线就接反了导致功能完全失效。2.2 寄存器级配置详解以Tiva系列MCU的UART为例硬件流控制的启用和模式选择完全由UARTCTL寄存器控制寄存器的两个位决定位名称功能描述15CTSENCTS流控制使能。1使能发送受UnCTS引脚控制。14RTSENRTS流控制使能。1使能UnRTS引脚自动反映接收FIFO状态。这两个位的组合定义了四种工作模式RTSENCTSEN模式描述11全硬件流控制发送受CTS控制接收方RTS自动指示FIFO状态。最常用、最完整的模式。01仅CTS使能发送受CTS控制但接收方不自动产生RTS信号UnRTS引脚可由软件控制。适用于只需要控制本方发送速率的场景。10仅RTS使能发送不受CTS控制一直发但接收方会自动产生RTS信号。适用于只需要告知对方自身状态的场景对方可能采用软件方式响应。00流控制禁用默认状态。发送和接收都不受流控制引脚影响。重要提示当RTSEN位被设置为1后UnRTS引脚将由硬件自动管理软件无法再通过UARTCTL寄存器中的RTS位如果存在来手动控制该引脚的电平。此时读取该RTS位的状态是无意义的。这一点在调试时需要注意别在代码里傻乎乎地去写那个位然后发现没效果。2.3 实战配置步骤与代码示例假设我们要在Tiva MCU上使能UART0的全硬件流控制并配置接收FIFO的水位触发点为1/2即FIFO半满时拉低RTS。步骤一硬件连接与引脚复用首先确保你的硬件上已将UART0的U0CTS和U0RTS引脚连接到对方设备的RTS和CTS并且正确交叉。然后在代码中配置这些引脚为UART功能。// 使能UART0和GPIOA端口的时钟 SYSCTL-RCGCUART | (1 0); // 使能 UART0 SYSCTL-RCGCGPIO | (1 0); // 使能 GPIOA __asm__ volatile(nop); // 插入少量延时等待时钟稳定 __asm__ volatile(nop); // 配置PA0(U0RX), PA1(U0TX), PA2(U0RTS), PA3(U0CTS) GPIOA-AFSEL | (1 0) | (1 1) | (1 2) | (1 3); // 启用引脚复用功能 GPIOA-PCTL ~((0xF (0*4)) | (0xF (1*4)) | (0xF (2*4)) | (0xF (3*4))); // 清除原有配置 GPIOA-PCTL | ((1 (0*4)) | (1 (1*4)) | (1 (2*4)) | (1 (3*4))); // PA0,1,2,3 复用为UART0功能 GPIOA-DEN | (1 0) | (1 1) | (1 2) | (1 3); // 使能数字功能步骤二配置UART基本参数与FIFO在使能UART模块前先配置波特率、数据格式等。同时为了使用硬件流控制我们必须先使能FIFO因为RTS的水位判断依赖于FIFO。// 1. 暂时禁用UART0以便配置 UART0-CTL ~(UART_CTL_UARTEN); // 2. 配置波特率 (假设系统时钟80MHz目标波特率115200) uint32_t ui32Divisor (80000000 * 64) / (16 * 115200); // 先计算BRD * 64 UART0-IBRD ui32Divisor / 64; // 整数部分 UART0-FBRD ui32Divisor % 64; // 小数部分 // 3. 配置数据格式8位数据1位停止位无校验使能FIFO UART0-LCRH UART_LCRH_WLEN_8 | UART_LCRH_FEN; // 4. 配置接收FIFO中断触发水位为1/2 (可选如果使用中断) // UART0-IFLS (UART0-IFLS ~UART_IFLS_RX_M) | UART_IFLS_RX1_2; // 对于纯硬件流控制可以不设中断但FIFO水位仍用于RTS控制 // RTS信号在水位达到UARTIFLS寄存器中设置的RX触发点时变化复位默认是1/2。步骤三使能硬件流控制这是最关键的一步配置UARTCTL寄存器。// 使能硬件流控制 (RTS和CTS) UART0-CTL | (UART_CTL_RTSEN | UART_CTL_CTSEN); // 最后使能UART模块 UART0-CTL | UART_CTL_UARTEN;2.4 注意事项与避坑指南连接错误务必记住“交叉连接”A.RTS - B.CTS, A.CTS - B.RTS。接成直连A.RTS接B.RTS是新手最常见的错误会导致流控制完全不起作用。电平逻辑确认你的UART控制器和对方设备可能是另一个MCU、模块PC的RTS/CTS引脚是低电平有效还是高电平有效。TI Tiva系列通常是低电平有效Active Low。有些USB转串口芯片或PC端软件可能需要配置反相逻辑。如果不匹配流控制信号会一直处于“禁止”状态。FIFO必须使能硬件流控制尤其是RTS自动生成依赖于FIFO功能。如果UARTLCRH寄存器中的FEN位为0FIFO禁用那么RTSEN位即使置1UnRTS引脚也不会根据缓冲区状态自动变化。此时它可能是一个固定的电平或由软件控制。使能时机建议在配置完所有UART参数波特率、数据位等并使能FIFO后最后再设置RTSEN和CTSEN位。有些控制器要求UART在禁用状态下配置这些控制位。调试方法当通信异常时用示波器或逻辑分析仪同时抓取TX、RX、RTS、CTS四根线。观察当接收方FIFO快满时其RTS是否变低请求对方暂停同时观察发送方的CTS是否随之变低以及TX线是否在完成当前字节后停止产生新的起始位。这是最直接的验证手段。3. 9位UART模式多机通信的寻址利器3.1 9位模式解决了什么问题在传统的8位UART通信中如果总线上挂了多个从机设备比如RS-485总线主机发出的数据帧对所有从机都是可见的。如何让数据只被指定的从机接收呢一个笨办法是每个数据帧都包含一个地址头所有从机都接收完整帧然后在软件里判断地址是否匹配不匹配则丢弃。但这意味着每个从机的CPU都会被中断并消耗资源去处理不属于自己的数据包效率低下。9位模式提供了一种硬件级的过滤机制。它在每个数据字节的标准8位数据之外增加了一个额外的位通常称为“第9位”或“地址/数据标识位”。这个位不用于传输普通数据而是用来标记当前字节的性质第9位 1表示这个字节是一个“地址字节”。第9位 0表示这个字节是普通的“数据字节”。这样从机可以在硬件层面进行判断只有当地址字节第9位为1与自身预设的地址匹配时才使能接收中断或DMA开始接收后续的数据字节第9位为0。不匹配的从机则完全忽略整个数据块CPU不会被无关数据打扰。这大大提升了多机系统的效率和实时性。3.2 硬件工作原理与寄存器配置以Tiva UART为例9位模式涉及几个关键寄存器UART9BITADDR(9位自地址寄存器)用于设置从机自身的地址。当收到一个第9位为1的字节时硬件会将接收到的8位数据与这个寄存器中的地址进行比较。UART9BITAMASK(9位地址掩码寄存器)默认值为0xFF表示进行精确匹配。你可以将其设置为其他值来实现地址组匹配。例如地址设置为0xA0掩码设置为0xF0那么所有地址在0xA0到0xAF之间的地址字节都会被匹配掩码为1的位参与比较为0的位忽略。这允许你对从机进行分组寻址。UARTLCRH寄存器中的9BITEN位实际上在Tiva中9位模式使能位9BITEN位于UART9BITADDR寄存器中。设置该位为1即启用9位模式。奇偶校验位的妙用在9位模式下接收器工作在无奇偶校验模式。那么第9位从哪里来呢对于发送方为了发送一个地址字节第9位为1需要“借用”奇偶校验位。具体操作是软件临时将奇偶校验配置为“固定奇校验”Sticky Parity, Odd这样硬件会自动在发送字节的奇偶校验位上产生一个‘1’从而模拟出第9位为1的效果。发送数据字节时再切回无校验或普通校验第9位即为0。工作流程如下主机发送地址帧主机先配置为固定奇校验发送目标从机地址。这个字节的第9位由奇偶位模拟为1。从机硬件过滤所有从机收到该字节。硬件自动检查第9位是否为1并比较8位数据是否与自身UART9BITADDR经掩码过滤后匹配。匹配成功匹配的从机会产生一个特殊中断地址匹配中断并开始接收后续所有第9位为0的数据字节存入FIFO。匹配失败不匹配的从机硬件自动忽略该地址字节及后续所有第9位为0的数据字节不会产生接收中断FIFO也不会被写入。主机发送数据主机切换回无校验模式发送数据流。这些数据字节的第9位均为0。通信结束通常主机可以通过发送一个特定的“广播地址”或再次发送地址帧来切换对话对象。3.3 实战代码配置从机9位模式假设一个从机地址为0x2A我们将其配置为9位模式。// 1. 禁用UART UART0-CTL ~(UART_CTL_UARTEN); // 2. 配置标准UART参数波特率、数据位等注意数据长度通常还是设置为8位 UART0-LCRH UART_LCRH_WLEN_8 | UART_LCRH_FEN; // 8位数据使能FIFO // 3. 配置9位模式相关寄存器 UART0-UART9BITADDR 0x2A; // 设置自身地址为 0x2A UART0-UART9BITAMASK 0xFF; // 设置地址掩码为精确匹配 (0xFF) UART0-UART9BITADDR | UART_9BITADDR_9BITEN; // 使能9位模式 // 4. 配置中断如果需要地址匹配中断 UART0-IM | UART_IM_9BITIM; // 使能9位地址匹配中断 NVIC_EnableIRQ(UART0_IRQn); // 使能NVIC中断 // 5. 使能UART UART0-CTL | UART_CTL_UARTEN;中断服务函数(ISR)中需要处理void UART0_Handler(void) { uint32_t status UART0-MIS; // 读取屏蔽后的中断状态 if (status UART_MIS_9BITMIS) { // 9位地址匹配中断 // 地址匹配成功可以准备接收数据 // 注意此时地址字节本身不会进入FIFO除非你配置了相应选项。 // 通常在这里设置一个标志通知主循环开始处理后续数据。 g_bAddressMatched true; // 清除中断标志 UART0-ICR UART_ICR_9BITIC; } if (status UART_MIS_RXMIS) { // 接收中断数据字节 if (g_bAddressMatched) { // 读取数据直到FIFO为空或达到预期长度 while (!(UART0-FR UART_FR_RXFE)) { uint8_t data UART0-DR 0xFF; // 读取数据低8位 // 处理数据... } } else { // 不应该进入这里因为地址不匹配时硬件应屏蔽数据接收。 // 如果进入了说明可能是配置错误或总线干扰。 // 清空FIFO中的无效数据 while (!(UART0-FR UART_FR_RXFE)) { volatile uint8_t dummy UART0-DR; } } UART0-ICR UART_ICR_RXIC; } // ... 处理其他中断 }3.4 注意事项与常见问题发送方的“魔术”主机在发送地址字节时需要临时切换到“固定奇校验”模式来产生第9位‘1’。这需要软件精确控制。一个常见的做法是在发送地址前修改UARTLCRH寄存器的奇偶校验设置发送完地址字节后立即改回来。务必确保这个切换过程发生在字节发送之间而不是一个字节的发送过程中。FIFO不存储第9位文档明确指出发送FIFO不保存地址/数据位信息。这意味着第9位的信息需要由软件在将数据写入UARTDR寄存器前通过配置奇偶校验位来“实时”生成。对于地址字节用固定奇校验对于数据字节用无校验或普通校验。地址匹配中断与数据中断使能9位模式后通常需要使能9BITIM中断来获知地址匹配事件。同时也需使能普通的接收中断(RXIM)来接收后续数据。在地址匹配之前RXIM中断应该被有效抑制由硬件完成。广播通信可以利用地址掩码寄存器(UART9BITAMASK)实现广播。例如设置掩码为0x00那么任何地址字节都会匹配所有从机都会接收后续数据。或者定义一个特定的广播地址如0xFF所有从机都将该地址纳入自己的匹配范围。与DMA的配合在9位模式下使用DMA需要格外小心。DMA控制器通常只负责搬运UARTDR中的数据位8位它不感知第9位。因此地址过滤和后续数据的DMA传输使能必须由CPU在地址匹配中断中手动配置和启动。4. FIFO操作、中断与DMA的协同优化4.1 FIFO从单字节到缓冲队列的飞跃复位后UART的发送和接收缓冲区是单字节的“保持寄存器”。这意味着每收/发一个字节就可能产生一次中断CPU频繁被打断效率极低。使能FIFOFirst In First Out先进先出功能相当于给UART加了一个小型的队列缓冲区Tiva系列是16x8位即16字节深。使能FIFO非常简单只需设置UARTLCRH寄存器的FEN位为1。一旦使能数据读写都将通过FIFO进行这对软件来说是透明的你依然读写UARTDR寄存器但硬件会自动管理FIFO的指针。FIFO状态监控主要通过UARTFR标志寄存器RXFE接收FIFO空。为1时表示没有数据可读。RXFF接收FIFO满。为1时表示FIFO已满新数据会丢失除非有硬件流控制。TXFE发送FIFO空。为1时表示发送移位寄存器空闲且FIFO为空。TXFF发送FIFO满。为1时表示不能再写入数据。4.2 中断触发水位精细控制CPU干预时机这是FIFO使用的精髓所在。你肯定不希望FIFO每收到一个字节就中断一次那和没开FIFO一样。UART允许你配置FIFO在达到特定填充程度时才触发中断从而让CPU批量处理数据大幅减少中断次数。配置寄存器是UARTIFLS中断FIFO电平选择寄存器。它可以独立设置发送和接收FIFO的触发点配置值触发水位说明0b0001/8FIFO填充到2字节16*1/8时触发0b0011/4FIFO填充到4字节时触发0b0101/2复位默认值填充到8字节时触发0b0113/4FIFO填充到12字节时触发0b1007/8FIFO填充到14字节时触发接收中断逻辑当接收FIFO中的数据量达到或超过你设置的触发水位时RXRIS原始中断状态位被置1。如果中断被使能(RXIM1)则产生中断。中断的清除有两种方式1) 通过读取UARTDR寄存器将FIFO中的数据量降低到低于触发水位2) 直接向UARTICR寄存器的RXIC位写1来清除中断标志。注意方式1是“自动”的方式2是“手动”的。如果你用手动清除但FIFO数据量仍然高于触发水位中断标志会立刻再次置起。发送中断逻辑发送中断的逻辑稍有不同它是穿越式的。当发送FIFO中的数据量从高于触发水位变为低于或等于触发水位时TXRIS位被置1。举个例子如果触发水位是1/28字节当你一次性写入12个字节高于水位后开始发送随着数据发送FIFO中数据量减少当减少到8字节或以下时触发中断。这个设计是为了让CPU有机会在发送缓冲区快空时及时补充数据避免发送断流。中断的清除同样有两种方式1) 通过写入UARTDR寄存器将FIFO中的数据量补充到高于触发水位2) 直接向UARTICR寄存器的TXIC位写1。配置示例将接收中断触发点设为3/412字节发送中断触发点设为1/44字节。UART0-IFLS (UART_IFLS_RXIFLSEL_3_4 | UART_IFLS_TXIFLSEL_1_4); // 然后使能接收和发送中断 UART0-IM | (UART_IM_RXIM | UART_IM_TXIM);这样的配置意味着CPU通常会在收到12个字节后才被中断一次然后一次性读取多个字节而在发送时当FIFO里只剩下4个字节时CPU就会收到中断提醒去填充数据保持发送流水线不断。4.3 超时中断处理“零碎”数据包接收超时中断RTIM是一个非常有用的功能。设想一下你设置接收中断触发水位是1/28字节但如果对方只发送了5个字节的数据包接收FIFO永远达不到8字节岂不是永远不会触发中断数据就会一直躺在FIFO里直到天荒地老。超时中断就是为了解决这个问题。当接收FIFO非空但在一段时间内32或64个位时间取决于HSE位没有收到任何新数据时就会产生超时中断。这相当于一个“数据包结束”的信号即使数据量很少也能及时通知CPU来处理。使能和配置方法// 使能接收超时中断 UART0-IM | UART_IM_RTIM; // 超时周期由UARTCTL寄存器的HSE位决定通常保持默认HSE032位时间即可。在中断服务程序中你需要检查UARTMIS寄存器的RTMIS位。当超时中断发生时即使FIFO中数据量很少你也应该将其全部读出。4.4 与DMA的强强联合对于大数据量、高带宽的串口传输频繁的中断仍然可能成为瓶颈。此时直接内存访问DMA是终极解决方案。UART可以与µDMA控制器协同工作实现数据在内存和UART FIFO之间的自动搬运完全解放CPU。DMA请求类型单次请求对于接收只要接收FIFO中有数据就会请求对于发送只要发送FIFO中有空位就会请求。适合小数据量或实时性要求高的场景。突发请求对于接收当接收FIFO中的数据量达到或超过UARTIFLS中设置的触发水位时请求对于发送当发送FIFO中的空余位置达到或超过触发水位时请求。适合大数据块的连续传输。配置步骤配置UART的DMA控制寄存器(UARTDMACTL)// 使能接收和发送通道的DMA UART0-DMACTL | (UART_DMACTL_RXDMAE | UART_DMACTL_TXDMAE); // 可选设置发生接收错误时自动禁用DMA接收请求防止错误数据覆盖内存 // UART0-DMACTL | UART_DMACTL_DMAERR;配置µDMA控制器这涉及另一个模块的寄存器核心是设置源地址对接收是UARTDR对发送是内存缓冲区、目标地址、传输数据量、传输模式如Ping-Pong模式等。这是另一个复杂话题但一旦配好效率提升是惊人的。处理DMA完成中断DMA传输完成后UART可以产生中断通过设置DMARXIM或DMATXIM。在中断中你可以重新配置DMA描述符准备下一轮传输。一个关键细节DMA的完成信号(dma_done)只表示数据已经从内存搬到了UART的发送FIFO或者从接收FIFO搬到了内存。它不代表数据已经通过串口线物理发送完毕。如果你需要知道最后一个比特何时离开串口需要使能UARTCTL寄存器中的EOTEnd Of Transmission位并监视相应的中断标志。4.5 避坑经验与性能调优FIFO使能顺序务必在禁用UART (UARTEN0)的情况下配置UARTLCRH寄存器以启用FIFO(FEN1)。如果在UART使能状态下修改可能导致不可预知的行为。中断标志清除永远在中断服务程序ISR的开始处读取UARTMIS或UARTRIS寄存器来确定中断源并在处理完相应事件后立即向UARTICR寄存器的对应位写1来清除中断标志。拖延清除可能导致中断丢失或重复进入。水位选择策略高吞吐量场景设置较高的接收触发水位如7/8和较低的发送触发位如1/4。这能最大化减少中断次数让DMA或CPU批量处理数据同时保证发送不卡顿。低延迟场景对于需要快速响应的短命令设置较低的接收触发水位如1/8甚至禁用FIFO并启用超时中断。确保任何小的数据包都能被及时处理。混合场景结合使用高水位中断和超时中断。高水位中断处理大数据块超时中断处理残留的小数据包。DMA缓冲区管理使用DMA时务必确保你提供的源/目标内存缓冲区是物理连续的并且对齐到合适边界通常4字节。使用“Ping-Pong”双缓冲区可以避免处理数据时DMA覆盖正在使用的缓冲区。总线冲突与错误处理在多机通信或长距离通信中使能错误中断溢出OE、帧错误FE、奇偶校验错误PE、线路中断BE至关重要。在错误中断中除了清除标志一定要读取一次UARTDR寄存器即使你不关心数据这样才能将错误状态从FIFO中移除否则可能锁死后续接收。如果使能了DMAERR在发生接收错误时DMA会自动停止你需要在软件中处理错误后重新使能DMA。5. 软件流控制与调制解调器状态虽然硬件流控制是首选但在引脚资源紧张或连接线不足时如只有TX、RX、GND三根线软件流控制XON/XOFF协议是一种备选方案。它不依赖额外的硬件信号线而是通过插入特殊的控制字符XON: 0x11, XOFF: 0x13到数据流中来控制流量。Tiva UART本身不直接实现XON/XOFF协议这需要软件在应用层实现。但是它提供了监控调制解调器Modem状态信号的能力这些信号如DSR数据设备就绪、DCD数据载波检测、RI振铃指示除了用于传统的电话调制解调器也可以被灵活用作通用的数字输入信号通过中断来通知CPU。通过配置UARTIM寄存器中的DSRIM,DCDIM,CTSIM,RIIM位可以使能这些引脚状态变化时的中断。这在需要检测外部设备连接状态如DCD表示载波可引申为“设备在线”、或响应外部事件如RI振铃可引申为“唤醒信号”时非常有用。6. 回环测试与调试技巧在开发阶段回环测试Loopback是验证UART驱动程序底层是否正确工作的绝佳方法。将UART配置为内部回环模式自己发送的数据会被自己接收无需连接外部硬件。配置方法极其简单// 在禁用UART的状态下设置回环模式位 UART0-CTL | UART_CTL_LBE; // 然后再使能UART UART0-CTL | UART_CTL_UARTEN;在回环模式下TX引脚上的输出被内部连接到RX引脚输入。你可以编写一个简单的测试程序发送一串数据然后读取接收到的数据对比是否一致。这可以快速排除软件驱动配置错误如波特率计算、数据格式将问题定位在硬件连接或外部设备上。最后的建议UART是一个相对简单的模块但其高级功能组合起来能应对复杂场景。最好的学习方式是在理解原理后动手写代码测试。从一个最简单的回环测试开始逐步加入FIFO、中断、硬件流控制观察系统行为的变化。使用逻辑分析仪抓取波形是理解这些硬件信号交互过程最直观的方式。当你清晰地看到CTS信号变低后TX线停止发送或者捕捉到那个特殊的第9位为1的地址帧时这些知识才真正变成了你自己的经验。