手册确认了关键信息。现在我可以给出准确的分析。
问题分析
您帖子里遇到的"定时器失效、灯一直亮但不闪"的问题,根源在于缺少了 ET0 = 1; 这一句。
为什么灯不闪?
您的主程序里虽然执行了:
Timer0_Init(); // 定时器0初始化
EA = 1; // 使能总中断
但根据 AI8051U 数据手册《中断系统》 一章的中断使能寄存器(IE)说明,中断允许是多级控制的:
"EA:总中断允许控制位。**EA的作用是使中断允许形成多级控制。**即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。"
也就是说,中断要能进入,必须同时满足两个条件:
- 总中断
EA = 1(您已经做了)
- 对应中断源自身的使能位要让能(您漏掉了)
对于定时器0,就是 ET0(定时/计数器 T0 的溢出中断允许位):
"ET0:定时/计数器T0的溢出中断允许位。
0:禁止T0中断
1:允许T0中断"
您的 Timer0_Init() 里只启动了定时器(TR0 = 1),但没有把 ET0 置 1,所以定时器虽然在跑,但它的中断请求无法被 CPU 响应,中断服务函数 Timer0_Isr 永远不会被执行,P2 = ~P2 自然也就不会执行 —— 灯就一直亮着不闪了。
您之前"还好好的",为什么突然失效?
很可能您之前用的例程(或早期版本)里是有 ET0 = 1; 的,后来改写代码时不小心把这句删掉了。这也是论坛回复中"狂热***"提醒你"可能缺少 ET0 = 1"的原因,他给出的正确初始化里就明确包含了 ET0 = 1; //Enable timer0 interrupt。
正确的修改方法
请在您的 Timer0_Init() 函数中、TR0 = 1; 之后(或之前)补上 ET0 = 1;:
void Timer0_Init(void) //100毫秒@40.000MHz
{
TM0PS = 0x3F; //设置定时器时钟预分频
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xDC; //设置定时初始值
TH0 = 0x0B; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //★ 使能定时器0中断(缺失这句导致不闪)
}
修改后,配合主程序里的 EA = 1;,定时器0的中断就能正常响应,LED 就会开始闪烁了。
小结
| 中断响应条件 |
您代码中状态 |
EA = 1(总中断) |
✅ 已有 |
ET0 = 1(T0中断允许) |
❌缺失,需补上 |
TR0 = 1(定时器运行) |
✅ 已有 |
信息来源:AI8051U 数据手册《中断系统》章节——中断使能寄存器(IE)中 ET0 及 EA 的多级控制说明。
方便的话,您可以补上这句后再测一下,如果还有问题欢迎继续反馈。另外如果您的实验板接有 USB 相关中断,也请确认不影响定时器中断的响应优先级。
🔍 搜索 "https://www.stcaimcu.com/thread-25299-1-1.html"
⏱️ 查找用时 8.3s | 总回答用时 16.0s