深入解析S12XS MCU串行通信接口:从SCI基础到红外与LIN应用 📅 2026/6/19 14:08:34 1. 串行通信接口SCI的核心价值与设计哲学在嵌入式系统开发中串行通信接口SCI就像一位沉默而可靠的邮差负责在微控制器MCU与外部世界之间传递信息。无论是调试信息的打印、传感器数据的读取还是模块间的指令交互SCI都扮演着不可或缺的角色。它基于异步通信协议无需共享时钟线仅凭两根线TXD发送RXD接收就能实现全双工数据交换这种简洁与高效使其成为嵌入式领域的“通用语言”。我接触过不少MCU的SCI模块从早期的8位机到复杂的32位ARM内核其核心思想一脉相承但具体实现上的“魔鬼细节”往往决定了通信的稳定性和效率。飞思卡尔现为NXPS12XS系列MCU中的S12SCIV5模块就是一个非常经典且功能丰富的代表。它不仅仅实现了基础的UART功能更集成了对红外IrDA物理层和LIN总线协议的原生硬件支持这让我们在开发遥控器、车载网络节点等特定应用时能大幅减轻软件负担提升系统响应速度和可靠性。理解SCI绝不能停留在“配置波特率、读写数据寄存器”的层面。我们需要深入其内部工作机制数据如何被拆分成帧、波特率误差如何被容忍、噪声如何被甄别、以及如何利用硬件特性去支持更复杂的通信标准。本文将以S12SCIV5模块为蓝本结合我多年的调试经验拆解从数据寄存器操作到红外、LIN支持的全过程让你不仅知道如何配置更明白为什么要这样配置以及在实践中如何避开那些让人头疼的“坑”。2. SCI数据寄存器读写背后的门道与效率陷阱SCI通信的所有数据交互最终都落在两个关键的寄存器上SCI数据寄存器高字节SCIDRH和低字节SCIDRL。很多新手会认为这不过是两个存储数据的地址但它们的访问时机、位域定义以及对9位数据模式的支持里面藏着不少讲究。2.1 数据寄存器的结构化解析根据手册SCIDRH和SCIDRL的位域定义非常清晰SCIDRL (地址偏移 0x0007): 这是一个8位寄存器直接对应数据字节的低8位Bit 7-0。无论是读取还是写入它都映射到实际的数据缓冲区。SCIDRH (地址偏移 0x0006): 这个寄存器只有Bit 7和Bit 6是有效的分别对应接收第9位R8和发送第9位T8。其余位保留。这里的关键在于“9位数据格式”。当SCI控制寄存器1SCICR1中的M位被置1时SCI工作在9位模式。此时一个完整的数据帧包含9个数据位。低8位依然通过SCIDRL传递而第9位即最高位或称为Bit 8则通过SCIDRH的T8发送或R8接收来操作。为什么需要9位模式这在多机通信中非常有用。第9位可以作为一个“地址/数据”标识位。例如约定当第9位为1时该帧为地址帧用于寻址总线上的某个从机为0时则为数据帧。从机硬件可以检测该位从而实现硬件级的地址过滤只有地址匹配的从机才会被唤醒并接收后续数据这比纯软件解析效率高得多。2.2 访问时序与实战中的“坑”手册中关于寄存器访问的说明每一句都值得仔细琢磨“Read: Anytime; reading accesses SCI receive data register. Write: Anytime; writing accesses SCI transmit data register; writing to R8 has no effect.”这句话看似简单却点出了两个独立的缓冲区读操作永远访问接收数据寄存器写操作永远访问发送数据寄存器。它们是物理上分离的。这意味着你向SCIDRL写入0x55并不会影响你从SCIDRL读出的值那是之前接收到的数据。更重要的提示在于对T8位的说明“NOTE: If the value of T8 is the same as in the previous transmission, T8 does not have to be rewritten.The same value is transmitted until T8 is rewritten.”这是一个重要的优化提示。在9位模式下如果你要连续发送一批数据帧且它们的第9位地址/数据标识都相同例如先发一个地址帧然后连续发多个数据帧那么你只需要在发送第一个字节前设置一次T8后续发送数据字节时只需写入SCIDRL即可T8的值会自动复用。这可以减少一次寄存器写操作对于追求极限效率的场合很有意义。然而这里有一个极易出错的实操陷阱访问顺序。“When transmitting in 9-bit data format and using 8-bit write instructions, write first to SCI data register high (SCIDRH), then SCIDRL.”为什么必须是先高后低这是因为硬件设计上将数据从发送数据寄存器转移到内部发送移位寄存器的动作通常由对SCIDRL的写入操作触发。如果你先写SCIDRL硬件可能会立即将旧的T8值可能不是你想要的和新的低8位数据组合成一个9位数并启动发送。之后你再写SCIDRH更新T8为时已晚。因此正确的9位数据发送顺序是将第9位数据写入SCIDRH的T8位。将低8位数据写入SCIDRL此操作会触发发送。对于接收端顺序则不重要因为当接收完成时SCIDRH中的R8和SCIDRL中的低8位已经被硬件同时更新好了你可以按任意顺序读取。我的经验心得在编写驱动时我通常会封装两个函数SCI_SendByte_8Bit()和SCI_SendByte_9Bit(uint16_t data)。对于9位版本函数内部将data的高位Bit 8与低8位拆开严格按照先写SCIDRH再写SCIDRL的顺序操作。这样上层应用只需关心数据本身避免了底层顺序错误导致的通信故障这种故障往往非常隐蔽表现为偶尔的数据错位。3. SCI整体功能框架与数据流剖析要驾驭SCI必须对其内部数据通路和控制逻辑有一个全景式的认识。S12SCIV5模块的框图虽然复杂但我们可以将其简化为几个核心部分来理解。3.1 核心功能模块交互模块的核心是一个全双工、异步的通信引擎。所谓全双工意味着发送和接收可以同时独立进行它们共享同一个波特率发生器但拥有各自独立的移位寄存器和数据寄存器SCIDRH/L。波特率发生器这是通信的“心跳”。它由一个13位的模数计数器SBR[12:0]构成通过对总线时钟Bus Clock进行分频产生驱动接收器和发送器的基准时钟。波特率的计算公式为SCI Baud Rate Bus Clock / (16 * SBR)。这里的16倍频是异步通信采样精度的关键接收器会以16倍于波特率的频率对RXD引脚进行采样以提高抗噪声和时钟容错能力。发送器路径数据从内部总线写入发送数据寄存器SCIDRH/L然后被自动加载到发送移位寄存器中。移位寄存器会在数据前后自动添加上起始位逻辑0和停止位逻辑1然后按照波特率时钟将数据位依次从TXD引脚移出。发送数据寄存器空TDRE标志位是软件流控的关键它指示何时可以安全写入下一个待发送字节。接收器路径RXD引脚上的串行数据流被送入接收移位寄存器。接收逻辑会检测起始位的下降沿然后以16倍波特率的节奏在每位数据的中间位置进行采样判决。一个完整的帧接收完毕后数据被并行加载到接收数据寄存器SCIDRH/L中并置位接收数据寄存器满RDRF标志通知CPU读取。3.2 关键控制位与工作模式模块的灵活性通过一系列控制寄存器SCICR1, SCICR2来体现M位 (SCICR1[4])选择数据字符长度0为8位1为9位。PE和PT位 (SCICR1[1:0])用于奇偶校验的使能和类型选择偶校验/奇校验。启用后硬件会自动生成或校验校验位。TE和RE位 (SCICR2[3:2])发送器和接收器使能位。这是模块工作的总开关。LOOPS和RSRC位 (SCICR1[7:6])用于配置回环Loop模式常用于模块自测试。当LOOPS1且RSRC0时为内部回环发送器的输出直接连接到接收器的输入不与外部引脚相连用于验证软件和内部硬件是否正常。理解这个框架后我们再看红外和LIN支持就会发现它们并非独立的模块而是巧妙地“嫁接”在这个核心框架之上的专用处理单元。4. 红外IrDA接口子模块从电信号到光脉冲的编码艺术红外通信IrDA是SCI一个非常经典的外设扩展。它并非一个独立的通信协议而是在标准SCI异步串行数据流之上增加了一层物理层编码/解码将电信号转换为符合IrDA标准的红外光脉冲。4.1 红外编码/解码原理标准UART使用NRZ不归零编码逻辑1保持高电平逻辑0保持低电平在整个位周期内电平不变。而IrDA物理层规范要求使用RZI归零反相编码逻辑0用一个窄的光脉冲来表示逻辑1则没有脉冲保持黑暗。这样做主要是为了降低红外LED的平均功耗因为发射脉冲是需要较大电流的。S12SCIV5的红外子模块完美实现了这一转换发送编码器位于发送路径末端。当SCI发送移位寄存器输出一个比特流时编码器会介入。对于每个0比特它会在该比特周期的中间位置生成一个持续时间很窄的高电平或低电平取决于TXPOL配置脉冲驱动外部的红外LED。对于1比特则输出无效电平。脉冲宽度可以选择为位周期的3/16、1/16、1/32或1/4由IREN和时钟选择位控制。接收解码器位于接收路径前端。外部红外接收头如HS0038B会将接收到的光脉冲转换为电脉冲通常是反相的即收到光时输出低电平。解码器的作用就是检测这些窄脉冲并将其“拉伸”还原成一个完整的、位周期宽度的逻辑0电平送给后续的SCI接收移位寄存器进行常规的UART帧解析。RXPOL位用于匹配接收脉冲的极性。一个关键配置点红外模块的时钟源R16XCLK, R32XCLK来自SCI的波特率发生器。这意味着红外通信的波特率设置和标准SCI模式是完全一样的。你只需要在标准波特率配置的基础上使能红外模块设置IREN等位硬件就会自动完成NRZ到RZI的编解码对上层软件完全透明。4.2 红外应用中的硬件连接与配置要点在实际搭建红外通信电路时有几点需要特别注意发送端MCU的SCTXD红外编码后输出引脚需要连接一个三极管或专用的LED驱动芯片来驱动红外LED。直接连接IO口驱动能力通常不足。脉冲电流可能达到100mA以上需根据LED规格设计限流电阻。接收端红外接收头如Vishay的TSOP系列输出的是解码后的数字信号通常需要连接到MCU的SCRXD引脚。注意接收头输出的信号极性有光/无光对应的电平是否与RXPOL设置匹配。大多数接收头在收到38kHz载波这是IrDA 1.0物理层要求的S12SCIV5不支持载波调制仅支持SIR即低速红外解调后输出是反相的即收到脉冲时输出低电平此时可能需要设置RXPOL1。波特率限制手册明确指出该设计仅支持2.4 kbit/s到115.2 kbit/s的速率。这是由脉冲拉伸电路的时序决定的。超出此范围脉冲可能无法被正确识别或生成。避坑指南调试红外通信时最常遇到的问题就是“收不到”或“数据错乱”。除了检查上述硬件连接和极性配置一个非常有效的工具是逻辑分析仪。同时抓取标准TXD引脚和红外编码后的SCTXD引脚波形进行对比。你应该能看到TXD上的一个0比特位在SCTXD上对应一个窄脉冲TXD上的1比特位在SCTXD上是一条平直线。通过对比可以迅速定位问题是出在编码前、编码后还是接收解码环节。5. LIN总线支持面向汽车网络的硬件加速LINLocal Interconnect Network是一种广泛应用于汽车车身控制的低成本串行网络协议。S12XS系列作为传统的汽车MCU其SCI模块原生集成了LIN协议所需的几项关键硬件支持极大简化了软件实现。5.1 断点Break检测LIN帧以一个特殊的“断点”字段开始它由至少13位对于标准SCI是13位对于9位模式是14位的显性电平逻辑0构成后跟一个同步间隔符。这个断点长度远超过普通数据帧用于帧起始的同步和唤醒睡眠中的节点。普通SCI在收到全0的帧时会将其识别为帧错误FE。而S12SCIV5的LIN支持提供了硬件断点检测电路。当使能断点检测BKDFE1后硬件会持续监测RXD引脚上的低电平持续时间。一旦检测到连续10个或11个取决于M位比特时间的低电平就会置位断点检测中断标志BKDIF而不会像普通模式那样置位RDRF和FE标志。这个功能至关重要提高可靠性软件无需通过计时器来软件判断超长的低电平响应更及时准确。减轻CPU负担产生的是专用的断点中断与普通数据接收中断分离中断服务程序ISR逻辑更清晰。保护数据如手册图14-17所示如果断点在一个字节传输中途开始RXD_2情况硬件会先将已接收的部分字节存入数据寄存器并标记错误FE然后再标记断点。这避免了数据丢失或混淆。5.2 发送碰撞检测LIN是单线、主从结构的网络理论上同一时刻只能有一个节点通常是主节点发送。但从节点也可能需要发送响应数据。如果软件逻辑错误或总线异常可能导致多个节点同时驱动总线产生“碰撞”。S12SCIV5的位级碰撞检测功能就是为了应对这种情况。当使能该功能通过BERRM[1:0]位后模块会在发送数据的同时通过一个同步器实时监听RXD引脚即总线上的实际电平。其工作原理如图14-18所示发送移位寄存器的输出期望发送的电平会与经过同步后的总线实际电平进行比较。比较的采样点可以选择在比特周期的不同位置由BERRM位控制。一旦检测到期望电平与实际总线电平不匹配硬件会立即采取行动中止当前发送立即停止发送当前字节并将发送缓冲区中的数据丢弃。驱动总线到安全状态根据TXPOL配置将TXD引脚驱动为高电平逻辑1隐性电平或低电平以释放总线或强制总线进入已知状态。置位标志设置发送数据寄存器空TDRE和发送完成TC标志同时置位比特错误中断标志BERRIF。锁定发送器在BERRIF被软件清除之前发送器将不再启动新的发送。这个功能对于构建健壮的LIN从节点至关重要。一旦检测到碰撞例如从节点在响应时主节点意外开始发送新的帧头从节点能立即退出发送避免总线持续冲突并在中断服务程序中处理错误尝试重发或报告错误。重要配置提示手册特别强调当启用碰撞检测时RXPOL和TXPOL必须设置为相同的值。这是因为比较器直接比较的是发送输出和接收输入的逻辑值。如果极性相反即使总线电平正常硬件也会误判为碰撞导致通信无法进行。6. 发送器与接收器的深度工作机制与配置流程理解了高级功能我们还需要回到基础透彻掌握发送和接收的每一个步骤这是稳定通信的基石。6.1 发送器完整工作流程与状态机发送一个字节并非简单地写入SCIDRL。手册14.4.5.2节给出了标准的初始化与发送流程结合我的经验一个健壮的发送驱动应遵循以下步骤初始化配置禁用发送器首先确保TE位为0。在配置过程中避免意外发送。配置波特率向SCIBDH和SCIBDL寄存器写入波特率分频值。这里有个细节必须同时写入高低字节才有效。单独写SCIBDH会被忽略。通常采用一个16位写操作如C语言中的SCIBD 分频值;来完成。配置帧格式设置SCICR1确定数据位长度M、奇偶校验PE, PT、以及是否使用回环LOOPS等。使能发送器与中断最后设置SCICR2使能发送器TE1并根据需要使能发送数据寄存器空中断TIE或发送完成中断TCIE。特别注意将TE从0写为1的瞬间硬件会自动加载一个“前导码”10或11个连续的1即空闲字符到发送移位寄存器并开始发送。这为总线提供了一个稳定的空闲状态便于接收方同步。字节发送循环查询方式为例等待发送缓冲区空循环读取SCISR1检查TDRE标志是否置1。TDRE1表示发送数据寄存器SCIDRH/L已空可以写入新数据。写入数据将待发送数据写入SCIDRL8位模式或先写T8到SCIDRH再写数据到SCIDRL9位模式。写入SCIDRL的动作会清零TDRE标志并触发硬件将数据从发送数据寄存器加载到发送移位寄存器开始串行发送。可选等待发送完成如果需要确保一帧完全发出例如在关闭发送器前可以等待TC标志置1。TC在移位寄存器发送完停止位后置1。关于TDRE标志的精确定时手册的NOTE里有一个非常关键的时间点描述TDRE标志是在前一个帧的停止位开始后约9/16个位时间被置位的。这意味着在当前字节的停止位发送完之前你就可以开始准备下一个字节了。这为高速、连续发送提供了可能实现了“流水线”操作。6.2 接收器的智能采样与容错机制接收器是SCI模块中更复杂、更智能的部分。它的核心任务是在存在噪声和时钟偏差的情况下从RXD引脚的电平变化中准确还原出数据位。同步与采样过程起始位检测接收器持续以16倍波特率的频率RT时钟采样RXD引脚。它寻找一个“下降沿”从1到0的跳变并且要求这个下降沿之前至少有3个连续的1即空闲状态。一旦找到就假设这是一个起始位的开始并启动RT计数器。起始位验证在RT3、RT5、RT7时刻对起始位进行三次采样。根据表14-17如果三次采样中至少有两次是0则起始位验证成功否则认为是噪声干扰复位RT计数器重新开始搜索。如果验证成功但采样值不一致会置位噪声标志NF。数据位采样对于每个数据位在RT8、RT9、RT10时刻即该比特位的中间位置进行三次采样采用“多数判决”原则确定该位的值见表14-18。同样如果三次采样值不一致会置位NF。停止位采样与帧错误在停止位预期的RT8、RT9、RT10时刻进行采样。如果多数采样结果为0则意味着没有检测到应有的停止位逻辑1硬件会置位帧错误标志FE。时钟容错与再同步这是异步通信可靠性的关键。接收器并非死板地按照自己的节奏采样。它会在两种情况下对RT时钟进行“再同步”每次成功检测到起始位的下降沿时。在数据位采样期间如果检测到一个从1到0的跳变这通常意味着一个数据位的开始尽管在帧中间这可能是噪声也会尝试重新对齐时钟。 这种机制允许发送器和接收器的波特率存在一定的偏差只要这个偏差在累积到足以导致采样点滑出比特位边界之前能被一次再同步纠正回来。手册14.4.6.5节详细计算了这种容错能力对于8位数据慢速偏差容忍约4.63%快速偏差容忍约3.75%。这解释了为什么在设置波特率时通常要求误差在2%-3%以内为系统留出足够的余量。我的调试经验当通信出现偶发性错误特别是FE或NF标志被置位时首先应该用示波器或逻辑分析仪测量实际波特率。计算发送端和接收端的波特率误差是否超出容限。其次检查PCB布线RXD/TXD走线是否过长是否靠近噪声源如电机、开关电源必要时增加串联电阻或并联电容进行整形。最后在软件上确保在读取数据后及时清除RDRF标志并妥善处理FE、NF等错误标志避免错误累积导致状态机卡死。7. 波特率生成精度计算与误差分析波特率是串行通信的“节拍器”其精度直接决定了通信的距离和可靠性。S12SCIV5的波特率发生器基于一个13位的分频器SBR[12:0]分频值范围为1到8191。7.1 波特率计算公式与配置方法波特率的计算公式非常直接目标波特率 总线时钟频率 / (16 * SBR)因此所需的分频值SBR为SBR 总线时钟频率 / (16 * 目标波特率)这里的关键是计算出的SBR必须是一个整数。但总线时钟和目标波特率往往不能整除这就引入了误差。配置步骤根据系统总线时钟例如外部晶振经过PLL倍频后的频率和目标波特率如9600计算理论SBR值。对理论SBR值进行四舍五入取最接近的整数。将整数SBR写入SCIBDH和SCIBDL寄存器。例如总线时钟为25 MHz目标波特率为9600 理论 SBR 25,000,000 / (16 * 9600) ≈ 162.7604 取整后 SBR 163 实际波特率 25,000,000 / (16 * 163) ≈ 9585.9 Hz 误差 (9585.9 - 9600) / 9600 ≈ -0.147%7.2 误差影响与实战选择手册表14-16给出了25MHz总线时钟下常见波特率的配置值及误差。可以看到在较高波特率下如38.4k误差可能接近0.76%。虽然仍在理论容限内但在长距离、高干扰或高速通信时累积的误差可能增加误码风险。降低误差的策略选择合适的总线时钟在设计系统时钟树时可以考虑让核心频率是目标波特率×16的整数倍。例如为了得到精确的115200波特率可以设置总线时钟为 115200 * 16 1.8432 MHz 的整数倍如 7.3728 MHz (4倍)、11.0592 MHz (6倍) 等。许多外部晶振直接提供11.0592MHz就是为了满足串口通信的整数分频需求。使用更高的总线时钟在允许范围内使用更高的总线时钟可以使分频系数SBR变大四舍五入带来的相对误差会减小。例如同样是9600波特率用50MHz时钟计算出的SBR为325.52取整325或326带来的误差比用25MHz时钟时更小。软件补偿高级技巧对于某些支持微调的高端MCU可以通过调整采样点如STM32的USART支持过采样来补偿微小误差。S12XS的SCI模块硬件固定为16倍过采样不支持此功能但可以在软件协议层增加校验如CRC来保证数据正确并设计重传机制。注意事项波特率发生器在SBR值为0时是禁用的。因此在初始化时如果先写了SCIBDH为0必须紧接着写入SCIBDL否则模块可能无法正常工作。最安全的做法是使用一个16位赋值语句一次性设置整个SCIBD寄存器。8. 高级功能与异常处理实战掌握了基础收发和波特率配置我们再来探讨几个高级主题和异常情况的处理这些是构建工业级可靠通信的关键。8.1 唤醒机制Receiver Wakeup在多机通信中的应用在多主机或一主多从的系统中让所有从机持续监听总线会消耗不必要的功耗。SCI的唤醒机制允许从机进入“睡眠”状态RWU1此时接收器仍在工作但收到数据时不会置位RDRF标志也不会产生接收中断从而降低功耗。主机如何唤醒特定的从机这通过两种唤醒模式实现由WAKE位选择空闲线唤醒WAKE0当总线保持空闲状态逻辑1超过一帧10或11位时间后再出现一个起始位下降沿所有从机都会被唤醒。这种方式适合广播唤醒所有节点。地址位唤醒WAKE1在9位数据格式下硬件会检查接收到的第9位即SCIDRH中的R8。如果该位为1则硬件认为这是一个地址帧并清除RWU位唤醒接收器以便接收后续的数据帧。如果第9位为0则保持睡眠状态忽略该帧。这种方式可以实现精准的、基于地址的从机寻址。配置流程示例地址位唤醒所有从机初始化时设置M19位模式WAKE1并置位RWU进入睡眠。主机要发送数据给地址为0x02的从机 a. 先发送一个地址帧数据低8位为0x02第9位T8置1。 b. 地址为0x02的从机收到此帧第9位为1硬件自动清除其RWU位将其唤醒。 c. 该从机产生接收中断如果RIE使能在中断服务程序中读取数据0x02并识别为自己的地址。 d. 主机随后发送的数据帧第9位T8都置0。 e. 只有被唤醒的从机地址0x02会继续接收这些数据帧第9位为0其他从机因RWU仍为1而忽略它们。通信结束后从机软件可以重新置位RWU再次进入睡眠。8.2 各类错误标志的识别与处理SCI提供了丰富的状态标志来指示通信异常正确处理这些标志是软件健壮性的体现。FEFraming Error帧错误未在预期位置检测到停止位。可能原因波特率严重不匹配、线路受到强干扰产生毛刺、对方发送了Break信号、硬件故障。处理读取状态寄存器SCISR1会自动清除FE。软件应丢弃该帧数据并检查线路和波特率配置。NFNoise Flag噪声标志在起始位、数据位或停止位的三次采样中结果不一致。可能原因线路噪声、接地不良、信号边沿质量差。处理NF标志在读SCISR1后通过读SCIDRL来清除。单次的NF不一定意味着数据错误因为采用了多数判决但频繁出现NF需要检查硬件。OROverrun溢出错误CPU尚未读取接收数据寄存器SCIDRH/L中的旧数据新的一帧数据又已接收完毕并准备写入。硬件会丢弃新数据并置位OR。可能原因接收中断服务程序执行时间过长、中断被长时间关闭、主程序轮询不及时。处理读取SCISR1可清除OR。必须优化软件确保及时读取数据。可以考虑使用接收FIFO如果硬件支持或DMA。PEParity Error奇偶校验错误当使能奇偶校验后硬件计算的校验位与接收帧中的校验位不匹配。可能原因传输过程中单比特翻转。处理同FE读取状态寄存器清除。可根据应用需求决定是请求重发还是仅做错误计数。BKDIFBreak Detect Interrupt Flag断点检测中断标志仅在LIN模式下使能BKDFE1。检测到LIN Break字符时置位。处理这是LIN通信的正常部分应在中断服务程序中将其作为帧开始的信号进行处理并清除该标志。一个通用的错误处理中断服务程序框架可能如下所示void SCI_IRQ_Handler(void) { uint8_t status SCISR1; // 1. 处理接收 if (status (SCISR1_RDRF_MASK | SCISR1_OR_MASK | SCISR1_FE_MASK | SCISR1_PF_MASK | SCISR1_NF_MASK)) { // 有接收事件或错误 uint8_t data SCIDRL; // 读取数据会清除RDRF和一些错误标志 uint8_t error status (SCISR1_OR_MASK | SCISR1_FE_MASK | SCISR1_PF_MASK | SCISR1_NF_MASK); if (error) { // 记录或处理错误error变量指示了具体错误类型 g_sci_error_count; // 通常当发生OR、FE、PF时接收到的data可能无效应丢弃 if (!(error SCISR1_NF_MASK)) { // 仅有NF错误时数据可能仍可用多数判决 // 丢弃数据 return; } } // 将有效数据存入缓冲区 if (g_rx_buffer_index RX_BUFFER_SIZE) { g_rx_buffer[g_rx_buffer_index] data; } } // 2. 处理发送略 // 3. 处理LIN断点检测如果使能 if ((SCISR2 SCISR2_BKDIF_MASK) (SCICR2 SCICR2_BKDIE_MASK)) { // 检测到LIN Break SCISR2 | SCISR2_BKDIF_MASK; // 写1清除标志 // 处理LIN帧头... } }8.3 发送器关闭与空闲字符插入的时序控制在需要分隔数据包或进行流控制的场合我们可能需要暂时关闭发送器或发送一个空闲字符全1。手册14.4.5.4节和14.4.5.2节的NOTE给出了精确的操作序列。关键原则直接清除TE位会立即停止发送器但如果此时移位寄存器中还有数据正在发送该帧会被截断导致接收方收到不完整的帧。正确关闭发送器的流程发送最后一帧数据写入SCIDRL。等待TDRE标志置1。这表示最后一帧数据已从发送数据寄存器转移到发送移位寄存器可以安全关闭发送器而不影响该帧的发送。清除TE位。在消息间插入空闲字符用于产生较长的高电平间隔发送第一条消息的最后一个字节。等待该字节的TDRE置1。在下一字节写入前先清除TE位再立即置位TE位。这个“Toggle”操作会使硬件在完成当前帧发送后自动插入一个完整的空闲字符10/11个1。紧接着写入第二条消息的第一个字节。时序陷阱手册警告TE位的Toggle操作必须在当前帧的停止位出现在TXD引脚之前完成。如果等到停止位发出后再操作则可能丢失下一个要发送的字节。最安全的做法是在TDRE置位后、写入下一个数据字节前立刻执行TE位的Toggle。