利用P3.3接一个外部中断输入,控制8个LED灯循环点亮,当外部中断未发生时,系统通过定时器完成定时0.5s的延时,使发光二极管呈从左到右的顺序一次被点亮,当有中断产生时,发光二极管则闪烁。
时间: 2024-03-14 17:47:15 浏览: 91
好的,这是一道稍微复杂一点的题目,需要借助中断和定时器的知识。以下是代码实现:
```c
#include <reg51.h> // 51单片机头文件
void delay(unsigned int xms); // 延时函数声明
void main()
{
unsigned char i = 0; // 定义计数器变量 i
unsigned char flag = 0; // 定义标志位变量 flag
TMOD = 0x01; // 设置定时器 0 为模式 1
TH0 = 0x3C; // 计时 0.5s
TL0 = 0xAF;
ET0 = 1; // 允许定时器 0 中断
TR0 = 1; // 启动定时器 0
EX0 = 1; // 允许外部中断 0
IT0 = 1; // 设置外部中断 0 为下降沿触发
while(1) // 循环执行
{
if(flag == 0) // 当外部中断未发生时
{
P1 = ~(0x01 << i); // P1口输出对应的LED灯亮
delay(500); // 延时 500ms
i++; // i 递增
if(i == 8) i = 0; // i 大于等于 8 时重置为 0
}
}
}
void delay(unsigned int xms) // 延时函数定义
{
unsigned int i, j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void timer0() interrupt 1 // 定时器 0 中断服务函数
{
unsigned char i;
for(i=0;i<8;i++) // 8个LED灯循环点亮
{
P1 = ~(0x01 << i);
delay(50); // 延时 50ms
}
}
void int0() interrupt 0 // 外部中断 0 中断服务函数
{
unsigned char i;
unsigned char flag = 1; // 标记外部中断已经发生
for(i=0;i<8;i++) // 8个LED灯闪烁
{
P1 = ~(0x01 << i);
delay(100); // 延时 100ms
P1 = 0xFF;
delay(100);
}
}
```
代码解析:
- 程序运行时,先定义计数器变量 i 和标志位变量 flag。
- 然后设置定时器 0 为模式 1,即 16 位自动重装载计数器,每次计数完毕后自动从 TH0 和 TL0 中重新加载计数值。
- 设置 TH0 和 TL0 的初值,使定时器每次计满 65536-500=65036 个时钟周期,即约为 0.5s。
- 允许定时器 0 中断和外部中断 0,设置外部中断 0 为下降沿触发。
- 进入 while(1) 循环体,即不断执行以下循环。
- 如果 flag 等于 0,即外部中断未发生时,进入 if 语句体。
- 在 if 语句体中,P1 口输出 ~(0x01 << i) 的值,即对应的 LED 灯亮起来。
- 延时 500ms 后,LED 灯熄灭,i 继续递增,进入下一个循环。
- 当 i 递增到 8 时,i 重置为 0。
- 如果 flag 等于 1,即外部中断已经发生时,flag 的值不变,程序不再执行 if 语句体。
- 当定时器 0 计满 0.5s 时,进入定时器 0 中断服务函数 timer0()。
- 在 timer0() 函数中,8 个 LED 灯循环点亮,每个灯亮 50ms,即一次循环需要 400ms。
- 当 8 个 LED 灯全部点亮后,定时器 0 中断结束,回到 while(1) 循环体,继续执行 if 语句体。
- 如果外部中断 0 触发,进入外部中断 0 中断服务函数 int0()。
- 在 int0() 函数中,8 个 LED 灯闪烁,每个灯亮 100ms,即一次循环需要 1600ms。
- 当 8 个 LED 灯全部闪烁后,外部中断 0 中断结束,flag 的值变为 1,回到 while(1) 循环体,不再执行 if 语句体。
阅读全文