1.png (73.02 KB, 下載次數: 40)
下載附件
2023-1-3 17:39 上傳
一、設計內容
內容:用單片機控制實現基本數字電子鐘的設計,擴展了4X4鍵盤和4位LED數碼顯示器,可用于顯示和按鍵控制。
功能:能夠顯示時和分;可通過按鍵設置鬧鐘功能;可進行整點報時;可通過按鍵設置分校時。
二、總體方案設計
2.1 功能分析
數字電子鐘系統可以分為主控制單元、復位電路、鍵盤電路、顯示電路等。
2.2 各模塊功能說明
晶振電路的功能:每個單片機系統里都有晶振,全程是叫晶體震蕩器,在單片機系統里晶振的作用非常大,他結合單片機內部的電路,產生單片機所必須的時鐘頻率,單片機的一切指令的執行都是建立在這個基礎上的,晶振的提供的時鐘頻率越高,那單片機的運行速度也就越快。晶振用一種能把電能和機械能相互轉化的晶體在共振的狀態下工作,以提供穩定,精確的單頻振蕩。
復位電路的功能:把電路初始化到一個確定的狀態,一般來說,單片機復位電路作用是把一個例如狀態機初始化到空狀態,而在單片機內部,復位的時候單片機是把一些寄存器以及存儲設備裝入廠商預設的一個值。
鍵盤電路:根據4×4矩陣鍵盤,它是用四條I/O線作為行線,四條I/O線作為列線組成的鍵盤。在行線和列線的每個交叉點上設置一個按鍵。這樣鍵盤上按鍵的個數就為4×4個。這種行列式鍵盤結構能有效地提高單片機系統中I/O口的利用率。實現按鍵控制鬧鐘,設置時間的功能。
顯示電路的功能:采用4位共陰極數碼管驅動方式P2口相應的位置0 即選擇要顯示的數碼管位,P0口相應的位置1即可顯示相應的數碼管段。負責顯示時鐘的時和分。
三、硬件系統設計
使用了Produce軟件進行硬件原理圖的仿真設計。
部分電路如圖所示:
a. 主控電路: 80C51單片機
b. 晶振電路:89C51單片機內部的振蕩電路是一個高增益反相放大器,引線XTAL1和XTAL2分別 為反相振蕩放大器的輸入及內部時鐘工作電路的輸入和來自反相振蕩器的輸出,該反相放大 器可以配置為片內振蕩器。
c. 復位電路:采用上電復位,上電后,由于電容充電,使RST持續一段時間的高電平,從而實 現上電復位操作。這不僅能使單片機復位,還能是單片機的外圍設備同時復位,當程序出 現錯誤時,可以隨時使電路復位。
d. 鍵盤電路:當按鍵被按下時,相應的引腳被拉低,經掃描后,獲得鍵值,并執行鍵功能程 序,因此通過按下同一個鍵,將執行不同的功能程序。
e. 顯示電路:主要是數碼管顯示數字電子鐘的時和分。
四、軟件系統設計
4.1 程序總體流程圖
主函數的流程框圖:先進行初始化設定初值,然后相關子程序的調用
4.2 主要模塊程序流程
1.調用中斷服務子程序,循環次數++,因為定時時長為50ms,所以循環次數為20時,循環次數清0,秒++;秒為60時分加++,秒清0;分為60時,時++,分清0;時為24時,時清0,中斷返回。
2.先確認彈簧消抖是否有鍵按下,之后判斷掃描按鍵,不同的按鍵觸發不同功能。
五、源代碼
部分代碼展示:
#include<reg51.h>
#define tl 0xba; //宏定義 tl賦初值
#define th 0x3c; //宏定義 th賦初值
sbit speaker=P3^5; //鬧鐘輸出 蜂鳴器
unsigned char code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //數碼管顯示的數字0-9的編碼
unsigned char count0,second,minit,hour; //時間時分秒
unsigned int second1,minit1,hour1;//鬧鐘時分秒
//timenum1是調節時間的按鍵按下的次數
//timenum2是調節鬧鐘的按鍵按下的次數
//f1是否在設置鬧鐘
//f2是否在設置時間
unsigned char timenum1,timenum2,f1,f2;
unsigned int dsflg;
unsigned char temp;
//延時子程序 代碼燒路軟件自動生成的
void delay(void)
{
unsigned int i;
for(i=0;i<100;i++);
}
//50ms
//數碼管顯示
void display(void)
{
P0=led[hour/10]; //p0口送數據 拆數顯示,時的十位
P2=0xFE; //片選 P2.0
delay(); //延時
P2=0xFF; //片選關
P0=led[hour%10]; //p0口送數據 拆數顯示,時的個位
P2=0xFD; //P2.1
delay();
P2=0xFF;
P0=led[minit/10]; //p0口送數據 拆數顯示,分的十位
P2=0xFB; //P2.2
delay();
P2=0xFF;
P0=led[minit%10]; //p0口送數據 拆數顯示,分的個位
P2=0xF7; //P2.3
delay();
P2=0xFF;
}
//掃描按鍵
void keyscan()
{
unsigned char temp;
P1=0xfe; // 給P1.0賦低電平
temp=P1;
temp=temp&0xf0; //判斷P1.0那一列是否有鍵按下
if(temp!=0xf0)// 確定有鍵按下的時候
{
delay1(10); //延時子程序進行消抖
temp=P1;
temp=temp&0xf0; //再次判斷p1.0那一列是否有鍵按下
if(temp!=0xf0) //確定有鍵按下
{
temp=P1; //將P1的值給temp
switch(temp)
{
case 0xee: //p1.4口
timenum1++; //標記++
TR1=0; //不啟動T1 ,關閉蜂鳴器
f2=0; //進入調時間的狀態
if(timenum1==1||timenum2==1) //如果timenum1==1 調時
{
dsflg=0; //正在調時間
}
if(timenum1==3) 如果timenum1==4 退出
{
TR1=1; //啟動T1
timenum1=0; //將按鍵次數歸零
dsflg=1; //退出調時間
f2=1; //退出調節時間
}
break;
case 0xde: //p1.5口
//調時間
if(timenum1==1) //如果timenum1==1 調時
{
hour++; //小時++
}
if(timenum1==2) //如果timenum1==2 調分
{
minit++;
}
//調鬧鐘
if(timenum2==1) //如果timenum2==1 調時 鬧鐘
{
hour1++; //小時++
}
if(timenum2==2) //如果timenum2==2 調分 鬧鐘
{
minit1++;
}
break;
case 0xbe: //p1.6口
speaker=1; //蜂鳴器處于不響狀態在設置時間的時候
if(timenum1==1) //如果timenum1==1 調時
{
hour--; //小時--
}
if(timenum1==2) //如果timenum1==2 調分
{
minit--; //分鐘--
}
//調鬧鐘
if(timenum2==1) //如果timenum2==1 調時 鬧鐘
{
hour1--; //小時--
}
if(timenum2==2) //如果timenum2==2 調分 鬧鐘
{
minit1--;
}
break;
case 0x7e://p1.7
timenum2++; //標記++
f1=0; //進入設置鬧鐘
if(timenum2==1||timenum2==2) //如果timenum2=1設定腦鐘的小時
{
dsflg=0; //正在調時間
}
if(timenum2==3) //如果timenum2=3退出
{
timenum2=0; //將按鍵次數歸零
dsflg=1; //退出調時間
f1=1; // 退出設置鬧鐘
}
break;
}
while(temp!=0xf0) //判斷按鍵是否彈起
{
temp=P1;
temp=temp&0xf0;
}
}
}
}
//按鍵控制 時間設置
void Keykonzhi()
{
if(timenum1==1) //如果timenum1==1 調時
{
if(hour>23) //限位
{
hour=0;
}
P0=led[hour/10]; //顯示小時
P2=0xFE; //小時十位 p2.0
delay();
P2=0xFF;
P0=led[hour%10]; //顯示小時
P2=0xFD; //小時個位 p2.1
delay();
P2=0xFF;
}
if(timenum1==2) 如果timenum1==2 調分 //以下也是和調時一樣的方法
{
if(minit>59)
{
minit=0;
}
P0=led[minit/10];
P2=0xFB; //分鐘十位 p2.2
delay();
P2=0xFF;
P0=led[minit%10];
P2=0xF7; //分鐘個位 p2.3
delay();
P2=0xFF;
}
}
//設置鬧鐘
void almset()
{
timenum1=0;
if(timenum2==1) //如果timenum2==1設定鬧鐘的小時
{
if(hour1>23) //限位
{
hour1=0;
}
P0=led[hour1/10];//小時顯示 十位
P2=0xFE;//p2.0
delay();
P2=0xFF;
P0=led[hour1%10];
P2=0xFD;//p2.1 小時個位 顯示
delay();
P2=0xFF;
}
if(timenum2==2) //如果timenum2==2設定鬧鐘的分鐘 和上面小時一樣
{
if(minit1>59)
{
minit1=0;
}
P0=led[minit1/10];//顯示分鐘十位
P2=0xFB; // p2.2
delay();
P2=0xFF;
P0=led[minit1%10];//顯示分鐘個位
P2=0xF7;// p2.3
delay();
P2=0xFF;
}
}
//控制鬧鐘 (鬧鐘到了設定時間就會響)
void almkozi()
{
if((hour1==hour)&&(minit1==minit)&&(second<4))
{
speaker=0; //鬧鐘時間到,蜂鳴器響
}
if(minit==0&&second<4)
{
//整點報時,蜂鳴器響
speaker=0;
}
if(second>4) //控制蜂鳴器響的時長
{
speaker=1; //關閉蜂鳴器
}
}
六、測試結果展示
1. 時鐘顯示:最開始設置時間為12:59。
2 . 鬧鐘調時:手動按鍵調整時鐘的時。
3. 鬧鐘調分:手動按鍵調整時鐘的分。
4. 整點報時:時鐘到整點蜂鳴器就會響,達到報時的效果。
在做設計的過程中,我進一步認識到全面專業知識以及邏輯思考方式對研究問題的重要性,同時我也更加具體的掌握了設計的基本方法。經過不斷的努力,我終于完成了這次設計,總的來說,我學到了不少的東西,知道了理論聯系實際的重要性。在設計過程中我遇到了很多的困難,但沒放棄,查閱了許多相關的書籍,自己獨立思考和借鑒了前人的許多優秀成果,并與所學的知識緊密的結合了起來。我相信這過程對我今后的學習和工作有著積極的影響,并搭好了平臺。通過這次設計,我對這門課有了更好的理解,尤其結合了這幾年學的相關的專業知識,對各門課都有了一個較全面的理解。這必將對我以后的學習和工作有很大的幫助。本次設計的定時鬧鐘電路,可以滿足人們的基本要求,但因為知識水平有限,此電路中存在一定的問題,雖可以通過增加電路解決,但過于復雜和現有水平有限,本次設計就未深入涉及,想要更好的改進電路,需要進一步的努力,如果有好的意見,希望
|