欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

程序员文章站 2022-07-12 11:19:01
...

功能要求:

1.利用定时器中断实现时钟功能,格式:时-分-秒。
2.实现时钟显示和闹钟设置两个功能的切换。
3.闹钟设置,且限定字符格式(如时针不得超过24等)。
4.时钟到达预设值时,闹铃正常响起,且用按键关闭。

思维导图:

1.主函数
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
2.时钟显示
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
3.闹钟设置

51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
4.闹铃
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
**

Proteus电路图

晶振频率12mhz
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

代码

**
头文件

#ifndef colock_h
#define colock_h

#include <reg52.h>

#define LedD P0                                              //段选
#define LedC P2                                              //位选

unsigned char s=57,m=59,h=23;									//时、分、秒初始值

unsigned char	j=0;														//闪烁位的延时参数

unsigned char flag=0;												//闪烁位
	
unsigned char	key1=0,key2=0,key3=0;					//三个中断按键
	
unsigned char	f1=0,f2=1,f3=0;								//f1:时钟到达闹钟预设值 标志位
																						//f2:闹钟关闭按键 标志位
																						//f3:闹钟状态 标志位

unsigned int i=0;														//计数器延时参数

sbit cl=P3^0; 							//闹钟功能切换提示
sbit bz=P1^0;								//闹铃输出口
																																
																	//共阴极数码管
																																	
unsigned char num1[] = {1,0,10,0,0,10,0,0};         	 						/* 时钟待显示字符对应key值*/  

unsigned char num2[] = {0,0,10,0,0,10,1,0};												/* 闹钟待显示字符对应key值*/ 

code unsigned char wx[] = {0xfe,0xfd,0xfb,0xf7,            			/* 位选编码 字符对应value值	*/           
                               0xef,0xdf,0xbf,0x7f};   

code unsigned char dx[] = {0x3f,0x06,0x5b,0x4f,0x66,      			 /* 0-9数字,-的编码 */
                               0x6d,0x7d,0x07,0x7f,0x6f,0x40};

void init();																				//初始化
void delay(unsigned char);													//延时
void display();																			//时针显示
void count();																				//时针计数(计时)
void transform();																		//将时分秒的个位十位分离
void twinkle(unsigned char);												//闹钟显示界面 控制某一位闪烁 
void int0();																				//外部中断0
void int1();																				//外部中断1
void it0();																					//定时器0
void compare();															 				//闹钟预设值与时钟值比较			
void ring();																				//闹铃
												
#endif

c文件

#include "colock.h"

void main(void)
{
	init();
	while(1)
	{
		compare();
		if(key1==1)
		{
			cl=1;
			twinkle(flag);							//已切换到闹钟功能 提示
		}
		else													//切换到时钟显示
		{
			cl=0;
			display();
		}
	}
}



void init(void)                /*初始化*/
{
	LedD = 0x00;                    /* 段码置0 */
	LedC = 0xff;                    /* 位选置1 */ 
	
	EA=1;													//总中断
	ET1=1;										//开启定时器中断1
	ET0=1;										//定时器0

	TR1=1;										//开启定时器1
	TMOD=0x20;								//定时器1,工作方式2,八位自动重装载
	TH1=156;
	TL1=156;									//0.1ms

	IT0=1;										//下降沿有效
	IT1=1;
	EX0=1;										//外部中断0、1
	EX1=1;
	
	ET0=1;												//开启定时器中断
	TMOD=0x06;										//八位自动重装载计数器0 扩展为中断
	TR0=1;												//开启定时器0
	TH0=0xff;
	TL0=0xff;
	
	bz=0;											//闹铃关闭
}

void display()												//字符显示
{
	unsigned char i;
	for(i=0; i<8; i++)
	{
		LedC = wx[i];            			 /* 选通某一位,例如i=0,即选通第0位 */
		LedD = dx[num1[i]];            /* 通过码表数组将第i位要显示的数字转换成数码管能识别的编码 */
		delay(20);                     /* 微量延时,用于显示保持 */
		LedD=0x00;										 //消隐
	}
}

void delay(unsigned char t)							//延时
{
	unsigned char i,j;
	for(i=0; i<20; i++)
		for(j=0; j<t; j++);

}

void transform()														//数位转换
{
	h%=24;
	num1[0]=h/10;				//十位
	num1[1]=h%10;				//个位
	num1[3]=m/10;
	num1[4]=m%10;
	num1[6]=s/10;
	num1[7]=s%10;
}

void count() interrupt 3								//计时
{
	i++;
	if(i==100)
	{
		s++;
		if(s==60)
		{
			s=0;
			m++;
		}
		if(m==60)
		{
			m=0;
			h++;
		}
		transform();
		i%=100;
		if(f1&&f2)														//启动闹铃
			ring();
		else
			bz=0;
	}
}

									//闹钟界面相关程序

void twinkle(unsigned char t)				//某一位闪烁
{	
	unsigned char i;
	j%=50;
	for(i=0;i<8;i++)
	{
		if((i==t)&&(j<25))
			continue;
		else
		{
			delay(20);
			P2=wx[i];
			P0=dx[num2[i]];
		}
	}
		j++;
}

void int0() interrupt 0							//进入闹钟界面
{
	key1++;
	key1%=2;
}

void int1() interrupt 2							//移动调整位(闪烁位)   关闭闹铃
{
	flag++;
	if(flag==2||flag==5)							//跳过分隔符
		flag++;
	flag%=8;
	
	if(f1)														//关闭闹铃标志符f2的赋值
	{
		f2=0;
		f1=0;
	}
	else
		f2=1;
}

void it0() interrupt 1							//闪烁位数字加一
{
	if(flag==0&&num2[flag]==2)				//限制 时针高位不得破2
	{
		num2[flag]=0;
		return;
	}
	else if(flag==1&&num2[flag]==3&&num2[0]==2)					//限制 时针为2时,低位不得破4
	{
		num2[flag]=0;
		return;
	}
	else if((flag==3||flag==6)&&num2[flag]==5)				//分针、秒针高位不得破6
	{
		num2[flag]=0;
		return;
	}
		num2[flag]++;
		num2[flag]%=10;														//防止任意数字破9
}

void compare()																		//闹钟,比较是否到达预定时间
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		if(num1[i]==num2[i])
			f1=1;
		else
		{
			if(f3)
				return;
			else
			{
				f1=0;
				return;
			}
		}
	}
	f3=1;
}

void ring()																		//闹铃
{
	bz=~bz;
}


部分说明:
num1[] 储存时钟数值
num2[] 储存闹钟数值
关闭闹铃的按键与更换闪烁位复用了
闹铃的闪烁与时钟的定时器复用了
(待后续补充)

效果展示

1.时钟显示
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

2.闹钟设置
切换
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

换位51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
数值+1
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

3.闹钟开启与关闭
利用中断持续闪烁
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)
关闭
51单片机 时钟显示、设置闹钟功能的实现 (附详细算法思路、proteus电路图)

**
1.闹铃的蜂鸣器我使用了led灯代替,便于显示
2.proteus里的延时似乎是受电脑性能影响,故代码中的延时参数 i 等全局变量并非理论值,应个性化调整
3.待后续补充…

ps:欢迎评论区咨询讨论