目录
本次设计使用4个按键,当KEY1按下时,P0口所接的发光二极管(D1~D8)以100ms的时间间隔自下至上循环点亮3圈,当KEY2按下时,以200ms的时间间隔自上至下循环点亮3圈;当KEY3按下时,LED自两边至中间循环点亮,循环次数为3圈,时间间隔为1000ms;当KEY4按下时,LED自中间至两边循环点亮,循环次数为3圈,时间间隔为1000ms。平时LED的状态为全部熄灭。
1、芯片74HC245功能、引脚含义
74HC245功能是做缓冲器,其OE管脚控制输出使能,低电平有效,DIR 管脚控制数据传输方向,若DIR为高电平数据传输方向是为A->B ,否则为B ->A,A0->A7和B0->B7管脚均用于数据的输入/输出,VCC和GND分别为芯片的电源端和接地端。
2、芯片74HC138功能、引脚含义
74HC138功能为将3位二进制,译码成8种输出状态,并且一共有8个输出I/O,其A0->A2为数据输入管脚,Y0->Y7为数据输出管脚,E1、E2、E控制芯片使能,只有当E1=0,E2=0,E3=1时,芯片才能被使能,否则芯片不会有任何有效输出,VCC和GND分别为芯片的电源端和接地端。
3、P0口作为通用I/O口时需注意
由于P0口的内部上拉电阻较大属于“弱上拉”,因此P0口输出高电平电流很小,而输出低电平时,下拉MOS管导通,灌电流较大,负载能力强。因此在设计中,一般采用低电平驱动方式。
4、点亮发光二极管硬件满足条件
点亮发光二极管需要让三极管导通,即Q3为低电平,即二极管的阴极为低电平。

- /*******************************************************************************
- * 函 数 名 : main
- * 函数功能 : 按键流水灯
- * 创作者 : 薄情书生
- * 创作时间 : 2022.9.15
- *******************************************************************************/
-
- #include "reg52.h"
- #include "intrins.h"
-
- /*********类型定义*********/
- typedef unsigned char u8;
- typedef unsigned int u16;
-
- /*********按键定义*********/
- sbit KEY0 = P3^2;
- sbit KEY1 = P3^3;
- sbit KEY2 = P3^4;
- sbit KEY3 = P3^5;
-
- /*********毫秒延时*********/
- void delay_ms(u16 ms)
- {
- u16 x,y;
- for(x=ms;x>0;x--)
- for(y=114;y>0;y--);
- }
-
- /*************38译码器**************/
- void SelectHC138(unsigned char channel)
- {
- switch(channel)
- {
- case 0:
- P1 = (P1 & 0x1f)|0x00;break; //发光二极管(LEDS0)
- }
- }
-
- /*************LED由下至上**************/
- void Bottom_Up()
- {
- u8 i,j;
- for(j=0;j<3;j++)
- {
- for(i=0,P0 = 0xff;i<8;i++)
- {
- P0 = P0<<1;
- delay_ms(200);
- }
- }
- P0 = 0xff;
- }
-
- /*************LED由上至下**************/
- void Up_Bottom()
- {
- u8 i,j;
- for(j=0;j<3;j++)
- {
- for(i=0,P0 = 0xff;i<8;i++)
- {
- P0 = P0>>1;
- delay_ms(100);
- }
- }
- P0 = 0xff;
- }
-
- /*************两边至中间**************/
- void LED_sides()
- {
- u8 i,j,ri,lf;
- for(j=0;j<3;j++)
- {
- for(i=0,ri=0x7f,lf=0xfe;i<4;i++)
- {
- P0 = ri&lf;
- ri = _cror_(ri,1);
- lf = _crol_(lf,1);
- delay_ms(1000);
- }
- }
- P0 = 0xff;
- }
-
- /*************中间至两边**************/
- void LED_middle()
- {
- u8 i,j,ri,lf;
- for(j=0;j<3;j++)
- {
- for(i=0,ri=0xef,lf=0xf7;i<4;i++)
- {
- P0 = ri&lf;
- ri = _crol_(ri,1);
- lf = _cror_(lf,1);
- delay_ms(1000);
- }
- }
- P0=0xff;
- }
-
- /*******************主程序************************/
- void main()
- {
- SelectHC138(0);
- while(1)
- {
- if(KEY0==0)
- {
- delay_ms(10);
- if(KEY0==0)
- {
- Up_Bottom();
- }
- }
- if(KEY1==0)
- {
- delay_ms(10);
- if(KEY1==0)
- {
- Bottom_Up();
- }
- }
- if(KEY2==0)
- {
- delay_ms(10);
- if(KEY2==0)
- {
- LED_sides();
- }
-
- }
- if(KEY3==0)
- {
- delay_ms(10);
- if(KEY3==0)
- {
- LED_middle();
- }
- }
- }
- }
KEY1按下时,P0口所接的发光二极管(D1~D8)以100ms的时间间隔自下至上循环点亮3圈。

KEY2按下时,以200ms的时间间隔自上至下循环点亮3圈。

KEY3按下时,LED自两边至中间循环点亮,循环次数为3圈,时间间隔为1000ms。
当KEY4按下时,LED自中间至两边循环点亮,循环次数为3圈,时间间隔为1000ms。
平时LED的状态为全部熄灭。

修改程序,实现4个按键控制,自上至下、自下至上、发光二极管闪烁3次,时间间隔为500ms、发光二极管全部点亮3秒后熄灭、结束后恢复到所有LED熄灭的正常状态。请自行编写程序并调试。思考题参考程序将在设计二:51单片机外部中断实验给出。
本专栏为51单片机实战教程,旨在以练促学,帮助小伙伴快速入门51单片机,学习51单片机相应理论知识请自行学习。本次设计涉及的相关理论知识:51单片机IO口控制、独立按键的使用,请自行参考资料学习。
本次设计源程序及仿真源文件百度网盘链接:https://pan.baidu.com/s/17PtMjM5y-YSfdHlqnqAUnA 提取码:4ma5