当前位置:   article > 正文

C51单片机的电子时钟(数码管显示+独立按键模块修改及暂停时间)_单片机时钟按键修改时间

单片机时钟按键修改时间

C51单片机的电子时钟(数码管显示+按键修改时间)

效果预览

IMG_1120

相关的开发板原理图解析

在这里插入图片描述在这里插入图片描述在这里插入图片描述通过查看这三个原理图我们可以得知控制K1、K2、K3及K4是通过P31、P30、P32及P33来实现的,控制8个数码管是P22、P23及P24来实现,
控制发光二极管则由P00-P07来实现。

正式代码

代码分为三部分分别为main.c、key.h、key.c

main.c代码部分

#include<reg52.h>
#include"key.h"
//这里定义了一个10个元素的只读数组zxCode,用于存放0~9的数码管显示码。
code unsigned char zxCode[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//这里定义了一个10个元素的只读数组_zxCode,用于存放0~9的数码管带点显示码。
code unsigned char _zxCode[10]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF};
//这里定义了一个长度为8的数组DsBuf,用于存放需要显示的数码管数据,数组的每一个元素代表数码管的一个位置。
unsigned char DsBuf[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/*控制数码管显示的函数。在该代码中,使用P0口来控制8个数码管的段选信号,同时使用P2口的3个引脚(即A、B、C)来控制数码管的位选信号。通过display函数,可以将DsBuf数组中存储的数值依次显示在8个数码管上,实现时分秒的动态显示。该函数中使用了一个静态变量n来循环控制位选信号A、B、C的输出,从而实现了数码管显示的循环刷新。*/
void display(){
	static unsigned char n=0;
	zixin=0x00;
	if(n&0x01)  A=1;
	else 				A=0;
	if(n&0x02)  _B=1;
	else 				_B=0;	
	if(n&0x04)  C=1;
	else 				C=0;	
	zixin=DsBuf[n];
	n++;
	n%=8;
}
/*filldisbuf函数的作用是将传入的时分秒的值按照一定的格式进行转换,并将转换后的结果存储在DsBuf数组中,以便后续的数码管显示*/
void filldisbuf(unsigned int n,unsigned int m,unsigned int h){
    DsBuf[0]=zxCode[n%10];
    n /=10;
    DsBuf[1]=zxCode[n%10];
    
    DsBuf[2]=_zxCode[m%10];
    m /=10;
    DsBuf[3]=zxCode[m%10];
    
    DsBuf[4]=_zxCode[h%10];
    h /=10;
    DsBuf[5]=zxCode[h%10];
}

//这里定义了一个延时函数,用于延时一段时间,用于稳定数码管的显示效果。
void delay(){
    char i;
    for(i=-100;i<100;i++);
}

//负责时间的走动与暂停
void start(unsigned int s,unsigned int m,unsigned int h){
	unsigned char i=0;
	unsigned char paused = 0;//一个标志,用来区分时间是在走动的还是停止的
	filldisbuf(s,m,h);
	while(1){
		if (!paused){
			display();
			delay();
			i++;
			if(i>=200){
				i=0;
				s = (++s) % 60;
				if (s == 0) {
					m = (++m) % 60;
					if (m == 0) {
						h = (++h) % 24;
					}
				}
				filldisbuf(s, m, h);
			}
		}
		else{
			display();
			delay();
			i++;
			if(i>=200){
				i=0;
				filldisbuf(s, m, h);}
		}
		//和main函数相同的功能,不同的是K4按键负责改变paused这个标志的值
		scankey();
		if (k1_down) {
			k1_down = 0;
			h = (++h) % 24;
		}
		if (k2_down) {
			k2_down = 0;
			m = (++m) % 60;
		}
		if (k3_down) {
			k3_down = 0;
			s = (++s) % 60;
		}
		if (k4_down) {
			k4_down = 0;
			paused = !paused;
		}
	}  
}

int main(){
    unsigned int s=0;//表示秒
    unsigned int m=0;//表示分
    unsigned int h=0;//表示时
    unsigned char i=0;
    while(1){
        scankey();//用来扫描按键的状态
        if(k1_down){//按下K1按键,数码管负责显示时的数值加1
            k1_down=0;
            h = (++h) % 24;
        }
        if(k2_down){//按下K2按键,数码管负责显示分的数值加1
            k2_down=0;
            
            m = (++m) % 60;
        }
        if(k3_down){
            k3_down=0;//按下K3按键,数码管负责显示秒的数值加1
            s = (++s) % 60;
        }
        if(k4_down){//按下K4按键,时间开始走动,再按下K4按键,时间停止走动
            k4_down=0;
            start(s,m,h);
        }
        delay();//主要功能时稳定的显示时间
        display();
        i++;
        if(i>=200){
            i=0;
            filldisbuf(s, m, h);
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

key.h部分

#ifndef __KEY_H_
#define __KEY_H_

#include<reg52.h>
这里定义了4个端口位,分别命名为K1、K2、K3及K4,分别代表P3口的1、0、2、3位。
sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;
//这里定义了3个端口位,分别命名为A、_B、C,分别代表P2口的2、3、4位。
sbit A=P2^2;
sbit _B=P2^3;
sbit C=P2^4;
//这里定义了一个宏定义,P0代表的是单片机的一个8位数据总线口
#define zixin P0


extern bit k1_down,k2_down,k3_down,k4_down;
void scankey(void);

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

key.c部分

scankey()函数的主要代码,通过软件入手提高系统的可靠性,防止外界干扰或用户按下按钮时的轻微抖动可能引起系统的误判。
它的主要策略如下:1

  1. 在固定时间间接扫描按键引脚状态并记录
  2. 若最近4次扫描结果出现1101或者0010,则认为中间出现的0/1为抖动或干扰,修正为1111和0000
  3. 若最近8次扫描结果为1111 0000,则可判断按键有被“按下”的动作发生;若结果为0000 1111,则可判断按键有被“放开”的动作发生。
#include"key.h"
bit k1_down=0,k2_down=0,k3_down=0,k4_down=0;
bit k1_up=0,k2_up=0,k3_up=0,k4_up=0;

void scankey(){
	static unsigned char filter1=0xFF,filter2=0xFF,filter3=0xFF,filter4=0xFF;
	
	filter1<<=1;
	filter2<<=1;
	filter3<<=1;
	filter4<<=1;
	
	if(K1)filter1|=0x01;
	if(K2)filter2|=0x01;
	if(K3)filter3|=0x01;
	if(K4)filter4|=0x01;
	
	if((filter1&0x0F)==0x0D)filter1|=0x02;
	if((filter2&0x0F)==0x0D)filter2|=0x02;
	if((filter3&0x0F)==0x0D)filter3|=0x02;
	if((filter4&0x0F)==0x0D)filter4|=0x02;
	
	if((filter1&0x0F)==0x02)filter1&=0x0D;
	if((filter2&0x0F)==0x02)filter2&=0x0D;
	if((filter3&0x0F)==0x02)filter3&=0x0D;
	if((filter4&0x0F)==0x02)filter4&=0x0D;
	
	if(filter1==0xF0)k1_down=1;
	if(filter2==0xF0)k2_down=1;
	if(filter3==0xF0)k3_down=1;
	if(filter4==0xF0)k4_down=1;
	
	if(filter1==0x0F)k1_up=1;
	if(filter2==0x0F)k2_up=1;
	if(filter3==0x0F)k3_up=1;
	if(filter4==0x0F)k4_up=1;
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

  1. 杜隆胤 面向系统集成的C51单片机教程 P54 ↩︎

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/408656
推荐阅读
相关标签
  

闽ICP备14008679号