基於51單片機電子時鐘

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<reg52.h>
//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等相關知識

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章