24小时切换简易时钟-51单片机

24小时切换简易时钟

简介

1、本设计主要介绍用单片机内部的定时/计数器来实现电子时钟的方法,本设计由单片机STC89C51单片机和LED数码管为核心,辅以必要的电路,构成了一个单片机电子时钟。
2、本设计拟实现的性能指标如下:
(1)键盘用于校正、调节数码管上显示的时间。
(2)单片机通过输出各种电脉冲信号开驱动控制各部分正常工作。
(3)单片机发送的信号经过显示电路通过译码最终在数码管上显示出来。
(4)按键还可以切换12小时制和24小时制,并有指示灯。
STC89C51单片机
STC89C51是一种低功耗、高性能CMOS8位微控制器,具有 4K 在系统可编程Flash 存储器。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C51为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。 具有以下标准功能: 4k字节Flash,512字节RAM, 32 位I/O 口线,看门狗定时器,内置4KB EEPROM,MAX810复位电路,三个16 位 定时器/计数器,一个6向量2级中断结构,全双工串行口。
STC89C51单片机引脚图
STC89C51单片机引脚图
(一)STC89C51主要功能、性能参数如下:
(1)内置标准51内核,机器周期:增强型为6时钟,普通型为12时钟;
(2)工作频率范围:040MHZ,相当于普通8051的080MHZ;
(3)STC89C51RC对应Flash空间:4KB;
(4)内部存储器(RAM):512B;
(5)定时器\计数器:3个16位;
(6)通用异步通信口(UART)1个;
(7)中断源:8个;
(8)有ISP(在系统可编程)\IAP(在应用可编程),无需专用编程器\仿真器;
(9)通用I\O口:32\36个;
(10)工作电压:3.8~5.5V;
(11)外形封装:40脚PDIP、44脚PLCC和PQFP等。
(二)STC89C51单片机的引脚说明:
(二)STC89C51单片机的引脚说明:
VCC:供电电压。
GND:接地。
P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中断0)
P3.3 /INT1(外部中断1)
P3.4 T0(记时器0外部输入)
P3.5 T1(记时器1外部输入)
P3.6 /WR(外部数据存储器写选通)
P3.7 /RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
I/O口作为输入口时有两种工作方式,即所谓的读端口与读引脚。读端口时实际上并不从外部读入数据,而是把端口锁存器的内容读入到内部总线,经过某种运算或变换后再写回到端口锁存器。只有读端口时才真正地把外部的数据读入到内部总线。上面图中的两个三角形表示的就是输入缓冲器CPU将根据不同的指令分别发出读端口或读引脚信号以完成不同的操作。这是由硬件自动完成的,不需要我们操心,1然后再实行读引脚操作,否则就可能读入出错,为什么看上面的图,如果不对端口置1端口锁存器原来的状态有可能为0Q端为0Q^为1加到场效应管栅极的信号为1,该场效应管就导通对地呈现低阻抗,此时即使引脚上输入的信号为1,也会因端口的低阻抗而使信号变低使得外加的1信号读入后不一定是1。若先执行置1操作,则可以使场效应管截止引脚信号直接加到三态缓冲器中实现正确的读入,由于在输入操作时还必须附加一个准备动作,所以这类I/O口被称为准双向口。89C51的P0/P1/P2/P3口作为输入时都是准双向口。
RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。
/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
XTAL2:来自反向振荡器的输出。

源文件下载:
原文件(可点击跳转)

原理图:
在这里插入图片描述
代码:

/************************************************************
作品名字:简易时钟(12小时和24小时可转换)
功能:六位数码管显示时分秒
二十四小时制和十二小时制可切换
十二小时制红灯亮,二十四小时制红灯灭
当时间在凌晨0点~中午12点之间时,黄灯亮,此时按切换按键数码管的示数不会变化
制作说明:P0接数码管段选,P2低6位接数码管位   
	
**************************************************************/
#include<reg52.h>		   //包含库文件
#define uc unsigned char
#define ui unsigned int		//宏定义,就是定义ui代替unsigned int,方便下面程序调用
sbit LED=P3^2;//定义LED
sbit key0=P3^3;//定义小时切换按键
sbit key1=P3^4;//定义调小时按键
sbit key2=P3^5;//定义调分钟按键
sbit key3=P3^6;//定义秒清零按键
sbit wan=P3^7;//上下午指示灯
uc min,hour,sec,num;//分钟,小时,秒,定时器计时变量
bit bdata zhi;//小时制标志位
uc code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};/*0,1,2,3,4,5,6,7,8,9,.*///共阴极编码

void delay(ui x)//延时函数,大约延时1ms
{
	ui i,j;
	for(i=0;i<x;i++)
	for(j=0;j<121;j++);	 //执行121次大约延时1ms
}
void display()//扫描显示函数,高位到低位
{
	P0=tab[hour/10];//小时数据是一个两位数,除以10得到的商是十位数,然后调用数组内的对应数字的编码赋值给P0口,显示对应数字
	P2=0xdf;//11011111	选择对应位
	delay(1);//延时
	P2=0xff;//关闭位选

	P0=(tab[hour%10])|0x80;//给第二位后加“点(段选接线最高位是小数点,所以就按位或0x80就是在最高位赋值1,就是显示小数点)
	P2=0xef;//11101111
	delay(1);
	P2=0xff;

	P0=tab[min/10];
	P2=0xf7;//11110111
	delay(1);
	P2=0xff;

	P0=(tab[min%10])|0x80;//给第四位后加“点”
	P2=0xfb;//11111011
	delay(1);
	P2=0xff;

	P0=tab[sec/10];
	P2=0xfd;//11111101
	delay(1);
	P2=0xff;

	P0=tab[sec%10];		//秒数据是一个两位数,%是取余运算,就是除以10的余数,得到个位数字
	P2=0xfe;//11111110
	delay(1);
	P2=0xff;
}

void keyscan()//键盘扫描,开关接地
{
	if(key0==0)			  //检测到按键按下
	{
		delay(5);		  //延时去抖
		if(key0==0)		  //再次判断按键是否按下
		{
			LED=~LED;	  //LED取反操作
			zhi=~zhi;	  //小时制取反
			if((hour>=12)&&(zhi==0))//小时大于等于12点时,且小时制等于0,也就是12小时制
			{	
				hour=hour-12;	//将当前小时数据减12赋值给hour
			}
			if((zhi==1)&&(wan==1))//小时制为24小时。是下午时
			{
				hour=hour+12;//将小时数据加12赋值给hour
			}			 		 
		}
		while(!key0) display();//判断是否松开,按键不送开时,key0是0,取反就是1,一直成立,就一直执行后面的显示函数,按键松开就跳出
	}
	if(key1==0)		//加小时按键按下
	{
		delay(5);
		if((key1==0)&&(zhi==0))	 //12小时制
		{
			hour++;				 //小时加
			if(hour==12)		 //加到12点
			{
				hour=0;			 //小时清零
				wan=~wan;		 //切换上下午
			}
		}
		if((key1==0)&&(zhi==1))	 //24小时制
		{
			hour++;				 //小时加
			if(hour==24)		 //加到24点
			hour=0;				 //清零
		}
		while(!key1) display();//判断是否松开
	}
	if(key2==0)					//分加按键按下
	{
		delay(5);
		if(key2==0)
		{
			min++;				 //分加
			if(min==60)			 //加到60
			min=0;				 //分清零
		}
		while(!key2) display();//判断是否松开
	}
	if(key3==0)//秒清零按键
	{
		delay(5);
		if(key3==0)
		{sec=0;}		//秒清零
		while(!key3) display();//判断是否松开
	}
}

void init()				  //系统初始化函数
{
	sec=0;//一通电,显示12:30:00
	min=30;
	hour=12;
	LED=1;	  //led点亮
	zhi=1;	  //默认是24小时制
	wan=1;	  //下午
	TMOD=0x01;//设置定时器0工作方式1
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;	//定时器初值50ms
	EA=1;				   //打开中断总开关
	ET0=1;				   //打开中断允许开关
	TR0=1;				   //打开定时开关
}

void shizhi()			   //小时制函数
{
	if(hour>=12)		   //小时能加到大于12点,说明是24小时制
	wan=1;				   //却换到下午
	if((hour<12)&&(zhi==1))//小时小于12并且是24小时制
	wan=0;				   //切换到上午
}

void main()//主函数
{
	init();			//调用初始化函数
	while(1)		 //进入循环
	{
		display();	//调用显示函数
		keyscan();//扫描是否有键按下
		shizhi();	//小时制函数
	}
}
void time0() interrupt 1	//定时器0工作函数
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;	 //进入中断后重新赋初值50ms
	num++;				//变量加
	if(num==20)			//加20次就是1s
	{
		num=0;		   //变量清零
		sec++;		   //秒变量加
		if(sec==60)	   //秒加到60
		{
			sec=0;	   //秒清零
			min++;	   //分加
			if(min==60)//分加到60
			{
				min=0; //分清零
				hour++;//小时加
				if((hour==12)&&(zhi==0)) //小时加到12,小时制为12
				{
					wan=~wan;	//切换上下午
					hour=0;		//小时清零
				}
				if((hour==24)&&(zhi==1)) //小时加到24,小时制为24小时制
				{
					hour=0;			  //小时清零
				}
			}
		}
	}
}

  • 9
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个小小白 - 呀吼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值