HC08 MCU软件模拟全双工串口:基于定时器中断的精准时序控制方案

HC08 MCU软件模拟全双工串口:基于定时器中断的精准时序控制方案 1. 项目概述与核心价值在嵌入式开发领域串行通信SCI/UART是连接微控制器与外部世界最基础、最常用的桥梁。然而很多低成本或引脚资源受限的MCU其硬件串口UART数量往往捉襟见肘。当项目需要额外的串口或者硬件UART被其他功能占用时软件模拟串口Software SCI就成了一个极具吸引力的替代方案。今天要深入探讨的就是基于Freescale现NXPHC08系列MCU利用其内置定时器模块TIM的两个独立通道实现一个高效、可靠的全双工软件SCI通信方案。这个方案的核心价值在于“全双工”和“中断驱动”。不同于一些简单的轮询式软件串口本方案为发送和接收分别分配了一个独立的TIM通道并各自配备了独立的中断服务程序ISR。这意味着发送和接收过程可以完全并行进行互不阻塞。当MCU在发送一个字节时它可以同时接收另一个字节通信效率接近硬件UART。这对于需要实时双向数据交换的应用如与传感器对话、调试信息输出、多机通信等场景至关重要。方案提供了两种模式标准模式实现基础的8-N-1格式通信增强模式则进一步支持9位数据、奇偶校验、1或2个停止位以及错误检测帧错误、奇偶校验错误、溢出错误功能更为完备。2. 方案设计思路与硬件基础2.1 为什么选择TIM通道模拟SCI在深入代码之前我们先要理解“为什么”。SCI通信的本质是精确的时序控制每个数据位包括起始位、数据位、校验位、停止位都需要在精确的时间点被采样或输出。硬件UART内部有一个专用的波特率发生器来完成这个定时任务。而在软件模拟中我们需要一个同样精准的“时钟源”来替代它。HC08的定时器模块TIM正是这样一个理想的时钟源。它是一个自由运行的计数器可以配置预分频器产生非常稳定的时间基准。TIM的输入捕捉/输出比较IC/OC通道功能允许我们在计数器达到特定值时产生中断或者捕获外部引脚的电平变化时刻。这正是模拟串口发送在特定时间点改变输出电平和接收在特定时间点采样输入电平所需要的核心机制。2.2 双通道全双工架构解析本方案的精妙之处在于对两个TIM通道的职责划分TIM通道0CH0专职负责接收RX。初始配置为输入捕捉IC模式下降沿触发。当RX引脚上出现起始位从高电平跳变到低电平时TIM会捕获当前计数器的值并产生中断。随后在中断服务程序中它会切换到输出比较OC模式引脚由端口控制。此时OC中断不再用于改变引脚电平而是作为一个精准的“闹钟”在每个位时间的中心点或附近唤醒MCU去采样RX引脚的状态。TIM通道1CH1专职负责发送TX。全程工作在输出比较OC模式。通过计算下一个位边沿的时间点并设置通道的比较寄存器TIM会在精确的时刻产生中断。在中断服务程序中根据待发送数据位的值0或1将通道配置为“比较匹配时清除输出”或“比较匹配时置位输出”从而在TX引脚上产生正确的波形。这种架构实现了物理上的隔离发送时序由CH1的OC中断严格把控接收采样由CH0的OC中断精准触发两者通过独立的寄存器组和状态机管理互不干扰从而实现了真正的全双工。2.3 关键参数位时间与“1.3位时间”软件串口的精度核心在于位时间Bit Time的计算。位时间由系统总线和目标波特率决定位时间计数值 总线频率 / 目标波特率例如使用9.8304MHz晶振HC08内部4分频后总线频率为2.4576MHz。要实现9600波特率位时间计数值 2,457,600 / 9600 256 0x0100在代码中BITHI:BITLO就存储了这个值0x01:0x00。对于接收有一个更精细的考量采样点。理想情况下我们应该在每个数据位的正中心采样以获得最强的抗干扰能力。但是从中断发生到执行采样指令存在一段固定的CPU周期延迟代码中称为“Pin Check Latency”。为了补偿这个延迟方案在接收第一个数据位时不是等待一个完整的位时间而是等待“1.3个位时间 - 延迟周期数”。1.3倍这是一个经验值旨在让第一个采样点落在第一个数据位的时间窗靠后位置更接近中心。减去延迟精确扣除中断响应、现场保护、判断逻辑等消耗的周期数标准模式26周期增强模式31周期确保补偿后的实际采样点准确。因此代码中定义了BIT1HI:BIT1LO用于接收第一个数据位的定时。计算示例如下BIT1HI:BIT1LO 位时间计数值 * 1.3 - 延迟周期数 0x0100 * 1.3 - 26 ≈ 0x0133 (标准模式)注意延迟周期数的计算必须精确到指令周期并考虑最坏情况。增强模式因增加了错误检测等逻辑延迟稍大31周期。在实际移植到不同型号HC08或优化代码时必须重新计算此值。3. 核心模块代码深度解析3.1 初始化配置 (RXTX_config)这是软件SCI的“总开关”。它的任务是为收发两个通道做好一切准备。RXTX_config: LDA #$30 ; 停止并复位定时器设置TSC寄存器的TSTOP和TRST位 STA TSC MOV #$48,TSC0 ; 配置通道0输入捕捉(IC)下降沿触发中断使能 MOV #$00,TSC1 ; 配置通道1输出比较(OC)初始输出高电平空闲状态中断关闭 MOV #$10,rSCSR1 ; 设置发送器空标志(SCTE)表示可以发送新数据 BSET TPIN,PTD ; 设置TX引脚为高电平空闲状态 BSET TPIN,DDRD ; 设置TX引脚为输出方向 BCLR RPIN,DDRD ; 设置RX引脚为输入方向 CLR rSCSR2 ; 增强模式清零状态寄存器2 CLI ; 全局中断使能 BCLR TSTOP,TSC ; 启动定时器计数器 RTS关键点解析定时器复位任何定时器操作前先停止并复位确保从一个干净的状态开始。通道0初始状态配置为输入捕捉IC等待RX引脚上的起始位下降沿。这是接收过程的“哨兵”。通道1初始状态配置为输出比较OC但先不使能中断。输出预设为高电平符合UART总线空闲状态。引脚配置必须正确设置数据方向寄存器DDRD。TX为输出RX为输入。标志位初始化SCTE发送空标志置位告诉上层应用“发送缓冲区就绪”。开中断启动定时器最后两步让整个系统“活”起来。3.2 数据发送流程 (SCISend与TX_isr)发送流程由应用层调用PutByte或直接操作寄存器触发最终由TX_isr中断服务程序驱动。SCISend子程序这是发送的“发起者”。它的核心逻辑是检查当前是否有发送正在进行通过检查CH1IE中断使能位或TPF标志。如果没有则清除SCTE标志表示发送缓冲区已被占用。从rSCTDR发送数据寄存器加载数据到rSCTSR发送移位寄存器。计算第一个输出比较的时间点当前定时器值 1个位时间并写入通道1的比较寄存器TCH1H:TCH1L。将通道1配置为“比较匹配时清除输出”以产生起始位低电平并使能通道中断。TX_isr中断服务程序这是发送的“执行者”。每次比较匹配中断发生时它负责送出下一个位。判断发送阶段通过检查TPF发送进行中标志区分是发送第一个位起始位还是后续数据位。计算下一个位时间总是在当前中断时刻为下一个位的中断计算时间点当前通道值 1个位时间。确定输出电平将发送移位寄存器rSCTSR右移其最低位或通过进位标志即是要发送的下一个数据位。根据该位是0还是1将通道1配置为“比较匹配时清除输出”或“比较匹配时置位输出”。处理发送结束当检测到所有数据位包括停止位都已发送完毕则清除TPF标志。然后检查是否有待发送数据SCTE标志是否被置位表示应用层又写入了新数据。如果有则加载新数据计算新的起始位时间开始下一轮发送如果没有则禁用通道1中断TX引脚保持高电平空闲。增强模式发送的进阶在增强模式中TX_isr变得更加复杂因为它需要处理9位数据模式使用两个8位寄存器rSCTSRH:rSCTSRL组合来存放9位数据和一个“结束标志位”。奇偶校验计算在发送每个数据位为‘1’时切换一个临时奇偶位TPTY。在所有数据位发送完后根据配置奇校验或偶校验计算出校验位并作为下一个“数据位”发送。1或2个停止位根据配置在发送完校验位或数据位后发送1个或2个高电平的停止位。3.3 数据接收流程 (RX_isr)接收完全由硬件触发并由RX_isr中断服务程序状态机驱动。起始位检测通道0初始化为输入捕捉IC下降沿触发。当RX引脚出现下降沿起始位开始硬件自动捕获此刻定时器值到TCH0H:TCH0L并产生中断。第一个RX_isr起始位中断设置RPF接收进行中标志。增强模式根据数据长度和校验配置初始化接收移位寄存器rSCRSRH:rSCRSRL设置一个“结束标志位”。关键步骤计算第一个数据位的采样点时间。公式为捕获到的时刻 1.3 * 位时间 - 延迟周期。结果写入TCH0H:TCH0L。将通道0重新配置为输出比较OC引脚由端口控制。这样下次比较匹配中断到来时就是我们预设的第一个数据位采样时刻。后续的RX_isr数据位采样中断采样在中断中立即读取RX引脚的电平状态。移位存储将采样到的电平0或1通过进位标志移入接收移位寄存器。判断阶段数据位如果“结束标志位”尚未被移入则只是计算下一个采样点时间1个位时间并返回。校验位/停止位增强模式如果“结束标志位”已被移入说明数据位已收完。接下来根据配置进行奇偶校验计算和比对如果使能并检查停止位是否为高电平帧错误检测。接收完成当所有位包括可选的校验位和停止位都处理完毕后清除RPF标志。将接收移位寄存器中的数据经过调整移除“结束标志位”后存入接收数据寄存器rSCRDR。设置SCRF接收满标志通知上层应用数据就绪。检查是否发生溢出错误上次数据未读新数据又到。最后将通道0重新配置为输入捕捉IC下降沿触发等待下一个起始位。实操心得接收中断的延迟补偿计算是软件串口稳定性的生命线。务必使用示波器或逻辑分析仪在目标波特率下实际测量从起始位下降沿到第一个采样点指令执行之间的时间确保其落在第一个数据位的中间靠后位置。如果采样点太靠近边沿极易因时钟误差或噪声导致误码。4. 应用层接口与移植要点4.1 用户APIGetByte与PutByte为了便于使用方案提供了两个友好的子程序。; 等待接收一个字节结果存放在累加器A中标准模式或H:X寄存器对中增强模式 GetByte: BRCLR SCRF, rSCSR1, * ; 循环等待直到接收满标志(SCRF)置位 LDA rSCRDR ; 标准模式从接收数据寄存器读取数据到A ; LDHX rSCRDRH ; 增强模式从接收数据寄存器读取数据到H:X BCLR SCRF, rSCSR1 ; 清除接收满标志允许下一次接收 RTS ; 将累加器A标准模式或H:X寄存器对增强模式中的数据发送出去 PutByte: STA rSCTDR ; 标准模式将A中的数据存入发送数据寄存器 ; STHX rSCTDRH ; 增强模式将H:X中的数据存入发送数据寄存器 JSR SCISend ; 调用发送启动子程序 BRCLR SCTE, rSCSR1, * ; 循环等待直到发送空标志(SCTE)置位表示数据已从缓冲区移入移位寄存器可以写入新数据 RTS使用注意PutByte中的等待循环BRCLR SCTE, rSCSR1, *会阻塞CPU直到当前字节被加载到发送移位寄存器。如果应用不允许长时间阻塞可以改为查询SCTE标志或者使用增强模式中的发送完成中断TIEN。4.2 移植到其他MCU的步骤这个方案的核心思想具有普适性可以移植到其他具有类似定时器带输入捕捉和输出比较功能的8位或16位MCU上如PIC、AVR、STM8等。移植的关键步骤定时器模块映射找到目标MCU的等效定时器及其输入捕捉(IC)和输出比较(OC)通道的控制寄存器、状态寄存器、比较/捕获寄存器。中断向量重定向将TX_isr和RX_isr的入口地址填写到目标MCU定时器对应通道的中断向量表中。引脚与端口配置根据你的硬件连接修改TPIN和RPIN对应的端口和位定义。指令集转换HC08汇编指令需要转换为目标MCU的汇编或C语言。重点注意位操作、寄存器间数据传输、中断现场保护与恢复的差异。时序重计算根据目标MCU的时钟频率和定时器预分频设置重新计算BITHI:BITLO。至关重要使用仿真器或示波器精确测量从接收中断发生到执行采样指令BRCLR RPIN, PTD, nocarry之间的CPU周期数重新计算BIT1HI:BIT1LO。这是移植成功与否的决定性因素。测试与校准使用逻辑分析仪同时监控TX和RX引脚波形。重点检查发送波形是否符合UART时序起始位低停止位高位宽均匀。接收采样点是否准确落在每个数据位的中心区域。进行长时间、全速率的双向数据收发测试检查误码率。5. 常见问题、调试技巧与优化建议5.1 典型问题排查速查表现象可能原因排查步骤与解决方案完全无法发送或接收1. 定时器未启动或配置错误。2. 全局中断未开启。3. 引脚方向配置错误。1. 检查TSC寄存器确认TSTOP位已清零定时器在运行。2. 确认CLI指令已执行或中断总开关已打开。3. 用万用表或IO控制代码测试TX/RX引脚的电平控制是否正常。发送正常接收不到数据1. 接收起始位检测失败。2.BIT1HI:BIT1LO计算错误采样点偏移。3. 接收中断向量配置错误。1. 用示波器看RX引脚是否有正确的起始位低电平。检查TSC0是否配置为下降沿输入捕捉。2.重点检查用逻辑分析仪抓取RX波形和程序运行确认第一个采样中断是否发生在第一个数据位中间。重新计算并调整BIT1LO值微调。3. 确认RX_isr地址是否正确写入TIM通道0的中断向量。接收数据错位或乱码1. 波特率不匹配BITHI:BITLO计算错误。2. 接收采样点不准确BIT1HI:BIT1LO误差大。3. 中断服务程序执行时间过长导致错过下一个中断。1. 核对系统时钟频率、定时器预分频设置、目标波特率重新计算位时间。2. 同上一问题精细调整BIT1LO。确保测量的是最坏情况下的中断延迟。3. 优化RX_isr和TX_isr代码减少不必要的指令。确保没有在其他地方长时间关闭中断。全双工时高速率下丢数据1. 中断服务程序执行时间接近或超过位时间。2. 主循环或高优先级中断阻塞时间过长。3. 数据缓冲区不足。1. 计算在最坏情况下RX_isr或TX_isr的执行周期数。必须远小于一个位时间如9600波特率下约104us。2. 检查主程序和其他中断避免关中断或执行耗时任务。3. 本方案是单字节缓冲区。高速率下应用层必须及时调用GetByte/PutByte。如需缓冲需在外围添加环形队列。增强模式奇偶校验错误1. 发送方和接收方校验配置不一致奇/偶。2. 校验位计算逻辑有误。1. 确认通信双方rSCCR寄存器中的PEN和PTY位设置一致。2. 单步调试TX_isr和RX_isr中与TPTY、RPTY相关的代码观察校验位的生成和验证过程。5.2 性能优化与资源考量CPU占用率这是软件串口的主要成本。每个数据位的收发都会产生一次中断。以9600波特率、8-N-1格式计算每传输一个字节10位会产生10次中断。如果收发同时全速进行每秒将产生19200次中断。这对HC08这类低速MCU是沉重负担。因此此方案更适合中低波特率如9600以下或非持续通信的场景。中断优先级确保TIM中断具有足够高的优先级避免被其他长时间中断阻塞。如果MCU支持中断嵌套且通信可靠性要求高可以考虑将TIM中断设为最高优先级之一。代码空间与内存整个软件SCI模块代码量不大约几百字节但包含了两个中断服务程序。在资源极其紧张的设备上需要权衡。RAM占用主要是几个状态和数据寄存器可以接受。从汇编到C虽然原代码是汇编但其逻辑清晰非常适合用C语言重写。用C语言实现可以提高可读性和可移植性但必须注意关键时序部分如RX_isr中的精确延迟计算要用内联汇编或仔细优化的C代码实现并确保编译器没有在中断函数中加入不可预测的序言/尾声。5.3 进阶扩展思路添加环形缓冲区当前的GetByte/PutByte是阻塞式的。可以在应用层封装一个带环形队列的接口RX_isr收到数据后放入队列TX_isr从队列取出数据发送。这样应用层读写不会阻塞提高了系统响应性。动态波特率设置可以将BITHI:BITLO和BIT1HI:BIT1LO作为变量在运行时根据通信协议动态修改实现自适应波特率。DMA辅助如果MCU支持对于发送可以配置DMA将内存中的连续数据自动搬运到某个映射到TX引脚的寄存器需硬件支持大幅减轻CPU负担。但接收的精确采样仍需中断或硬件UART支持。实现一个稳定的全双工软件SCI是一项细致的工作它对时序的要求极为苛刻。这个HC08方案提供了一个经过验证的、结构清晰的蓝本。成功的关键在于深刻理解其“双通道独立中断”的设计哲学并在移植和调试过程中耐心地使用工具进行测量和校准。当你看到两个由软件精确控制的波形在示波器上稳定地交互数据时那种对底层硬件掌控的成就感正是嵌入式开发的乐趣所在。