menu Secto白帽博客-专注于技术研究
单片机之Protues模拟仿真-按键控制LED小灯和数码管99倒计时
326 浏览 | 2020-03-23 | 分类:硬件设计 | 标签:单片机,protues仿真,数码管,LED小灯,按键

前言

今天抽时间用protues软件仿真了一个按键控制LED小灯和数码管99倒计时的单片机小程序,就拿来和大家分享一下吧。
本次展示的仿真是通过51单片机的C语言进行程序的编写,相信学习单片机的小伙伴对51单片机和C语言的基础知识应该是有的,在此我就不详细介绍单片机的基础知识。希望大家能够理解。

原理

通过P0.0到P0.3四个按键控制LED小灯的亮灭和数码管的99倒计时。现象功能为:

  1. 程序运行后按下K1按键第一次八个LED小灯同时亮起,按下K1按键第二次八个LED小灯中奇数小灯亮偶数小灯灭,按下K1按键第三次八个LED小灯中偶数数小灯亮奇数小灯灭,当按下K1按键第四次时八个LED小灯全灭。
  2. 当按下K2按键时数码管开始倒计时(还可以根据控制LED小灯一样控制数码管暂停和清零,本次实验就不展示了,下次有时间再给大家补充一下)

电路图

我们通过protues进行电路仿真,首先打开protues软件并进行创建项目,然后进行设计电路。在设计电路图前我们需要先把电路中所需要用到的原件进行找到。寻找原件我们可以在左边工具栏中选择第二个,然后点击“P”符号的蓝色方块,可以进入查找原件的对话框中。如下图所示。

通过输入关键字依次查找到如下原件

查找到所有原件后我们就可以来绘制电路图了,整体电路图如下所示

这个电路设计是比较简单的一种,程序设计也是要根据电路设计来进行编写的,如果有朋友可以尝试的话可以设计出更好的电路出来,也可以根据实际51单片机的开发板来设计电路,当然你设计的电路不同,程序也就有点不同了,但具体思路还是大致相同的。

代码设计

#include <reg51.h>
#include <stdio.h>

//函数定义
void jishu();   //数码管计数
void initeConfig();   //初始化配置
void changeLED();    //LED小灯改变
void startDaojishu();   //数码管倒计时开始计数

//按键IO定义
sbit K0=P0^0;
sbit K1=P0^1;
sbit K2=P0^2;
sbit K3=P0^3;

//数码管显示控制io引脚定义
sbit ADDR0=P3^0;
sbit ADDR1=P3^1;
sbit ADDR2=P3^2;
sbit ADDR3=P3^3;
sbit ADDR4=P3^4;
sbit ADDR5=P3^5;

unsigned char KeySta[4] = {1,1,1,1}; //4个按键状态定义
unsigned char backup[4] = {1,1,1,1}; //4个按键状态缓冲区定义
unsigned char flags=0;    //数码管一秒计时状态标志
unsigned int cnt1=0;   //一秒计时变量
unsigned char i=0;     //for循环控制变量
unsigned char start=0;  //开始倒计时按键按下标志
unsigned char cnt = 0;    //LED小灯状态控制变量
unsigned long sec=100;   //99倒计时数值变量
unsigned char code LedChar[]={  //数码管0到F显示的十六进制值的初始化
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
    0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
unsigned char LedBuff[6]={    //六个数码管的缓存数组
    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
};

void main(void){  
    initeConfig();    //环境初始化
    while (1){
        if(start==1){    //当start=1时开始倒计时
            startDaojishu();
        }
        for(i=0;i<4;i++){    //循环判断四个按键是否被按下
            if(KeySta[i] != backup[i]){
                if(backup[i] == 0){
                    if(i==1){    //如果K1按键按下时改变LED小灯的状态
                    changeLED();
                    }
                    else if(i==2){    //如果K1按键按下时
                    start=1;    //开始倒计时按键按下标志赋值为1  表示开始倒计时
                    }
                }
            backup[i] = KeySta[i];
            }
        }
    }
}

void initeConfig(){
   K1=1;
   EA = 1;
   TMOD = 0x01;
   TH0=0xFC;
   TL0=0x67;
   ET0 = 1;
   TR0 = 1;
}

void changeLED(){
   cnt++;
   if(cnt==1){   //k1按键按下第一次小灯全亮
      P2=0x00;
   }
   else if(cnt==2){    //k1按键按下第二次奇数小灯全亮
      P2=0xAA;
   }
   else if(cnt==3){    //k1按键按下第三次偶数小灯全亮
      P2=~P2;
   }
   else if(cnt==4){    //k1按键按下第四次小灯全灭
      P2=0xFF;
      cnt=0;
   }
}

void jishu(){
   cnt1++;
   if(cnt1>=1000){    //时钟中断时间为1ms  所以当在第一千次中断时为一秒,数码管倒计时减1
       cnt1=0;
       flags=1;
   }
   P1=0xFF;
   //这是通过人眼的视觉暂停效应进行同时显示多个数码管,但实际上时每1ms只显示一个数码管的
   if(i==0){
      ADDR5=1; ADDR4=0; ADDR3=0;ADDR2=0; ADDR1=0; ADDR0=0; i++; P1=LedBuff[0];   //给第六个数码管io引脚实时赋值  
   }
   else if(i==1){
      ADDR5=0; ADDR4=1; ADDR3=0;ADDR2=0; ADDR1=0; ADDR0=0; i=0; P1=LedBuff[1];   //给第五个数码管io引脚实时赋值  
   }
}
 
void startDaojishu(){
   if(flags==1){    //当计时1s到了时,数码管倒计时减1
      flags=0;
      sec--;
      //减1后分别给每个数码管的显示值赋值,比如sec=98时,数码管个位sec%10=8,十位sec/10%10=9
      //然后在让数码管缓存的0号元素和1号元素分别存储数码管显示位是8和9的十六进制值,让他们在jishu函数中进行赋值到io引脚上从而让数码管显示相应的数字
      LedBuff[0]=LedChar[sec%10];  
      LedBuff[1]=LedChar[sec/10%10];
      if(sec==0)
     sec=99;
   }
}
 
//T0计时器中断函数,中断时间到了就判断四个按键的状态,并进行按键消抖操作。
void InterruptTimer0() interrupt 1{
    static unsigned char keybuf[] = {0xFF,0xFF,0xFF,0xFF};
    char i=0;
    TH0=0xFC;
    TL0=0x67;
    keybuf[0] = (keybuf[0] << 1) | K0;     
    keybuf[1] = (keybuf[1] << 1) | K1;
    keybuf[2] = (keybuf[2] << 1) | K2;
    keybuf[3] = (keybuf[3] << 1) | K3;
    for(i=0;i<4;i++){
        if(keybuf[i] == 0x00){
            KeySta[i] = 0;
        }
        else if(keybuf[i] != 0x00){
            KeySta[i] = 1;
        }
    }
    if(start==1){
        jishu();
    }
}

By:star147
Time:2020/3/23

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

发表评论

email
web

全部评论 (暂无评论)

info 还没有任何评论,你来说两句呐!