|
一:電路原理和器件選擇
制作電路:單片機(jī)(AT89S52)實(shí)現(xiàn)多功能數(shù)字鐘
性能指標(biāo):該數(shù)字鐘實(shí)現(xiàn)時(shí)鐘運(yùn)行,調(diào)整,倒計(jì)時(shí),秒表功能,且精確度經(jīng)調(diào)試一天的誤差在2S內(nèi)。
實(shí)現(xiàn)原理:利用單片機(jī)定時(shí)器及計(jì)數(shù)器產(chǎn)生定時(shí)效果通過編程形成數(shù)字鐘效果,再利用數(shù)碼管動(dòng)態(tài)掃描顯示單片機(jī)內(nèi)部處理的數(shù)據(jù)。同時(shí)通過端口讀入當(dāng)前外部控制狀態(tài)來改變程序的不同狀態(tài),實(shí)現(xiàn)不同功能。
電路主要模塊及原理圖:
1.數(shù)碼顯示硬件驅(qū)動(dòng)

數(shù)碼管驅(qū)動(dòng)電路
2.單片機(jī)最小系統(tǒng):

單片機(jī)最小系統(tǒng)
3.LED及單片機(jī)電源原理圖

LED及單片機(jī)電源
4.外部控制狀態(tài)輸入模塊原理圖

外部控制狀態(tài)輸入模塊原理圖
主要元器件選擇:
單片機(jī):AT89S52采用市場上比較常用的AT89S52,這里采用AT89S52而不是AT89S51是為了最大限度減小誤差,因?yàn)橐獙?shí)現(xiàn)多功能(例如秒表,時(shí)鐘,倒計(jì)時(shí))為了相互之間不干擾而要用到3個(gè)定時(shí)/計(jì)數(shù)器,而51系列只有2個(gè),而52系列有3個(gè),故采用52系列
三極管:用來進(jìn)行數(shù)碼管顯示的位選,這里采用PNP管
數(shù)碼管:采用共陽級(jí)四位數(shù)碼管
晶振:采用的是11.0592MHZ的晶振
電源部分:采用5V電壓供電,采用的是L7805穩(wěn)壓芯片供電(加濾波)
電阻:大部分時(shí)限流電阻,阻值為4.7K或10K,1K
端口分配及連接:
P0:LED數(shù)碼管顯示內(nèi)容通過P1口從單片機(jī)傳送到數(shù)碼管
P2.4-P2.7:數(shù)碼管位選控制端口
P2.0-P2.3:分別連接開關(guān)K0,K1,K2,K3通過不同的組合實(shí)現(xiàn)外部控制程序狀態(tài)
P1.0:蜂鳴器,倒計(jì)時(shí)完畢產(chǎn)生鳴響
P1.2-P1.5:四個(gè)發(fā)光二極管,顯示當(dāng)前時(shí)鐘狀態(tài)
完整的源程序如下:
附程序源代碼及注釋
#include <reg52.h>
#include <absacc.h>
#define uint unsigned int
#define uchar unsigned char
/*定義P2口各管腳*/
sbit K0=P2^2;
sbit K1=P2^1;
sbit K2=P2^0;
sbit K3=P2^3;
sbit D0=P2^4;
sbit D1=P2^5;
sbit D2=P2^6;
sbit D3=P2^7;
/*定義P1口各管腳*/
sbit beep=P1^0;
sbit L0=P1^5;
sbit L1=P1^4;
sbit L2=P1^3;
sbit L3=P1^2;
uchar data BUFFER[4]={0,0,0,0}; //顯示緩沖區(qū)(依次從低位到高位,共四位數(shù)碼管)
uchar data CLOCK[4]={0,0,0,0}; //存放時(shí)鐘時(shí)間(依次是百分秒,秒,分,時(shí))
uchar data SECOND[3]={0,0,0}; //存放秒表時(shí)間(依次時(shí)百分秒,秒,分)
uchar data SEVER[4]={0,0,0,0}; //存放倒計(jì)時(shí)時(shí)間(依次是百分秒,秒,分,時(shí))
/*定義程序運(yùn)行狀態(tài)*/
uchar data STATE=0;
/*STATE=0;時(shí)鐘運(yùn)行*/
/*STATE=1;時(shí)鐘分調(diào)整*/
/*STATE=2;未定義狀態(tài),可添加*/
/*STATE=3;時(shí)鐘時(shí)調(diào)整*/
/*STATE=4;倒計(jì)時(shí)分調(diào)整*/
/*STATE=5;倒計(jì)時(shí)時(shí)調(diào)整*/
/*STATE=6;秒表*/
/*STATE=7;倒計(jì)時(shí)運(yùn)行*/
/*定義輔助計(jì)時(shí)全局變量*/
uchar m=60;
/*共陽數(shù)碼管顯示"0"-"9","-" */
uchar code TABLE[]={0xC0,0xf9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98,0xbf};
/*自定義子函數(shù)*/
void display(); //顯示函數(shù)
void delay(); //顯示延時(shí)函數(shù)
void intsvr(); //調(diào)整時(shí)間時(shí)加1子函數(shù)
void delay10ms(); //延時(shí)函數(shù)
/*主函數(shù)體*/
void main(void)
{
EA=1;ET0=1; //開總中斷源,開T0中斷
TMOD=0x61; //T1方式2計(jì)數(shù),T0方式1計(jì)時(shí)
TH0=-9460/256;TL0=-9460%256; //初始化計(jì)數(shù)器初值
TH1=0xff;TL1=0xff;
T2CON=0;TH2=-9452/256;TL2=-9452%256;
K0=1;K1=1;K2=1; //初始化控制狀態(tài)位
STATE=P2&0x07;
for(;;)
{
switch(STATE)
{
case 1: //時(shí)鐘分調(diào)整程序
{
TR0=0;ET0=0;EX0=0;TR2=0; //關(guān)閉定時(shí)器,時(shí)鐘停止運(yùn)行,同時(shí)關(guān)閉外中斷IT0
L3=0;L1=0;L2=0;L0=1;
intsvr(); //調(diào)用加1函數(shù)
BUFFER[0]=CLOCK[2]%10; //數(shù)碼管顯示分鐘個(gè)位
BUFFER[1]=CLOCK[2]/10; //數(shù)碼管顯示分鐘十位
BUFFER[2]=10; //顯示"-"
BUFFER[3]=10; //顯示"-"
}break;
case 3: //時(shí)鐘時(shí)調(diào)整程序
{
TR0=0;ET0=0;EX0=0;TR2=0; //關(guān)閉定時(shí)器,時(shí)鐘停止運(yùn)行
L3=0;L1=0;L2=0;L0=1;
intsvr(); //調(diào)用加1函數(shù)
BUFFER[0]=CLOCK[2]%10; //數(shù)碼管顯示分鐘個(gè)位
BUFFER[1]=CLOCK[2]/10; //數(shù)碼管顯示分鐘十位
BUFFER[2]=CLOCK[3]%10; //數(shù)碼管顯示時(shí)鐘個(gè)位
BUFFER[3]=CLOCK[3]/10; //數(shù)碼管顯示時(shí)鐘十位
}break;
case 4: //倒計(jì)時(shí)分鐘調(diào)整程序
{
TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常運(yùn)行,即時(shí)鐘正常運(yùn)行,同時(shí)關(guān)閉外中斷IT0
L3=0;L2=0;L1=0;
intsvr(); //調(diào)用加1函數(shù)
BUFFER[0]=SEVER[2]%10; //數(shù)碼管顯示分鐘個(gè)位
BUFFER[1]=SEVER[2]/10; //數(shù)碼管顯示分鐘十位
BUFFER[2]=10; //顯示"-"
BUFFER[3]=10; //顯示"-"
SECOND[1]=0; //秒表初始化為0
SECOND[2]=0;
}break;
case 5: //倒計(jì)時(shí)時(shí)鐘調(diào)整程序
{
TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常運(yùn)行,即時(shí)鐘正常運(yùn)行,同時(shí)關(guān)閉外中斷IT0
L3=0;L2=0;L1=0;
intsvr(); //調(diào)用加1子函數(shù)
BUFFER[0]=SEVER[2]%10; //數(shù)碼管顯示分鐘個(gè)位
BUFFER[1]=SEVER[2]/10; //數(shù)碼管顯示分鐘十位
BUFFER[2]=SEVER[3]%10; //數(shù)碼管顯示時(shí)鐘個(gè)位
BUFFER[3]=SEVER[3]/10; //數(shù)碼管顯示時(shí)鐘十位
SECOND[1]=0; //秒表初始化為0
SECOND[2]=0;
}break;
case 6:
{
TR0=1;ET0=1;EX0=1;ET2=1;//保持T0正常運(yùn)行,即時(shí)鐘正常運(yùn)行,同時(shí)開外中斷IT0
BUFFER[0]=SECOND[1]%10; //數(shù)碼管顯示秒表秒個(gè)位
BUFFER[1]=SECOND[1]/10; //數(shù)碼管顯示秒表秒十位
BUFFER[2]=SECOND[2]%10; //數(shù)碼管顯示秒表分個(gè)位
BUFFER[3]=SECOND[2]/10; //數(shù)碼管顯示秒表分十位
}break;
case 7:
{
TR0=1;ET0=1;EX0=0;ET2=1; //倒計(jì)時(shí)運(yùn)行,同時(shí)時(shí)鐘也正常運(yùn)行,關(guān)閉外中斷T0
if((SEVER[2]==0)&&(SEVER[3]==0)) //當(dāng)預(yù)置時(shí)間(分,時(shí))變?yōu)?時(shí),計(jì)時(shí)完畢
{
beep=!beep; //蜂鳴器響
BUFFER[0]=10; //顯示"-"
BUFFER[1]=10;
BUFFER[2]=10;
BUFFER[3]=10;
TR2=0; //關(guān)閉T2
}
else
{
TR2=1; //開啟T2
}
SECOND[1]=0; //秒表時(shí)間初始化
SECOND[2]=0;
}break;
default:
{
ET0=1;TR0=1;EX0=0; //開啟T0,時(shí)鐘運(yùn)行,關(guān)閉外中斷
L1=1;L3=1;L2=1;
BUFFER[0]=CLOCK[2]%10; //數(shù)碼管顯示分鐘個(gè)位
BUFFER[1]=CLOCK[2]/10; //數(shù)碼管顯示分鐘十位
BUFFER[2]=CLOCK[3]%10; //數(shù)碼管顯示時(shí)鐘個(gè)位
BUFFER[3]=CLOCK[3]/10; //數(shù)碼管顯示時(shí)鐘十位
}
}
K0=1;K1=1;K2=1; //重新預(yù)置狀態(tài)位
display(); //調(diào)用顯示函數(shù)
STATE=P2&0x07; //通過P2口提取當(dāng)前狀態(tài)
}
}
/*T0中斷服務(wù)*/
void time0(void) interrupt 1 using 1 //T0中斷函數(shù)
{
TH0=-9460/256; //計(jì)時(shí)器放入預(yù)置時(shí)間,大概10毫秒
TL0=-9460%256;
CLOCK[0]=CLOCK[0]+1; //一次中斷加1
if(CLOCK[0]==50) //0.5秒到
{
L0=!L0; //L0取反
}
if(CLOCK[0]==100) //1秒到
|
|