写一篇单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接有一只 按钮开关K1。在外部中断1输入引脚(P3.3)接有一只按钮开关K2。要求K1和 K2都夫按下时,P1口的8只LED呈流水灯显示,仅K1(P3.2)按下再松开时,上下各4只LED交替闪烁10次,然后再回到流水灯显示。如果按下再松开K2(P3.3)时,P1口的8只LED全部闪烁10次,然后再回到流水灯显示的程序
时间: 2023-12-17 11:03:00 浏览: 212
这是一道典型的单片机应用题,需要使用中断和定时器等知识。下面是一个简单的实现过程。
首先,需要定义一些常量和变量:
```c
#include <reg52.h>
#define LED_COUNT 8 // LED 数量
#define LED_DELAY 200 // LED 闪烁延时
#define LED_STEP 4 // LED 流水灯步进值
#define LED_MAX_STEP 8 // LED 流水灯最大步进值
sbit K1 = P3 ^ 2; // K1 按钮开关
sbit K2 = P3 ^ 3; // K2 按钮开关
unsigned char LED_STATE = 0; // LED 当前状态
unsigned char LED_STEP_COUNT = 0; // LED 流水灯计数器
unsigned char LED_BLINK_COUNT = 0; // LED 闪烁计数器
unsigned char LED_BLINK_TIMES = 0; // LED 闪烁次数
```
其中,LED_STATE 表示 LED 当前状态,LED_STEP_COUNT 表示 LED 流水灯计数器,LED_BLINK_COUNT 表示 LED 闪烁计数器,LED_BLINK_TIMES 表示 LED 闪烁次数。
接下来,需要初始化中断和定时器:
```c
void init() {
// 外部中断0和1,下降沿触发
IT0 = 1;
IT1 = 1;
EX0 = 1;
EX1 = 1;
EA = 1;
// 定时器0,1ms中断一次
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x67;
ET0 = 1;
TR0 = 1;
}
```
在中断处理函数中,需要根据按钮开关的状态来改变 LED 的显示状态:
```c
void EX0_ISR() interrupt 0 {
if (K1 == 0 && K2 == 0) {
// K1 和 K2 同时按下,显示流水灯
LED_STATE = 1;
LED_STEP_COUNT = 0;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 0;
} else if (K1 == 0 && K2 == 1) {
// K1 按下,上下各4只LED交替闪烁10次
LED_STATE = 2;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 10;
} else if (K1 == 1 && K2 == 0) {
// K2 按下,所有LED闪烁10次
LED_STATE = 3;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 10;
} else {
// K1 和 K2 都没按下,显示流水灯
LED_STATE = 1;
LED_STEP_COUNT = 0;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 0;
}
}
void EX1_ISR() interrupt 2 {
if (K1 == 0 && K2 == 0) {
// K1 和 K2 同时按下,显示流水灯
LED_STATE = 1;
LED_STEP_COUNT = 0;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 0;
} else if (K1 == 0 && K2 == 1) {
// K1 按下,上下各4只LED交替闪烁10次
LED_STATE = 2;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 10;
} else if (K1 == 1 && K2 == 0) {
// K2 按下,所有LED闪烁10次
LED_STATE = 3;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 10;
} else {
// K1 和 K2 都没按下,显示流水灯
LED_STATE = 1;
LED_STEP_COUNT = 0;
LED_BLINK_COUNT = 0;
LED_BLINK_TIMES = 0;
}
}
```
在定时器中断处理函数中,需要根据 LED 的状态来改变 LED 的显示效果:
```c
void T0_ISR() interrupt 1 {
static unsigned char led_index = 0;
TH0 = 0xFC;
TL0 = 0x67;
switch (LED_STATE) {
case 1: // 流水灯
P1 = ~(1 << led_index);
led_index = (led_index + LED_STEP) % LED_COUNT;
LED_STEP_COUNT++;
if (LED_STEP_COUNT >= LED_MAX_STEP) {
LED_STEP_COUNT = 0;
}
break;
case 2: // 上下各4只LED交替闪烁
P1 = ~(0xAA >> (led_index % 2));
LED_BLINK_COUNT++;
if (LED_BLINK_COUNT >= LED_DELAY) {
led_index++;
LED_BLINK_COUNT = 0;
}
if (led_index >= LED_COUNT) {
led_index = 0;
LED_BLINK_TIMES--;
}
if (LED_BLINK_TIMES == 0) {
LED_STATE = 1;
P1 = 0xFF;
}
break;
case 3: // 所有LED闪烁
P1 = 0x00;
LED_BLINK_COUNT++;
if (LED_BLINK_COUNT >= LED_DELAY) {
P1 = 0xFF;
LED_BLINK_COUNT = 0;
}
led_index++;
if (led_index >= LED_COUNT) {
led_index = 0;
LED_BLINK_TIMES--;
}
if (LED_BLINK_TIMES == 0) {
LED_STATE = 1;
P1 = 0xFF;
}
break;
}
}
```
最后,在主函数中调用初始化函数即可:
```c
void main() {
init();
while (1);
}
```
这样,就完成了一个简单的单片机应用。需要注意的是,这只是一个示例代码,实际应用中还需要考虑一些细节问题,如消抖、按键状态判断等。
阅读全文