基于51单片机电子时钟

2020-08-23 17:34发布

1 基于51单片机用LCD1602实现时-分的显示


2. 按键控制时-分的调整


3. 能实现整时报时的功能(蜂鸣器响)


4. 闹钟模式


5.按键切换模式(模式一:时-分显示,模式二:60秒倒计时) 一、设计思路:


主体:


通过外部中断0来控制mod值;mod=0,1.2,3分别对应时钟模式,调整模式,闹钟设置模式,一分钟倒计时模式。


细节:


mod0


通过定时计数器,每一秒增加变量秒(s),每60秒,增加1分(min)并且s置0,每60min,增加1小时h,当h>23,h=0;进行一天循环


mod1


按键控制增加min,h和s制0


mod2


另外设置变量min1,h1,当min=min1,h=h1时蜂鸣器响


mod3


设置变量daojishi=60, 通过定时计数器,每一秒daojishi减1,当daojishi<0时,蜂鸣器响


另外:


1.设置外部中断2,关闭蜂鸣器


2.时间发送一次只能发送一个位 程序:

#include

//K1后K3加分钟,K4加时间,K2加秒,K1进入闹钟设置,K2退出 
//K2关闭闹钟 
typedef unsigned int u16;	//对数据类型进行声明定义 
typedef unsigned char u8; 
#define data8b P1 sbit K1=P3^2; //外部中断0 
sbit K2=P3^3; //外部中断1 
sbit K3=P3^0; 
sbit K4=P3^1; 
sbit BUZ=P2^4; //蜂鸣器,0响 
sbit RW=P2^5; //4脚,数据(1)or命令(0) 
sbit RS=P2^6; //5脚,读(1)写(0) 
sbit E=P2^7; //6脚,使能信号 
u8 code dat1[]={0X30,0X31,0X32,0X33, 0X34,0X35,0X36,0X37, 0X38,0X39}; 

void delay(u16 i) //延时函数 
{ while(i--); } 


void open012() //打开中断0,1,定时器中断0 
{ TMOD|=0X01; //选择为定时器0模式,工作方式1 
ET0=1; //打开定时器0中断允许 
EA=1; //打开总中断 
TR0=1; //打开定时器	
EX0=1; //打开外部中断0 
IT0=1; //边沿触发方式 
EX1=1; //打开外部中断1 
IT1=1; //边沿触发 
} 

void wrm(u8 dat) //写入命令 
{ delay(1000); 
RS=0; 
RW=0; 
E=0; 
data8b=dat; 
E=1; 
delay(1000); 
E=0; } 

void wrd(u8 dat) //写入数据 
{ 
delay(1000); 
RS=1; 
RW=0; 
E=0; 
data8b=dat; 
E=1; 
delay(1000); 
E=0; 
} 

void zero() 
{ 
wrm(0X38); //八位数据,两行显示,5*7 
wrm(0X0c); //无光标,打开显示 
wrm(0X06); //光标右移,屏幕不移动 
wrm(0X01); //清屏 
wrm(0X80); //设置数据指针起点 
} 

u8 fg=0,sg=0,bfg=0,bsg=0; 
u16 i=0; 
u8 s=0; 
u8 mod=0; 
char dingshi; 
bit bell=0; 
bit zanting=1; 

void fangsong() 
{ 
wrd(dat1[sg/10]); //时十位 
wrd(dat1[sg%10]); //时个位 
wrd(0x3A); //: 
wrd(dat1[fg/10]); //分十位 
wrd(dat1[fg%10]); //分个位 
wrd(0x3A); //: 
wrd(dat1[(s/10)]); //秒十 
wrd(dat1[(s%10)]); //秒个 
} 

void fangsong1() 
{ 
wrm(0X80); 
wrd(dat1[sg/10]); //时十位 
wrd(dat1[sg%10]); //时个位 
wrd(0x3A); //: 
wrd(dat1[fg/10]); //分十位 
wrd(dat1[fg%10]); //分个位 
wrd(0x3A); //: 
wrd(dat1[(s/10)]); //秒十 
wrd(dat1[(s%10)]); //秒个
 } 

void chuli() 
{ 
if(fg==60) 
{ 
sg++; 
fg=0; 
} 
if(sg==24) 
{ 
sg=0; 
} 
} 

void main() 
{ 
u8 shijian; 
open012(); 
zero(); 
chuli(); 
fangsong(); 
shijian=100; 
while(1) 
{ 
while(mod==0) 
{ 
EX1=1; //打开外部中断1 
if(s==60) 
{ 
fg++; //60秒转化为1分钟 
s=0; 
} 
chuli(); 
if((fg==0)&&(shijian!=sg)) 
{ 
BUZ=0; 
shijian=sg; 
} 
fangsong1(); 
if((BUZ==0)&&(bell==0)) 
{ 
delay(1000); 
BUZ=1; 
} 
if((fg==bfg)&&(sg==bsg)&&(bell==1)) 
BUZ=0; 
else BUZ=1; 
} 
while(mod==1) 
{ EX1=0; //关闭外部中断1 
zero(); 
fangsong(); 
if(K3==0) 
{ delay(1000); 
if(K3==0) 
fg++; 
} 
if(K4==0) 
{ delay(1000); 
if(K4==0) 
sg++; 
} 
if(K2==0) 
{ delay(1000); 
if(K2==0) s=0; } 
if(fg>59) 
{ fg=0; } 

if(sg>23) 
{ sg=0; } 
if(s>=59) 
{ s=0; } 	    
} 
while(mod==2) //设置闹钟 
{ 
if(bfg==60) 
{ bsg++; 
bsg=0; 
} 

if(bsg==24) 
{ bsg=0; } 
zero(); 
wrd(0x20); 
wrd(0x20); 
wrd(0x20); 
wrd(dat1[(bsg/10)]); //时十位 
wrd(dat1[(bsg%10)]); //时个位 
wrd(0x3A); //: 
wrd(dat1[(bfg/10)]); //分十位 
wrd(dat1[(bfg%10)]); //分个位 
if(K3==0) 
{ delay(1000); 
if(K3==0) bfg++; 
} 

if(K4==0) 
{ delay(1000); 
if(K4==0) bsg++; 
} bell=1; 
zero(); 
} 

while(mod==3) 
{ while(zanting) 
{ dingshi=60; 
EX1=1; //打开外部中断1 
wrm(0X80); 
wrd(dat1[(dingshi/10)]); //时十位 
wrd(dat1[(dingshi%10)]); //时个位 } 
wrm(0X80); 
wrd(dat1[(dingshi/10)]); //时十位 
wrd(dat1[(dingshi%10)]); //时个位 
while(dingshi<0) 
{ wrm(0X80); 
wrd(dat1[0]); //时十位 
wrd(dat1[0]); //时个位 BUZ=0; 
} 
} 
} 
} 

void time0() interrupt 1 
{ TH0=0XFC;	     //给定时器赋初值,定时1ms 
TL0=0X18; 
i++; 
if(i==1000) //ms转化为s 
{ 
i=0; 
s++; 

dingshi--; }	
} 
void key1() interrupt 0 //外部中断0,调整时间 
{ delay(1000); 
if(K1==0) 
{ mod++; 
while(!K1); 
} 
if(mod>3) 
{ 
mod=0; 
} 
zero(); 
} 
void naozhong() interrupt 2 //开关闹钟 
{ if(K2==0) { delay(1000); //消抖 
if(K2==0) 
{ 
bell=0; 
BUZ=1; 
zanting=~zanting; } //关闭蜂鸣器 
while(!K2); //确认按键松开 } }

在这里插入图片描述

二、收获


1.更熟练掌握了定时器中断和外部中断的使用


在这里插入图片描述

在这里插入图片描述

可以通过打开和关闭外部中断使同一个按键实现不同的功能 2.了解到了一点寄存器操作

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.中断配置小结


外部中断


在这里插入图片描述


定时器中断


在这里插入图片描述

串口通信


在这里插入图片描述


4.更熟练使用proteus


制作了一个小型软件开发版


在这里插入图片描述

5.学会了如何学习一个新元器件(LCD1602)


1.看说明书,重点是看时序图,真值表等


2.按照时序图写程序


3.一二都不成立时,查找相关资料


6.下载原理


单片机的烧写原理:


单片机烧写,又称为单片机程序下载、烧录等,本质上是单片机和PC机按照芯片厂家规定的编程协议,通过芯片厂家规定的接口,把已编译好的程序传输到单片机,单片机把数据存储到自身存储器中。


理解这个原理需要知道几个知识点:


单片机内部是有程序的,是出厂时固化在硬件中,用户无法修改的(这也会被认为它内部没有程序),这些程序可以调用各种通信接口、内部存储器等;


可以下载的通信接口:JTAG,SPI,UART,usb等;(还有很多可以扩展485、以太网等)


编程协议:一般大厂都会公开的,在芯片的专用技术手册中会有;


存储器:有很多种,掩膜,EPROM,EEROM,flash等寿命不一样,掩膜只能一次,而且要工厂做,flash擦写次数10000+;


可以这样比喻性的理解:单片机就是电脑的主板,我们写的程序就是操作系统,主板里面装入引导操作系统的基本程序,下载程序就是给电脑装系统! 7.其他


1.理解了现在电子表的操作原理


2.学会了借助现成品(电子表)作参考,写程序


3.懂得了与人交流的重要性(受王同学的启发,完善了原有程序)

 三.后期计划


1、继续32的学习


2、练习焊功


3、继续51其他外设的学习


4、按兴趣学习电路、模电、数电、DXP等相关知识