1. 项目概述:深入理解MC68HC908AZ60A的TIMB模块
在嵌入式开发,尤其是涉及电机驱动、电源管理或通信协议解析的项目里,精准的时序控制往往是决定系统稳定性和性能的关键。很多新手工程师在面对数据手册中复杂的定时器章节时,常常感到无从下手,寄存器配置表看花了眼,功能描述读起来也似懂非懂。如果你正在使用Freescale(现NXP)的MC68HC908AZ60A这款经典的8位微控制器,并且需要用到它的Timer Interface Module B(TIMB),那么这篇文章就是为你准备的。我将结合自己多年在工业控制项目中使用HC08系列MCU的经验,为你彻底拆解TIMB模块的输入捕获、输出比较和PWM功能,把数据手册里那些干巴巴的描述,变成可以直接“抄作业”的配置步骤和避坑指南。
MC68HC908AZ60A的TIMB模块是一个16位的定时器,它最核心的价值在于,能用硬件帮你完成“计时”和“比较”这两件最耗CPU精力的事。想象一下,你需要测量一个传感器脉冲的宽度,如果让CPU不停地去查询引脚状态并记录时间,那CPU就几乎干不了别的了。而输入捕获功能,可以在脉冲边沿到来的瞬间,自动把当前定时器的计数值“冻结”到寄存器里,你只需要在合适的时候去读取这个值即可。同样,输出比较功能可以让你设定一个时间点,时间一到,硬件自动改变引脚电平,生成精准的方波,CPU完全不用干预。PWM(脉冲宽度调制)则是输出比较的一种高级应用,通过周期性改变输出比较值,就能生成占空比可调的波形,这是驱动电机、LED调光、DAC模拟的基础。
这个TIMB模块提供了两个独立的通道(Channel 0和Channel 1),每个通道都可以被灵活配置为输入捕获或输出比较模式。更厉害的是,这两个通道还能“联手”工作,形成 缓冲输出比较 和 缓冲PWM 模式,这能在不干扰当前输出波形的前提下,提前准备好下一个周期的参数,实现无缝切换,对于生成复杂、稳定的波形至关重要。接下来,我们就从最根本的模块结构和寄存器配置讲起,一步步摸清它的脾气。
2. TIMB模块整体架构与核心寄存器解析
要驾驭TIMB,首先得看懂它的“大脑”和“手脚”——也就是控制寄存器与数据通路。很多朋友一上来就照着例程配置,结果出了问题也不知道寄存器某一位到底起了什么作用,调试起来一头雾水。我们必须先建立起清晰的模块框图。
2.1 模块核心:16位计数器与时钟源
TIMB的核心是一个16位向上计数器(TBCNTH:TBCNTL)。它可以工作在两种模式下: 自由运行模式 和 模数计数模式 。在自由运行模式下,计数器从0x0000开始,一直累加到0xFFFF,然后溢出回到0x0000重新开始,如此循环。在模数计数模式下,计数器从0x0000开始,累加到我们预设的一个模数值(存放在TBMODH:TBMODL寄存器中),然后溢出归零。这个模数值就决定了定时器溢出的周期,是PWM周期和许多定时任务的时间基准。
这个计数器的“心跳”时钟从哪里来?由TIMB状态控制寄存器(TBSC)中的PS[2:0]这三位决定。它们提供了7个内部总线时钟的分频选项(1, 2, 4, 8, 16, 32, 64分频)和一个外部时钟输入选项。
关键经验 :选择时钟源是计算所有时间参数的第一步。例如,如果你的系统总线频率是8MHz,选择4分频(PS[2:0]=010),那么TIMB的计数时钟就是2MHz,每个计数周期就是0.5微秒。这直接决定了你能测量的最小时间分辨率(0.5us)和能生成的最短PWM脉冲。
外部时钟通过PTD4/ATD12/TBCLK引脚输入,最高频率不能超过4MHz或总线频率的一半(取两者中较小值)。使用外部时钟时,需要将PS[2:0]设置为111,并且将该引脚配置为输入(无论DDRD4如何设置,此时它都是输入模式)。
2.2 控制与状态寄存器:TBSC
地址
$0040
的TBSC寄存器是TIMB的总指挥。我们逐位分析:
- TOF(Bit 7) :溢出标志位。当计数器达到模数值(模数模式)或0xFFFF(自由运行模式)时,硬件自动置1。 清除它需要“读-改-写”操作 :先读取TBSC(此时TOF=1),然后向TOF位写0。这个顺序很重要,是防止丢失中断请求的关键机制。
- TOIE(Bit 6) :溢出中断使能位。置1后,当TOF=1时,会向CPU申请中断。
- TSTOP(Bit 5) :定时器停止位。置1则计数器暂停。 特别注意 :在需要TIMB中断唤醒WAIT模式的场景下,绝对不能设置此位。同时,如果设置此位前有定时器标志位(如TOF)已经置1,必须先清除TSTOP,再清除标志位,最后再置位TSTOP,否则标志位可能无法正确清除。
- TRST(Bit 4) :定时器复位位。 这是一个只写位,读出来永远是0 。向它写1会立即将计数器和预分频器清零,然后从0开始计数。它不影响其他任何寄存器。通常用于定时器的精确同步启动。
- PS[2:0](Bit 2-0) :如前所述,时钟预分频选择位。
2.3 通道控制寄存器:TBSC0与TBSC1
每个通道都有一个自己的控制寄存器(TBSC0地址
$0045
,TBSC1地址
$0048
),结构类似但略有不同(Channel 1没有MS1B位)。它们是配置通道具体行为的关键。
- CHxF(Bit 7) :通道x标志位。在输入捕获模式下,当指定边沿到来时置1;在输出比较模式下,当计数器值与通道寄存器值匹配时置1。清除方式同TOF,也需要“读-改-写”序列。
- CHxIE(Bit 6) :通道x中断使能位。
- MSxB(仅TBSC0有,Bit 5) :模式选择B位。这是实现 缓冲模式 的开关。 只有当MS0B=1时,Channel 0和Channel 1才会被链接起来,用于缓冲输出比较或缓冲PWM,此时Channel 1的控制寄存器TBSC1失效,其引脚PTF5/TBCH1可作为通用IO使用。
- MSxA(Bit 4) :模式选择A位。它与ELSxB:A位共同决定通道模式,具体组合见下文表格。
-
ELSxB, ELSxA(Bit 3, Bit 2)
:边沿/电平选择位。这是配置中最灵活也最容易出错的地方。它根据MSxA的状态,有不同的含义:
- 当通道被配置为输入捕获(MSxA=0)时,它们选择捕获边沿:01=上升沿,10=下降沿,11=任意边沿。
- 当通道被配置为输出比较/PWM(MSxA=1)时,它们选择匹配动作:01=翻转,10=清零,11=置位。
- 当ELSxB:A = 00时,通道与引脚断开,引脚归端口控制。此时MSxA决定引脚初始电平(1=低,0=高)。
- TOVx(Bit 1) :溢出翻转位。这是实现PWM功能的核心之一。置1后,每次定时器溢出(TOF置位)时,对应通道的引脚电平会自动翻转。 对于PWM生成,此位必须置1 。
- CHxMAX(Bit 0) :通道x最大占空比位。当TOVx=1且CHxMAX=1时,会强制输出100%占空比(常高)的PWM信号。结合TOVx=0可以产生0%占空比(常低)。
为了更直观地理解MSx和ELSx位的组合,我将数据手册中的表格重新整理并加入了中文注释:
| MSxB | MSxA | ELSxB | ELSxA | 模式与配置 | 功能说明 |
|---|---|---|---|---|---|
| X | 0 | 0 | 0 | 输出预置 | 引脚由端口控制,初始输出高电平(MSxA=0) |
| X | 1 | 0 | 0 | 输出预置 | 引脚由端口控制,初始输出低电平(MSxA=1) |
| 0 | 0 | 0 | 1 | 输入捕获 | 仅在上升沿触发捕获 |
| 0 | 0 | 1 | 0 | 输入捕获 | 仅在下降沿触发捕获 |
| 0 | 0 | 1 | 1 | 输入捕获 | 上升沿或下降沿均触发捕获 |
| 0 | 1 | 0 | 0 | 输出比较/PWM | 软件比较 (仅置标志,不操作引脚) |
| 0 | 1 | 0 | 1 | 输出比较/PWM | 比较匹配时翻转引脚 |
| 0 | 1 | 1 | 0 | 输出比较/PWM | 比较匹配时清零引脚(输出低) |
| 0 | 1 | 1 | 1 | 输出比较/PWM | 比较匹配时置位引脚(输出高) |
| 1 | X | 0 | 1 | 缓冲输出比较/PWM | 比较匹配时翻转引脚 (双通道缓冲) |
| 1 | X | 1 | 0 | 缓冲输出比较/PWM | 比较匹配时清零引脚 (双通道缓冲) |
| 1 | X | 1 | 1 | 缓冲输出比较/PWM | 比较匹配时置位引脚 (双通道缓冲) |
2.4 数据寄存器:计数器、模值与通道寄存器
-
TIMB计数器寄存器(TBCNTH:
$0041, TBCNTL:$0042) :只读。这里有个 重要细节 :读取高字节(TBCNTH)时,低字节(TBCNTL)的当前值会被锁存到一个缓冲区。后续读取TBCNTH得到的都是这个锁存值,直到你读取一次TBCNTL,这个锁存才会更新。因此,为了读取完整的16位计数器值,必须先读TBCNTH,再读TBCNTL。 在断点中断中读取时,务必在退出断点前读取TBCNTL来解锁,否则TBCNTL将一直保持断点时的锁存值。 -
TIMB计数器模数寄存器(TBMODH:
$0043, TBMODL:$0044) :读写。设置模数值。 写入时必须先写高字节(TBMODH),再写低字节(TBMODL) 。在写高字节后、写低字节前,溢出标志TOF和溢出中断会被禁止,以防止出现错误的溢出事件。 最佳实践是,在修改模数值前,先用TRST位复位计数器。 -
TIMB通道寄存器(TBCH0H:
$0046, TBCH0L:$0047, TBCH1H:$0049, TBCH1L:$004A) :读写。在输入捕获模式下,它们是只读的,存放捕获到的计数值。在输出比较/PWM模式下,它们存放用于比较的目标值。
3. 三大功能模式详解与实战配置
理解了寄存器,我们就可以深入三大功能模式了。我会为每种模式提供清晰的配置流程、代码片段(基于C语言伪代码)和必须注意的“坑”。
3.1 输入捕获模式:精准测量时间间隔
输入捕获的本质,是在你关心的外部事件(引脚边沿)发生的那个瞬间,让硬件自动“拍一张快照”,把当前计数器的值保存起来。这常用于测量脉冲宽度、信号周期或频率。
配置流程与示例:测量PTF4引脚上正脉冲的宽度
假设我们需要测量PTF4/TBCH0引脚上一个正脉冲的高电平持续时间。思路是:在上升沿和下降沿各捕获一次,两次捕获值之差就是高电平持续的计数次数,再乘以计数周期就得到时间。
-
初始化TIMB基础时钟 :假设总线频率8MHz,我们选择8分频,则TIMB时钟为1MHz,计数周期为1us。
// TBSC: 停止定时器,复位,选择时钟,禁止溢出中断 TBSC = 0x20 | 0x10 | 0x03; // TSTOP=1, TRST=1, PS=011 (8分频) // 注意:TRST是只写位,上述操作后应清除TRST启动,但通常先配置其他寄存器 -
配置通道0为输入捕获 :捕获上升沿和下降沿。
// TBSC0: 输入捕获模式,任意边沿触发,禁止中断(先轮询) // MS0A=0 (输入捕获), ELS0B:A=11 (任意边沿) TBSC0 = 0x0C; // 二进制 0000 1100 -
启动定时器并清空旧标志 :
// 清除可能存在的旧标志 dummy = TBSC0; // 读操作 TBSC0 &= ~0x80; // 写0清除CH0F dummy = TBSC; // 读操作 TBSC &= ~0x80; // 写0清除TOF // 启动定时器:清除TSTOP和TRST TBSC &= ~0x30; // 清除TSTOP(bit5)和TRST(bit4) -
等待并处理捕获事件 :
unsigned int rise_time, fall_time, pulse_width; // 等待上升沿 while(!(TBSC0 & 0x80)); // 等待CH0F置位 rise_time = (unsigned int)TBCH0H << 8 | TBCH0L; dummy = TBSC0; TBSC0 &= ~0x80; // 清除CH0F标志 // 等待下降沿 while(!(TBSC0 & 0x80)); fall_time = (unsigned int)TBCH0H << 8 | TBCH0L; // 计算脉冲宽度(考虑计数器溢出) if(fall_time >= rise_time) { pulse_width = fall_time - rise_time; } else { // 发生了溢出,需要结合溢出次数计算,这里简化处理 pulse_width = (65536 - rise_time) + fall_time; } // 实际时间 = pulse_width * 1 us (根据时钟分频计算)
避坑指南 :
- 边沿稳定性 :在使能输入捕获前,务必确保目标引脚的电平已经稳定了至少两个总线周期,否则可能捕获到毛刺。
- 计数器溢出处理 :在测量长间隔信号时,定时器可能溢出多次。简单的差值计算会出错。 可靠的方案是 :开启溢出中断(TOIE=1),在中断服务程序里维护一个软件扩展的“溢出计数器”(比如一个
volatile unsigned long overflow_count)。计算时间时:总时间 = (overflow_count * 65536) + (capture_value - previous_capture_value)。在捕获中断里也要记录对应的溢出计数。- 标志清除顺序 :务必遵循“先读寄存器(标志位置1时),再写0清除”的顺序。直接写0是无效的。
3.2 输出比较模式:硬件定时与波形生成
输出比较模式是让硬件帮你“守时”。你设定一个目标计数值(存入通道寄存器),当定时器计数达到这个值时,硬件会自动执行你预设的动作(置高、置低或翻转引脚),并可以产生中断。这非常适合生成精确的延时、方波或驱动时序。
配置流程与示例:在PTF4引脚生成一个1KHz,占空比50%的方波
假设TIMB时钟为1MHz(8MHz总线,8分频)。1KHz方波周期为1ms,即1000个计数周期。50%占空比意味着高电平持续500个计数周期。
-
初始化TIMB基础时钟与模值
:我们使用自由运行模式(模值寄存器保持0xFFFF),或者将模值设为999(0x03E7)以实现精确的1ms溢出周期。这里采用模数模式,方便后续扩展。
// 1. 停止并复位定时器 TBSC = 0x30 | 0x03; // TSTOP=1, TRST=1, PS=011 // 2. 设置模值,决定方波周期 (1000个计数 -> 1ms) TBMODH = 0x03; // 1000 = 0x03E8 TBMODL = 0xE8; // 注意:先写高字节,再写低字节 // 3. 配置通道0为输出比较,匹配时翻转引脚,并使能溢出翻转(用于生成周期) // MS0A=1 (输出比较), ELS0B:A=01 (翻转), TOV0=1 (溢出时也翻转) TBSC0 = 0x12; // 二进制 0001 0010 // 4. 设置比较值,决定第一次翻转(即上升沿)的时间点 (500个计数 -> 0.5ms) TBCH0H = 0x01; TBCH0L = 0xF4; // 500 = 0x01F4 // 5. 启动定时器 TBSC &= ~0x30; // 清除TSTOP和TRST
这段代码配置后,引脚PTF4会输出精确的1KHz方波。其工作原理是:
- 计数器从0开始,计数到500(0x01F4)时,发生比较匹配,根据ELS0B:A=01的配置,引脚电平翻转(假设初始为低,则变为高)。
- 计数器继续计数到1000(0x03E8)时,发生溢出(TOF置位),根据TOV0=1的配置,引脚电平再次翻转(高变回低)。同时计数器归零,开始下一个周期。
- 如此循环,就得到了周期1ms(1000计数)、高电平0.5ms(500计数)的方波。
核心要点 :在这个例子中, 输出比较决定了脉冲的边沿(上升沿),而定时器溢出决定了周期的结束(下降沿) 。两者结合才构成了一个完整的PWM周期。这正是PWM模式的基础。
3.3 PWM模式:缓冲与非缓冲的深度解析
PWM可以看作是输出比较的一种自动化、周期性的应用。TIMB支持两种PWM生成方式: 非缓冲PWM 和 缓冲PWM 。它们的区别是更新占空比时的“安全性”。
非缓冲PWM :直接向当前正在控制输出的通道寄存器写入新的比较值。如果写入时机不对(比如在计数器已经超过新旧值之间的某个时刻写入),可能导致当前周期波形错误,甚至丢失一次比较事件。数据手册给出了安全的更新策略:
- 当需要减小占空比(新值 < 旧值)时 :在 输出比较中断 中更新新值。因为中断发生在当前脉冲边沿之后,你有整个剩余周期的时间去写入,确保在下一个周期生效。
- 当需要增大占空比(新值 > 旧值)时 :在 定时器溢出中断 中更新新值。因为中断发生在周期结束、新周期开始时,此时写入最安全。如果在输出比较中断中写入一个更大的值,可能导致在当前周期内发生第二次比较匹配,产生错误波形。
缓冲PWM(双通道链接) :这是TIMB的一个高级特性,通过将Channel 0和Channel 1链接起来实现。其核心思想是“双缓冲”或“乒乓缓冲”:一个通道(例如Ch0)控制当前周期的输出,另一个通道(Ch1)则预先写入下一个周期的值。在当前周期结束时(溢出瞬间),硬件会自动切换,让Ch1的值生效,同时Ch0变为缓冲寄存器,可以安全地写入再下一个周期的值。这样就完全避免了写入冲突,可以实现平滑、无毛刺的PWM更新,特别适用于电机控制等对波形连续性要求高的场合。
配置流程与示例:在PTF4引脚生成缓冲PWM,频率100Hz,初始占空比30%
假设总线频率8MHz,预分频64,则TIMB时钟为125KHz。100Hz对应周期10ms,即1250个计数周期。30%占空比对应高电平时间375个计数周期。
-
初始化TIMB :
// 1. 停止并复位定时器 TBSC = 0x30 | 0x06; // TSTOP=1, TRST=1, PS=110 (64分频) // 2. 设置PWM周期 (1250 = 0x04E2) TBMODH = 0x04; TBMODL = 0xE2; // 3. 配置通道0和1为缓冲PWM模式 // 首先,设置TBSC0:MS0B=1 (使能缓冲模式), MS0A无关, ELS0B:A=10 (匹配时清零引脚), TOV0=1 (溢出翻转) // 我们希望PWM高电平有效,则匹配时应清零(变低),溢出时翻转(变高)。 TBSC0 = 0x2C; // 二进制 0010 1100 (MS0B=1, ELS0B:A=10, TOV0=1) // 此时,TBSC1寄存器被忽略,PTF5/TBCH1引脚可作为通用IO。 -
设置初始占空比 :
// 4. 初始输出由Channel 0寄存器控制。设置比较值(决定高电平结束时间) // 占空比30%,高电平时间 = 1250 * 0.3 = 375 = 0x0177 TBCH0H = 0x01; TBCH0L = 0x77; // 5. 预先填充Channel 1寄存器(缓冲寄存器),假设我们下一个周期想改为50%占空比 // 50%占空比,高电平时间 = 1250 * 0.5 = 625 = 0x0271 TBCH1H = 0x02; TBCH1L = 0x71; -
启动定时器 :
// 6. 启动定时器 TBSC &= ~0x30; // 清除TSTOP和TRST
运行后,PTF4引脚将输出100Hz,占空比30%的PWM波。在第一个周期结束时(计数器溢出),硬件会自动将控制权从TBCH0H:L切换到TBCH1H:L,于是第二个周期占空比变为50%。 关键来了 :在第二个周期期间,软件可以安全地向 当前未激活 的寄存器(此时是TBCH0H:L)写入第三个周期的占空比值(例如0x03E8对应80%),而不会干扰正在输出的波形。
缓冲模式下的致命陷阱 : 绝对不要向当前正在控制输出的那个通道寄存器写入新值! 这相当于破坏了缓冲机制,回到了非缓冲模式,可能引发波形错误。软件必须跟踪当前是哪个通道在控制输出(通常可以通过检查上一次是在哪个通道的中断里更新的,或者利用一个软件标志位来跟踪)。
4. 高级应用与疑难问题排查
掌握了基本模式后,我们来看一些更复杂的场景和那些容易让人栽跟头的问题。
4.1 利用输入捕获与输出比较实现可编程延迟
这是一个经典组合应用:在检测到一个外部事件(如按键按下)后,需要精确延迟一段时间再执行动作(如点亮LED)。用CPU软件延时不准且占用资源,用定时器则非常精准。
思路 :
- 将一个通道(如Ch0)配置为输入捕获,捕获事件边沿。
-
在输入捕获中断服务程序中,读取捕获到的时刻
capture_val。 -
计算目标时刻:
target_val = capture_val + delay_ticks。注意处理溢出(如果相加结果超过0xFFFF,则取模)。 -
将
target_val写入另一个配置为输出比较的通道(如Ch1)的寄存器,并设置匹配时执行所需操作(如置位引脚)。 - 使能Ch1的输出比较中断,在中断中执行后续动作。
这样,从事件发生到动作执行,延迟时间就是
delay_ticks * timer_period
,由硬件精确保证,不受其他中断或代码执行时间影响。
4.2 低功耗模式下的TIMB行为
MCU进入WAIT模式后,TIMB默认继续运行。如果你的应用依赖TIMB中断来唤醒MCU,那么 绝对不能 在进入WAIT前设置TSTOP位。同时,在WAIT模式下,CPU不能访问TIMB寄存器。如果不需要TIMB唤醒,则在进WAIT前停止TIMB可以降低功耗。
执行STOP指令后,TIMB时钟停止,模块完全冻结。唤醒后,TIMB从停止时的状态继续运行。这意味着计数器值、寄存器配置全部保持原样。
4.3 常见问题排查清单
当你配置的TIMB功能不按预期工作时,可以按以下清单逐一排查:
-
完全没有输出或捕获不到 :
- 引脚复用 :PTF4/TBCH0和PTF5/TBCH1是复用引脚。你配置了TIMB功能,但相应的端口方向寄存器(DDRF)配置对了吗?对于输出模式,需要将DDRFx设为1(输出);对于输入捕获模式,DDRFx应设为0(输入)。 一个常见错误是只配置了TIMB,忘了配置端口方向 。
- 时钟源 :TBSC中的PS[2:0]选对了吗?TSTOP位清除了吗?用示波器或软件读取TBCNTH:L,看看计数器在递增吗?
- 模式选择 :TBSCx中的MSxA和ELSxB:A位组合是否正确?对照前面的表格仔细检查。例如,想输出PWM,但MSxA设成了0,那就成了输入捕获模式。
-
PWM频率或占空比不对 :
-
计算错误
:重新计算周期和占空比对应的计数值。公式:
计数值 = 时间 / 定时器时钟周期。定时器时钟周期 =1 / (总线频率 / 预分频系数)。 - 模数寄存器 :PWM周期由TBMODH:L决定,你写入了吗?写入顺序对吗(先高后低)?
- 比较值寄存器 :占空比由通道寄存器TBCHxH:L决定。在非缓冲模式下,你更新的是正确的寄存器吗?在缓冲模式下,你更新的是非活动通道的寄存器吗?
- TOVx位 :生成PWM必须将TOVx置1,否则引脚只会在比较匹配时动作一次,不会周期性翻转。
-
计算错误
:重新计算周期和占空比对应的计数值。公式:
-
中断不触发 :
- 中断使能 :TBSC中的TOIE(溢出中断)或TBSCx中的CHxIE(通道中断)置1了吗?
-
MCU总中断
:MCU的全局中断开关(通常类似
asm(“cli”)或asm(“sei”)指令)打开了吗? - 中断标志 :中断服务程序(ISR)里清除标志位了吗?必须用“先读后写0”的顺序清除TOF或CHxF。
- 中断向量 :你的开发环境正确设置了TIMB溢出或通道中断的中断服务程序入口地址吗?
-
缓冲PWM模式下载入异常 :
- MS0B位 :确保TBSC0的MS0B位被置1,这是启用双通道缓冲的唯一开关。
-
通道跟踪
:你的软件逻辑是否准确跟踪了当前哪个通道(0或1)是活动通道?是否错误地向活动通道写了数据?建议用一个
volatile变量,在溢出中断中翻转其值来指示当前活动通道。 - 初始化顺序 :严格按照数据手册20.3.4.3节的PWM初始化流程:先停止(TSTOP)复位(TRST)定时器,再写模值(TBMOD)和比较值(TBCHx),最后配置控制寄存器(TBSCx)并启动定时器(清TSTOP)。
-
测量输入捕获值不稳定 :
- 信号毛刺 :被测信号是否有抖动或毛刺?可以在输入端增加简单的RC滤波。
- 边沿选择 :是否错误配置了边沿?用示波器观察信号,确认你配置的边沿(上升、下降、任意)与实际信号一致。
- 消抖处理 :对于机械开关等信号,必须在硬件或软件上做消抖处理,否则会多次触发捕获。
调试时,最有效的工具就是读取寄存器状态。编写一个简单的函数,通过串口打印出TBSC、TBSC0、TBSC1、TBCNTH:L、TBMODH:L、TBCH0H:L、TBCH1H:L等关键寄存器的值,与实际预期对比,大部分问题都能定位。记住,嵌入式编程,尤其是底层驱动, “寄存器状态就是一切” 。

3万+


被折叠的 条评论
为什么被折叠?



