1. 项目概述与核心价值
在嵌入式开发的江湖里,80C51单片机就像一位久经沙场的老将,其内置的定时器/计数器和串口(UART)是驱动无数经典项目的“心脏”与“喉舌”。我接触过不少项目,从简单的延时闪烁LED到复杂的多机通信网络,其稳定性的基石往往就建立在对这两个外设的深刻理解与精准配置之上。很多新手觉得数据手册里寄存器描述晦涩难懂,模式切换令人眼花缭乱,实际调试时波特率对不上、定时不准更是家常便饭。这篇文章,我就结合Philips P89C66x系列这款经典的增强型80C51单片机,把定时器/计数器与串口的工作原理、协同工作模式以及那些手册里不会写的调试心得,掰开揉碎了讲清楚。
简单来说,定时器/计数器负责“计时”和“数数”。它要么对单片机内部的机器周期进行计数,实现精确的延时或定时中断;要么对外部引脚上的脉冲信号进行计数,用于测量频率、转速或作为外部事件触发器。而串口(UART)则负责“说话”和“听话”,实现设备间的异步串行通信,是单片机与电脑、传感器、显示屏或其他单片机交换数据最常用的方式之一。这两者的核心联系在于:串口通信的节奏——也就是波特率,其生成极度依赖于定时器提供的精准时钟源。理解它们如何配合,是玩转80C51通信功能的关键。
无论你是正在学习单片机原理的学生,还是需要为老旧设备维护或新项目选型的工程师,掌握这套经典架构的底层运作机制,都能让你在调试时更有底气,在方案设计时更加游刃有余。下面,我们就从最核心的定时器开始,一步步深入。
2. 定时器/计数器核心原理与工作模式全解析
80C51单片机通常内置至少两个16位定时器/计数器(Timer 0和Timer 1),在P89C66x等增强型型号中还增加了功能更强大的Timer 2。它们的本质是一个可编程的加法计数器,其计数脉冲的来源可以选择内部系统时钟(定时模式)或外部输入引脚(计数模式)。通过配置相关的特殊功能寄存器(SFR),我们可以控制它的计数长度、启动停止、溢出行为以及中断触发。
2.1 核心控制寄存器:TMOD与TCON
所有对Timer 0和Timer 1的控制,都始于两个寄存器:TMOD(定时器模式寄存器)和TCON(定时器控制寄存器)。
TMOD寄存器(地址89H)用于设定工作模式。它是一个不可位寻址的8位寄存器,高4位控制Timer 1,低4位控制Timer 0。每一位都至关重要:
GATE:门控位。当GATE=0时,定时器仅由软件位TRx(在TCON中)控制启停。当GATE=1时,定时器的启动还额外受外部中断引脚INTx电平的控制,这常用于精确测量外部脉冲的宽度。C/T:定时器或计数器选择位。C/T=0时为定时器模式,计数脉冲来自内部系统时钟(经分频)。C/T=1时为计数器模式,计数脉冲来自外部引脚Tx(P3.4或P3.5)的下跳沿。M1和M0:模式选择位。这两位共同决定了定时器的工作模式,是功能差异的核心。
TCON寄存器(地址88H)用于控制定时器的运行和标志状态,它可位寻址:
TR0/TR1:定时器0/1的运行控制位。软件置1启动,清0停止。TF0/TF1:定时器0/1的溢出标志位。当计数器从最大值翻转到0时,硬件自动置1。它可以触发中断(如果中断已开启),并且必须由软件清0。- 其余位(
IE0,IT0,IE1,IT1)与外部中断相关,此处不赘述。
实操心得一:寄存器配置顺序在初始化定时器时,我习惯遵循一个固定的顺序:先配置
TMOD确定模式,再给THx和TLx写入初值设定时间,最后才置位TCON中的TRx来启动定时器。这个顺序可以避免在模式未确定或初值未设定时,定时器意外启动产生不可预期的中断。
2.2 四大工作模式深度剖析
Timer 0和Timer 1共有四种工作模式(Mode 0-3),Timer 2则有三种(捕获、自动重载、波特率发生器)。我们逐一拆解。
2.2.1 Mode 0:13位定时器/计数器模式
这是为了兼容早期8048单片机而保留的模式。在此模式下,定时器寄存器被配置为一个13位计数器。其中高8位是THx,低5位是TLx的低5位(TLx的高3位无效,应忽略)。
工作原理:计数器从设定的初值开始,对脉冲进行加1计数。当低5位计满(从11111到00000)时向高8位进位,当全部13位计满溢出时,硬件置位溢出标志TFx。其最大计数值为2^13 = 8192。
计算公式(定时模式): 假设系统时钟频率为f_osc,在标准的12时钟模式下,机器周期 = 12 /f_osc。 定时时间T = (8192 - 初值) × 机器周期。 初值X = 8192 - (T / 机器周期)。
应用场景:如今已较少使用,但在需要兼容老代码或特定分频比时可能会用到。
2.2.2 Mode 1:16位定时器/计数器模式
这是最常用、最经典的定时模式。计数器THx和TLx全部16位参与计数,构成一个完整的65536进制计数器。
工作原理:与Mode 0类似,但计数容量更大。从初值开始加1计数,当TLx先计满255(0xFF)后向THx进位,当THx也计满255且TLx再次计满时,16位全部归零,TFx置位。
计算公式(定时模式): 最大计数值为65536。 定时时间T = (65536 - 初值) × 机器周期。 初值X = 65536 - (T / 机器周期)。
应用场景:需要较长定时时间的场合,如秒级延时、周期性数据采集。由于是纯软件重载(溢出后需在中断服务程序中重新赋值),其定时精度最高,但软件开销稍大。
2.2.3 Mode 2:8位自动重载模式
这是一个高效率的定时/计数模式,特别适合产生固定频率的脉冲或作为串口波特率发生器。在此模式下,TLx作为8位计数器,THx则存放一个固定的重载值。
工作原理:TLx从初值开始计数,溢出时不仅置位TFx,还会自动将THx中保存的值重新装入TLx,然后TLx从这个新值开始继续计数。THx的值在初始化后保持不变。
计算公式: 定时时间T = (256 - THx初值) × 机器周期。THx初值X = 256 - (T / 机器周期)。
优势:自动重载避免了Mode 1中软件重载带来的时间误差和代码开销,特别适合需要精确定时且周期固定的应用,如产生通信波特率。
实操心得二:Mode 2的精度陷阱Mode 2的自动重载虽然方便,但要注意其重载是同步进行的。即在
TLx溢出、TFx置位的同一个机器周期,重载操作发生。这意味着从中断发生到CPU响应并读取TLx之间,TLx已经是一个新值。如果你需要在中断中读取当前计数值,Mode 2并不合适,应选择Mode 1或Mode 3。
2.2.4 Mode 3:双8位定时器模式(仅Timer 0)
这是一个特殊模式,仅适用于Timer 0。当Timer 0工作在Mode 3时,它被拆分成两个独立的8位定时器:
TL0:占用Timer 0的全部资源(GATE,C/T,TR0,TF0,INT0引脚),可以独立工作在定时或计数模式。TH0:固定为定时器模式(计数机器周期),并“借用”了Timer 1的控制位TR1和溢出标志TF1。
此时,Timer 1会怎样?如果Timer 1本身不处于Mode 3(它没有Mode 3,其Mode 3定义是停止计数),它仍然可以正常工作,但其溢出标志TF1已被TH0占用。因此,Timer 1通常在此模式下被用作串口波特率发生器(不需要中断),或者简单地关闭(TR1=0)。
应用场景:当你需要三个独立的定时器,而硬件只提供了两个时,Mode 3可以救急。例如,系统需要一个精确定时器(TH0),一个外部事件计数器(TL0),同时还需要一个波特率发生器(Timer 1)。
2.3 增强型定时器:Timer 2详解
P89C66x系列提供的Timer 2是一个功能更为强大的16位定时器/计数器,它引入了捕获、自动重载(可逆计数)和波特率发生器三种新模式。
核心控制寄存器T2CON(地址C8H):
TF2/EXF2:溢出和外部标志位。Timer 2有两个中断源。RCLK/TCLK:串口接收/发送时钟选择位。这是Timer 2作为波特率发生器的关键。EXEN2:T2EX引脚外部触发允许位。TR2:启动/停止控制。C/T2:定时/计数选择。CP/RL2:捕获/重载选择位。
2.3.1 捕获模式
当CP/RL2=1且RCLK=TCLK=0时,Timer 2工作于捕获模式。此时,TL2和TH2组成一个16位计数器。如果EXEN2=1,则外部引脚T2EX(P1.1)上的一个下降沿,会触发将当前TL2和TH2的计数值“捕获”(复制)到RCAP2L和RCAP2H寄存器中,同时置位EXF2标志。这非常适合测量脉冲宽度或信号周期:在脉冲上升沿启动定时器,在下降沿触发捕获,读取捕获值即可得到时间差。
2.3.2 自动重载模式(可逆计数)
当CP/RL2=0且RCLK=TCLK=0时,Timer 2工作于自动重载模式。这又分为两种子模式:
- 向上计数(DCEN=0,默认):与Timer 1的Mode 2类似,但重载值是16位的。计数器从初值加到
0xFFFF后溢出,硬件将RCAP2L/H的值自动重装入TH2/TL2,并置位TF2。 - 可逆计数(DCEN=1):这是一个独特功能。计数方向由
T2EX引脚电平控制:T2EX=1向上计数,溢出时重载RCAP2L/H;T2EX=0向下计数,当计数值等于RCAP2L/H时,发生“下溢”,计数器重载为0xFFFF。这可用于电机控制、正交编码器解码等需要双向计数的场合。
2.3.3 波特率发生器模式
这是Timer 2最常用的功能之一。当RCLK或TCLK为1时,Timer 2进入波特率发生器模式。此时,Timer 2的溢出脉冲被直接用于产生串口的接收和/或发送时钟。
关键特性:
- 时钟源特殊:作为波特率发生器时,Timer 2的计数脉冲是振荡器频率的1/2(6时钟模式)或1/1(12时钟模式),而不是通常的1/12或1/6。这使得它能在相同晶振下产生更高的波特率。
- 无中断:在此模式下,Timer 2的溢出不会置位
TF2,也不会产生中断。因此无需关闭Timer 2中断。 - 独立收发时钟:
RCLK和TCLK可以独立设置,允许串口的接收和发送使用不同的波特率(分别来自Timer 1和Timer 2),这在某些特殊通信协议中很有用。
波特率计算公式(内部时钟源):波特率 = f_osc / [ n * (65536 - (RCAP2H, RCAP2L)) ]其中,(RCAP2H, RCAP2L)是16位重载值,n在6时钟模式下为16,在12时钟模式下为32。
配置步骤:
- 确定所需波特率和系统时钟
f_osc。 - 根据公式计算重载值
RCAP2H, RCAP2L。 - 设置
T2CON寄存器,令RCLK=1和/或TCLK=1,CP/RL2=0,C/T2=0(选择内部定时)。 - 将计算出的重载值写入
RCAP2H和RCAP2L。 - 置位
TR2启动Timer 2。
注意事项:访问限制当Timer 2作为波特率发生器运行时,不要去读取或写入
TH2和TL2,因为它们在每个状态周期都在变化,读出的值可能不准确。可以读取RCAP2H/L,但写入操作应在关闭Timer 2(TR2=0)后进行,以免与自动重载过程冲突,导致写入错误或重载错误。
3. 全双工增强型UART(串口)工作机制
串口是单片机与外界对话的窗口。80C51的UART是全双工的,意味着它可以同时进行发送和接收,并且具有接收缓冲,可以在读取前一个字节之前就开始接收第二个字节(但如果第二个字节接收完成时第一个还未读取,则会丢失)。
3.1 串口控制核心:SCON寄存器
SCON寄存器(地址98H)是串口的总指挥部,每一位都控制着关键行为:
SM0和SM1:共同决定串口的四种工作模式。SM2:多机通信控制位。在模式2和3中,当SM2=1时,只有接收到第9位数据(RB8)为1(表示地址帧)时,才置位RI引发中断。这用于多机系统中的地址筛选。REN:接收允许位。软件置1才能启动接收。TB8:在模式2和3中,这是要发送的第9位数据。可用于奇偶校验或多机通信中的地址/数据标识。RB8:在模式2和3中,这是接收到的第9位数据;在模式1中,若SM2=0,它存放停止位。TI:发送中断标志。一帧数据发送结束时硬件置1,必须软件清0。RI:接收中断标志。一帧数据接收完成时硬件置1,必须软件清0。
3.2 四种工作模式详解
3.2.1 Mode 0:同步移位寄存器模式
这不是标准的UART,而是一个同步串行扩展模式。
- 数据格式:8位数据,低位在先。
- 引脚:
RXD(P3.0)用于数据输入/输出,TXD(P3.1)输出同步移位时钟。 - 波特率:固定为
f_osc/12(12时钟模式)或f_osc/6(6时钟模式)。 - 应用:常用于通过“串入并出”或“并入串出”移位寄存器(如74HC595、74HC165)来扩展I/O口。
3.2.2 Mode 1:8位UART,可变波特率
这是最常用的异步通信模式。
- 数据格式:1位起始位(0),8位数据位(低位在先),1位停止位(1),共10位。
- 引脚:
TXD发送,RXD接收。 - 波特率:可变,由Timer 1或Timer 2的溢出率决定。公式为:
波特率 = (2^SMOD / 32) × (Timer1溢出率)(12时钟模式)。其中SMOD是PCON寄存器的最高位,加倍波特率。
3.2.3 Mode 2:9位UART,固定波特率
- 数据格式:1位起始位,8位数据位,1位可编程的第9位数据,1位停止位,共11位。
- 第9位用途:发送时由
TB8决定,可作为奇偶校验位或多机通信的地址/数据标识位(1为地址,0为数据)。 - 波特率:固定为
f_osc/64或f_osc/32(由SMOD位选择,12时钟模式)。
3.2.4 Mode 3:9位UART,可变波特率
数据格式与Mode 2完全相同,唯一区别是波特率可变,生成方式与Mode 1相同(使用Timer 1或Timer 2)。Mode 2和3配合SM2位,是实现多机通信的基础。
3.3 波特率生成:定时器与串口的协同
串口通信的时序精度完全依赖于波特率。Mode 1和3的波特率由定时器溢出产生。
使用Timer 1(最常用): 通常将Timer 1配置为Mode 2(8位自动重载),用作波特率发生器。这样无需中断服务程序重装初值,波特率稳定。 计算公式:波特率 = (2^SMOD / 32) × (f_osc / [12 × (256 - TH1)])(12时钟模式)。 因此,TH1重载值 =256 - f_osc × (2^SMOD) / (384 × 波特率)。 例如,在f_osc=11.0592MHz,SMOD=0,目标波特率9600时,计算得TH1 ≈ 0xFD。
使用Timer 2(更精准、更灵活): 如前所述,Timer 2的波特率发生器模式时钟源更快,且为16位自动重载,精度更高,尤其适合高波特率或非标准波特率。 计算公式:RCAP2H, RCAP2L = 65536 - f_osc / (n × 波特率),其中n在12时钟模式下为32。
实操心得三:波特率计算与误差
- 晶振选择:11.0592MHz是一个“魔法数字”,因为它能被许多常用波特率(如9600,19200)整除,计算出的
TH1恰好是整数,没有误差。使用12MHz晶振计算9600波特率时,TH1约为0xFD.xxx,取整为0xFD会产生约0.16%的误差,通常通信仍可接受,但长距离或高速时需注意。- Timer 2的优势:当需要非常高的波特率(如115200以上)或极低的波特率误差时,Timer 2是更好的选择。它的16位重载值提供了更精细的调整粒度。
- 双机通信:通信双方的单片机必须使用相同的波特率、相同的数据格式(数据位、停止位)、相同的时钟模式(6时钟/12时钟)。任何一项不匹配都会导致通信失败。
3.4 增强功能:帧错误检测与自动地址识别
P89C66x的UART在标准基础上增加了两个实用功能:
帧错误检测(FE): 通过设置PCON.6(SMOD0)为1,可以将SCON.7的功能从SM0切换为帧错误标志FE。当接收器检测到无效的停止位(即期望为1,但实际采样为0)时,硬件会自动置位FE。FE只能由软件清除。这个功能在通信环境恶劣、容易产生噪声时非常有用,可以快速识别出受损的数据帧。
自动地址识别: 这是对标准多机通信功能的硬件增强。通过设置SADDR(从机地址寄存器)和SADEN(地址掩码寄存器),可以定义本机地址。当SM2=1且工作在9位数据模式(Mode 2或3)时,只有接收到的地址字节与本地地址匹配(根据掩码),RI才会被置位,从而产生中断。这省去了软件逐个比对地址的开销,提高了多机系统的效率。
掩码SADEN的使用技巧:SADEN中为1的位表示SADDR中对应位必须严格匹配;为0的位表示“不关心”(Don‘t Care)。这允许灵活地定义地址组。例如:
- 主机地址
0x01,掩码0xFF(全匹配),则只响应地址0x01。 - 从机地址
0xC0,掩码0xF0(高4位匹配),则响应地址0xC0~0xCF,可用于对一组设备进行广播式命令下发。
4. 实战配置:从寄存器操作到代码实现
理解了原理,最终要落到代码上。下面以最典型的应用场景为例,展示如何配置。
4.1 场景一:使用Timer 1 Mode 2产生9600波特率,串口Mode 1通信
假设系统使用12MHz晶振,12时钟模式,目标波特率9600,SMOD=0。
计算初值: 波特率 = (2^0 / 32) × (12MHz / (12 × (256 - TH1))) 9600 = (1/32) × (10^6 / (256 - TH1)) 解得:TH1 = 256 - 10^6 / (32 × 9600) ≈ 256 - 3.255 ≈ 253 = 0xFD
初始化代码(汇编风格/C语言描述):
; 串口初始化 MOV SCON, #50H ; 设置串口为Mode 1 (8位UART, REN=1允许接收) MOV PCON, #00H ; 设置SMOD=0 (波特率不加倍) ; 定时器1初始化 (作为波特率发生器) MOV TMOD, #20H ; 设置Timer 1为Mode 2 (8位自动重载),不影响Timer 0 MOV TH1, #0FDH ; 装入波特率重载值 MOV TL1, #0FDH ; 初始计数值 SETB TR1 ; 启动Timer 1 ; 中断系统初始化 (如果需要) SETB ES ; 允许串口中断 SETB EA ; 开启全局中断对应的C语言代码片段(基于Keil C51):
void UART_Init(void) { SCON = 0x50; // Mode 1, 允许接收 PCON &= 0x7F; // SMOD = 0 TMOD &= 0x0F; // 清零Timer 1控制位 TMOD |= 0x20; // 设置Timer 1为Mode 2 TH1 = 0xFD; // 波特率重载值 TL1 = 0xFD; TR1 = 1; // 启动Timer 1 ES = 1; // 使能串口中断 EA = 1; // 开启总中断 }4.2 场景二:使用Timer 2产生115200波特率
假设系统使用11.0592MHz晶振,12时钟模式,目标波特率115200。
计算重载值: 根据公式:RCAP2H, RCAP2L = 65536 - f_osc / (32 × 波特率)RCAP2H, RCAP2L = 65536 - 11059200 / (32 × 115200)= 65536 - 11059200 / 3686400= 65536 - 3 = 65533 = 0xFFFD
初始化代码:
; 首先关闭Timer 2 CLR TR2 ; 配置Timer 2为波特率发生器模式,用于接收和发送 MOV T2CON, #34H ; 0011 0100B: RCLK=1, TCLK=1, CP/RL2=0, TR2=0 MOV RCAP2H, #0FFH ; 装入重载值高字节 MOV RCAP2L, #0FDH ; 装入重载值低字节 MOV TH2, #0FFH ; 初始化计数器高字节 (可省略,但建议写入) MOV TL2, #0FDH ; 初始化计数器低字节 ; 配置串口为Mode 1 MOV SCON, #50H ; 启动Timer 2 SETB TR2注意事项:Timer 2的启动顺序对于Timer 2,特别是作为波特率发生器时,我强烈建议采用“先配置,后启动”的顺序。即先清零
TR2停止定时器,然后配置T2CON、写入RCAP2H/L,最后再置位TR2。这可以避免在配置过程中计数器意外运行,导致初始波特率错误。
4.3 场景三:利用Timer 0 Mode 1实现50ms精确定时
假设系统使用12MHz晶振,12时钟模式,目标定时50ms。
计算初值: 机器周期 = 12 / 12MHz = 1μs。 所需计数值 = 50ms / 1μs = 50000。 16位计数器最大计数值65536。 初值X = 65536 - 50000 = 15536 = 0x3CB0。
初始化代码:
; 定时器0初始化 (16位定时模式) MOV TMOD, #01H ; 设置Timer 0为Mode 1 (16位定时器),GATE=0 MOV TH0, #3CH ; 装入初值高字节 0x3C MOV TL0, #0B0H ; 装入初值低字节 0xB0 SETB ET0 ; 允许Timer 0中断 SETB TR0 ; 启动Timer 0 SETB EA ; 开启全局中断中断服务程序中重载初值: 由于Mode 1不会自动重载,必须在每次中断中手动重装初值。
TIMER0_ISR: CLR TR0 ; 暂停定时器(可选,提高重载精度) MOV TH0, #3CH ; 重装高字节 MOV TL0, #0B0H ; 重装低字节 SETB TR0 ; 重启定时器 ... ; 执行定时任务 CLR TF0 ; 清除溢出标志(硬件可能已清,但软件清除更安全) RETI5. 常见问题排查与调试经验实录
理论配置看似简单,但调试中总会遇到各种“坑”。下面是我总结的几个典型问题及解决方法。
5.1 波特率不准,通信乱码
这是最常见的问题。
- 检查晶振频率:用示波器测量单片机XTAL2引脚,确认实际振荡频率是否与程序设定值一致。11.0592MHz和12MHz的代码不能混用。
- 核对时钟模式:确认单片机是工作在6时钟模式还是12时钟模式(通常由芯片配置或烧录选项决定)。这直接影响机器周期和所有定时相关的计算。P89C66x系列通常可通过编程器配置。
- 验算初值:重新用公式计算
TH1或RCAP2H/L的值。特别注意SMOD位是否设置正确。对于Timer 1,SMOD=1会使波特率加倍。 - 检查Timer配置:确认定时器是否工作在正确的模式(Timer 1应为Mode 2,Timer 2应使能
RCLK/TCLK)。确认TRx位已置1,定时器已启动。 - 测量实际波特率:让单片机持续发送
0x55(二进制01010101),用示波器测量TXD引脚上一个位的时间宽度。0x55的波形是标准的方波,其周期T的倒数即为实际波特率。与目标值对比。
5.2 发送正常,但接收不到数据或数据错误
- 确认双机共地:这是硬件基础,两个系统的GND必须连接在一起。
- 检查
REN位:接收允许位REN必须置1,否则串口不会接收任何数据。 - 查询
RI与中断:如果使用查询方式,必须在主循环中不断检查RI标志,并在读取SBUF后立即用软件清零RI。如果使用中断,确保中断服务程序(ISR)正确读取了SBUF并清除了RI。RI不清零会导致无法触发下一次接收中断。 - 注意
SM2位:在单机通信(Mode 1)或作为多机通信的主机时,SM2应设为0。如果误设为1,在Mode 1下会要求有效的停止位(为1)才能置位RI,若线路干扰导致停止位出错,则收不到数据。 - 电压电平匹配:如果连接的是RS-232设备(如电脑串口),需要MAX232等电平转换芯片。直接连接TTL电平到RS-232端口会损坏芯片或无法通信。
5.3 定时器中断不触发或触发过于频繁
- 中断系统总开关
EA:必须置1。 - 定时器中断允许位
ETx:必须置1。 - 中断标志
TFx:在中断服务程序中,虽然硬件在跳入中断时可能自动清除了TF0/TF1,但为了代码清晰和兼容性,建议手动再清除一次。对于Timer 2,要检查是TF2还是EXF2引起的中断,并分别清除。 - 中断优先级:如果同时开启了多个中断,检查
IP和IPH寄存器,确保定时器中断的优先级没有被其他长时间中断阻塞。 - 初值计算错误:如果初值算错,导致定时时间极短,就会感觉中断“过于频繁”。重新核对计算过程。
5.4 多机通信失败
- 确保所有从机
SM2=1,主机SM2=0。 - 主机发送地址帧时,第9位(
TB8)必须置1;发送数据帧时,TB8必须清0。 - 从机地址识别逻辑:从机在收到地址帧(
RB8=1)后,应将自己接收到的地址与本地SADDR比较(考虑SADEN掩码)。如果匹配,则软件清除本机的SM2位,以准备接收后续的数据帧。数据接收完成后,应重新置位SM2,等待下一个地址帧。 - 广播地址:广播地址是
SADDR和SADEN逻辑或的结果,通常为0xFF。主机发送地址0xFF且TB8=1,所有SM2=1的从机都应响应。
5.5 使用增强型UART的帧错误检测
当发现通信不稳定时,可以启用帧错误检测功能。
- 置位
PCON.6(SMOD0),使能FE功能位。 - 在串口接收中断或查询到
RI=1后,不仅读取SBUF,也检查SCON.7(现在是FE位)。 - 如果
FE=1,表示这一帧数据的停止位出错,数据可能不可靠,应做丢弃或重发处理。 - 软件清除
FE位(写0)。
if (RI) { RI = 0; // 清除接收中断标志 if (FE) { // 检查帧错误 FE = 0; // 清除帧错误标志 // 处理错误帧,例如丢弃数据或请求重发 error_handler(); } else { // 处理正常接收的数据 process_data(SBUF); } }通过以上从原理到寄存器,从配置到调试的完整梳理,相信你对80C51的定时器、计数器和串口有了更立体、更深入的理解。这些外设是单片机功能的骨架,掌握它们,就掌握了让单片机“按时做事”和“与人交流”的核心能力。在实际项目中,多动手配置,多借助示波器观察波形,遇到问题对照手册和本文的思路逐一排查,经验自然就会积累起来。