|
課程設計文檔,含原理圖,程序。
課程設計(論文)任務書目錄
摘要
第1章 緒論
1.1籃球計分器簡介
1.2設計主要內容
1.2.1設計方案
1.2.2設計的主要步驟
1.2.3主要功能
第2章 系統硬件設計
2.1硬件組成
2.2顯示模塊
2.3時鐘電路、復位電路模塊
2.4按鍵模塊
第3章 系統軟件設計
3.1 主程序框圖
3.2程序分析
3.2.1延時子程序
3.2.2比分顯示程序
3.2.3時間顯示程序
3.2.4鍵盤掃描程序
3.2.5定義的74ls595寫入程序
第4章 實驗與分析
4.1 籃球計分器的比分測試
4.1.1相關功能鍵的測試
4.1.2出現的問題與分析
4.2籃球計分器時間測試
4.2.1相關功能鍵的測試
4.2.2出現的問題與分析
參考文獻
心得體會
附錄 硬件電路圖
附錄 程序清單
摘要隨著人們生活水平的提高和生活節奏的加快,對時間的要求越來越高,精準數字計時的消費需求也是越來越多。 我國生產的電子萬年歷有很多種,總體上來說以研究多功能電子萬年歷為主,使萬年歷除了原有的顯示時間,日期等基本功能外,還具有鬧鈴,報警等功能。商家生產的電子萬年歷更從質量,價格,實用上考慮,不斷的改進電子萬年歷的設計,使其更加的具有市場。 本設計為軟件,硬件相結合的一組設計。在軟件設計過程中,應對硬件部分有相關了解,這樣有助于對設計題目的更深了解,有助于軟件設計。基本的要了解一些主要器件的基本功能和作用。 此次課程設計使用專門的時鐘芯片DS1302在液晶顯示器LCD12864上顯示時鐘,并能通過按鍵對其進行調試和校準以及實現年月日。DS1302是一種高性能、低功耗、帶RAM的實時時鐘芯片,它能夠對時分秒進行精確計時。將RST、SCLK、I/O引腳分別與STC12C5A60S2單片機P2^0、P2^1、P2^2相連,使單片機對其進行讀寫操作,把讀出的數據送到LCD12864上顯示,通過4個按鍵實現對時間的調整和鬧鈴的設定和調整,具有顯示直觀、電路簡潔、使用方便簡單等優點。
第1章 緒論1.萬年歷簡介電子萬年歷是一種非常廣泛的日常計時工具,它可以對年、月、日、周、時、分、秒進行精確計時在日常生活中極為實用,DS1302是常用的時鐘芯片,價格低廉,精度高且對與數字電子萬年歷采用直觀的數字顯示,還具有時間校準等功能。 1.2設計主要內容1.2.1設計方案- 顯示部分:通過12864液晶顯示模塊顯示年、月、日、時、分、秒,并可以切換顯示時間設置、鬧鐘設置和波形圖。
- 按鍵部分:本次設計將采用
1.003.jpg (21.67 KB, 下載次數: 104)
下載附件
2017-4-22 23:28 上傳
矩陣鍵盤作為功能按鍵,需要的功能按鍵有:日期/時間切換鍵,控制鍵,加鍵,減鍵,鬧鐘關閉鍵,貪睡鍵,方波輸出鍵,正弦波輸出鍵。
(3)時鐘模塊:采用時鐘芯片DS1302。美國DALLAS公司推出的具有涓細電流充電能的低功耗實時時鐘電路DS1302。它可以對年、月、日、周日、時、分、秒進行計時,還具有閏年補償等多種功能,而且DS1302的使用壽命長,誤差小。對于數字電子萬年歷采用直觀的數字顯示,可以同時顯示年、月、日、周日、時、分、秒,還具有時間校準等功能。利用單片機對其進行讀寫操作,然后將讀出的時間數據送到LCD12864上顯示。 - 查閱相關資料,了解老師所給的資料里面開發板的線路連接和各個模塊資料;
- 用protel實現硬件的仿真,畫出原理圖以及PCB圖;
- 參照老師所給示例程序和網上資料用keil 軟件進行單片機的編程設計,運行調試;
- 將keil生成的hex文件燒錄進入開發板,進行測試。
1.2.3主要功能(1)使用掃描式鍵盤,通過按鍵實現設定、修改日期和時間,省電(關閉顯示)等功能,鍵盤功能自行定義; (2)實現倒計時功能,倒計時時間由鍵盤輸入設定,定時時間到LED閃爍; (3)實現4路可調鬧鐘功能,當4路鬧鈴中的任一路時間到時,通過不同的鈴聲顯示鬧鈴時間到,且鈴聲持續時間不超過1分鐘。1分鐘以內若按下停止鍵,鈴聲停止;若按下貪睡鍵,鈴聲停止,3分鐘以后再次響鈴;1分鐘以內若不按任何鍵,鈴聲自動停止,3分鐘后再次響鈴。 (4)通過2個按鍵,分別實現輸出10Hz的正弦波及方波。
第2章 系統硬件設計 2.1硬件組成硬件以STC12C5A60S2單片機為核心,外部擴展LCD12864液晶顯示模塊、按鍵控制鍵盤模塊、DS1302時鐘芯片,蜂鳴器模塊實現動態顯示時間日期,鬧鈴設置,倒計時,波形圖顯示等功能。 基本硬件結構圖如圖2.1所示。
1.004.jpg (16.42 KB, 下載次數: 122)
下載附件
2017-4-22 23:28 上傳
圖2.1 萬年歷基本硬件結構圖 2.2顯示模塊
1.005.jpg (43.36 KB, 下載次數: 111)
下載附件
2017-4-22 23:28 上傳
圖2.2 數碼管 顯示模塊用的是兩個4位7段數碼管,切換顯示比分和時間,例如比分顯示為111--111,時間顯示為01-12-00:1為第一節,12-00為倒計時。 2.3時鐘電路、復位電路模塊
1.006.jpg (33.24 KB, 下載次數: 115)
下載附件
2017-4-22 23:28 上傳
圖2.3 時鐘電路、復位電路 時鐘電路在單片機系統中有著非常重要的作用,是保證系統正常工作的基礎。在一個單片機應用系統中,時鐘是保證系統正常工作的基準震蕩定時信號,主要由晶振和外圍電路組成,晶振頻率的大小決定了系統工作的快慢。圖中采用12MHZ的晶振,另外有兩個30P的電容,兩晶振引腳分別連到XTAL1和XTAL2振蕩脈沖輸入引腳。復位電路是單片機的初始化操作,圖中RST引腳是復位信號的輸入端。具體連接如圖2.3所示。 2.4按鍵模塊S2控制甲隊加分,S5控制甲隊減分;S3控制乙隊加分,S6控制乙隊減分;S8控制比分互換;S13控制比分切換到時間,S11控制時間切換到比分;S9為比分清零;S12為增加節數,S21為減少節數。具體連接分布如圖2.4所示。
1.007.jpg (51.1 KB, 下載次數: 127)
下載附件
2017-4-22 23:28 上傳
圖2.4 矩陣鍵盤電路 第3章 系統軟件設計3.1 主程序框圖當程序啟動時,先進入各個模塊初始化,初始化完成后,進入鬧鐘判斷,若是鬧鐘設置的時間到了,則進入鬧鐘中斷子程序中,處理鬧鐘中斷;若是沒有,則是在數碼管上顯示初始化程序里的時間。接著是調用鍵盤掃描程序,判斷控制鍵是否按下,若按下,則i的值加1,同時進入相應的功能程序。其中主要的功能程序有:4個鬧鐘時間的設置,波形輸出,時間的設置,以及倒計時功能。當它們執行完相應的子程序后,則返回時間顯示界面。
1.008.jpg (26.35 KB, 下載次數: 97)
下載附件
2017-4-22 23:28 上傳
圖3.1 主程序框圖 3.2控制鍵程序 控制鍵按下時,程序的變量i會相應地加1,而且同時進入相應的功能程序,例如i=1、2、3時,會進入相應地鬧鐘時間設置,分別設置鬧鐘1的時/分/秒。同理,i=4~12分別設置鬧鐘2、3、4的時間。然后i=13、14、15、16、17、18接下來是正常的時間設置,分別設置年/月/日/小時/分鐘/秒鐘。I=19時,進入波形輸出,i=20時,進入倒計時功能。最后程序返回時間顯示,同時i的值清零。
1.009.jpg (33.5 KB, 下載次數: 109)
下載附件
2017-4-22 23:28 上傳
圖3.2.控制鍵程序流程圖
1.010.jpg (1.86 KB, 下載次數: 94)
下載附件
2017-4-22 23:28 上傳
東北大學課程設計報告 參考文獻 3.3日期/時間設置流程圖控制鍵按下時,i=13、14、15,分別進入年/月/日的設置,然后通過加/減鍵來使當前鍵值加1或者減1;當i=1、4、7、10、16時,進入小時設置;當i=2、5、8、11、17進入分鐘設置;i=3、6、9、12、18,進入秒鐘設置。
1.011.jpg (58.17 KB, 下載次數: 117)
下載附件
2017-4-22 23:28 上傳
圖3.3時間/日期設置程序流程圖
3.4 DS1302程序
1.012.jpg (32.69 KB, 下載次數: 106)
下載附件
2017-4-22 23:28 上傳
圖3.4DS1302時控流程圖 3.4.1 DS1302讀寫程序void SendByte(uchar Command,SendDat) { //字節發送子程序。入口參數:命令字,數據 uchar i; RST=0;CLK=0;RST=1; for(i=0;i<8;i++) //發送命令字 { DP=Command&0x01; //取一位送數據口 CLK=0;CLK=1; //產生一個上升沿 Command>>=1; } for(i=0;i<8;i++) //發送數值 { DP=SendDat&0x01; CLK=0;CLK=1; SendDat>>=1; } RST=0; }
uchar ReadByte(uchar Command) //讀字節子程序。入口參數:命令字 { //出口參數:數值 uchar i,RecDat=0; RST=0;CLK=0;RST=1; for(i=0;i<8;i++) //發送命令字 { DP=Command&0x01; CLK=0;CLK=1; Command>>=1; } for(i=0;i<8;i++) //讀入數值 { CLK=1;CLK=0; //產生一個下降沿 if(DP) RecDat|=0x01<<i; 讀入數據[="" align]" }[="" rst="0;" return(recdat);="" 返回數值[="" null,="" left][size="12pt]當鬧鐘設置的時間到了時,這時程序就會進入鬧鐘中斷程序。例如鬧鐘1設置的時間到了,就會使蜂鳴器響起鬧鈴,鍵盤掃描停止鍵是否按下,若在一分鐘內按下,則鬧鐘停止,同時鍵盤掃描判斷貪睡鍵是否按下,若按下,則三分鐘后再次響鈴,若一分鐘內沒有鍵按下,自動停止,然后3分鐘后響鈴;
1.013.jpg (19.88 KB, 下載次數: 105)
下載附件
2017-4-22 23:28 上傳
圖3.5鬧鐘中斷程序流程圖
第4章 實驗與分析為了實現籃球計分器的功能,我們必須通過不斷地測試和分析,實現軟件與硬件融為一體。從內容上,我們將它分為比分的測試和時間的測試。 4.1 籃球計分器的比分測試4.1.1相關功能鍵的測試- 按下S2鍵控制A隊加1分(2)按下S5鍵控制A隊減1分(3)按下S3鍵控制B隊加1分(4)按下S6鍵控制B隊減1分(5)按下S8鍵控制比分互換(6)按下S9鍵為比分清零
如圖4.1所示,當前比分為24比17 圖4.1籃球計分器比分測試圖 4.1.2出現的問題與分析分析:出現這種情況可能的原因:一、硬件方面,可能是矩陣鍵盤的S2和S3連線問題,使按下它們兩個鍵時,實現功能相同,二、軟件方面,可能是定義該功能時,重復使用了該鍵。沿著這兩個思路,我們首先將老師給的例程燒錄進去,該例程實現的功能就是按下不同的鍵,數碼管將會顯示不同的數字,當我們分別按下S2和S3時,出現的數字不同,那么證明硬件方面沒問題。然后查了一遍程序,果然是編寫程序時,重復使用了該鍵。 分析:可能原因一、S8鍵可能出現故障了,二,編寫程序時,比分交換的那段代碼邏輯結構出錯。因為已經檢測過矩陣鍵盤的所有按鍵,都是好的,那么只能時軟件方面出錯。最后發現果然是t=a1,a1=a2,a2==t這個邏輯關系順序寫錯了。 4.2籃球計分器時間測試4.2.1相關功能鍵的測試- 按下S13鍵控制比分切換到時間(2)按下S11鍵控制時間切換到比分(3)按下S12鍵為增加節數(4)按下S21鍵為減少節數。
如圖4.2所示,當前時間顯示為第一節還剩9分42秒。 圖4.2籃球計分器時間測試圖 4.2.2出現的問題與分析- 按下S13鍵比分切換到時間時,再次按時,卻無法將時間切換比分
分析:首先這種情況不可能是硬件問題,因為 S13鍵按下后能有反應,那么只能是程序問題。后面經過多次分析程序,發現還是自己程序結構問題,因為定義了兩種情況,f==0和f==1,從而實現比分和時間切換,用兩個鍵簡單快捷。當按下某一鍵只能實現f==0或f==1,所以需要兩個鍵。 分析:因為按照算數邏輯,節數一直減總會減到小于零,而數碼管無法顯示小于零的數,所以它只能是邏輯上存在而無法顯示,當我們按下S12鍵使節數加時,一直加到大于零時,它又將重新顯示出來。
參考文獻- 張建勛編著. C語言程序設計教程. 北京:清華大學出版社,2008.
- 曾屹、劉輝編著. 單片機原理及應用. 中南大學出版社,2009
心得體會剛選這個題目,我以為很簡單到網上一搜就有,誰知道自己真正做起來才知道這個課題要實現的功能很多,在網上找了好多類似的但都用不了,不是編譯錯誤就是功能太復雜不會改。這個星期由于是考試周的原因,對于這個課題我一心就想早點把它搞好,以后的時間好復習。但是和伙伴早晚一直待在實驗室連續做了4天還是沒有很大的進展,剛開始的時候用的是數碼管切換顯示時間和日期,但是考慮到還要加4個鬧鐘和倒計時、顯示波形等功能,我們改用了LCD12864來顯示這些東西,本來想把兩個結合起來,但一直搞不好,第三天的時候將時間和日期顯示到了液晶屏上,接下來我們想辦法設計程序來調節從DS1302讀出來的時間,參考網上的程序嘗試了好幾次,卻一直沒有想要的結果,就這樣一直到了第四天驗收,雖然通過了,但離題目要求還差很遠,自己還有好多需要學習的東西,還有好多沒有理解的東西,真正在做的時候才發現自己差的并不只是一點。 雖然這次課設過程很艱難,成果也很有限,但是還是學到了許多東西,以后在接觸到類似的東西就不會還是一頭霧水,遇到問題要一步一步來,不斷取得一些進展,才能激發自己前進的動力。
程序清單:
- #include
- #include
- #define uchar unsigned char
- #define uint unsigned int
- sbit DP=P1^6;
- sbit CLK=P1^5;
- sbit RST =P1^7;
- sbit DAT_595_PIN = P1^0; //串行數據輸入
- sbit SCK_595_PIN = P1^2; //移位時鐘脈沖
- sbit RCK_595_PIN = P1^1; //輸出鎖存器控制脈沖
- uint a1=0;
- uint a2=0;
- uint t=0;
- uint ft=0;
- uint jie=1;
- uchar Year,Month,Day,Week,Hour,Minute,Sec;
- uchar code num_buf[22]= {0xf5,0x05,0xb3,0x97,0x47,0xd6,0xf6,0x85,0xf7,0xd7,
- //0 1 2 3 4 5 6 7 8 9
- 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xef,0xef,0x02,0x00};
- //0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
- Uchar code bit_buf[8] = {0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};//0xf7,0xef,0xdf,0xbf,0x7f};
- uchar data led_buf[8] = {0,0,0,20,20,0,0,0};
- unsigned int num;
- // Function Declare ********************************************************************
- void Delay(void);
- void Write_595(void);
- uchar Scan_Key(void);
- void delay(int ms)
- {
- while(ms--)
- {
- uchar i;
- for(i=0;i<250;i++)
- {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- }
- }
- void mDelay(uchar DelayTime) //延時子程序,入口參數每加1約加2us
- { while(--DelayTime);
- }
- void SendByte(uchar Command,SendDat)
- { //字節發送子程序。入口參數:命令字,數據
- uchar i;
- RST=0;CLK=0;RST=1;
- for(i=0;i<8;i++) //發送命令字
- {
- DP=Command&0x01; //取一位送數據口
- CLK=0;CLK=1; //產生一個上升沿
- Command>>=1;
- }
- for(i=0;i<8;i++) //發送數值
- {
- DP=SendDat&0x01;
- CLK=0;CLK=1;
- SendDat>>=1;
- }
- RST=0;
- }
-
- uchar ReadByte(uchar Command) //讀字節子程序。入口參數:命令字
- { //出口參數:數值
- uchar i,RecDat=0;
- RST=0;CLK=0;RST=1;
- for(i=0;i<8;i++) //發送命令字
- {
- DP=Command&0x01;
- CLK=0;CLK=1;
- Command>>=1;
- }
- for(i=0;i<8;i++) //讀入數值
- {
- CLK=1;CLK=0; //產生一個下降沿
- if(DP) RecDat|=0x01<<i; 讀入數據
- }
- RST=0;
- return(RecDat); //返回數值
- }
-
- void OscCtrl(bit CtrlDat) //振蕩起動和停止控制,入口參數1(起動)或0(停止)
- {
- if (CtrlDat) SendByte(0x80,0x00);
- else SendByte(0x80,0x80);
- }
- // Main Function
- void main(void) //主程序
- {
- uchar key_value,cnt;
- uchar i;
- OscCtrl(1);
- SendByte(0x80,0x00); //送字節
- SendByte(0x82,0x20);
- SendByte(0x84,0x13);
- SendByte(0x86,2);
- SendByte(0x88,1);
- SendByte(0x8C,11);
- while(1){
- while(ft==0)
- {
- led_buf[0] = a1/100; //左側比分的百位
- led_buf[1] = (a1%100)/10; //左側比分的十位
- led_buf[2] = a1%10; //左側比分的個位
- led_buf[3] = 20; //短橫線
- led_buf[4] = 20; //短橫線
- led_buf[5] = a2/100; //右側比分百位
- led_buf[6] = (a2%100)/10; //右側比分十位
- led_buf[7] = a2%10; //右側比分個位
- Write_595();
- key_value = Scan_Key();
- //keydown();
- //Delay();
- switch(key_value) //鍵盤掃描函數
- {
- case 0:
- break;
- case 0x88: //按第一列第一行鍵a1+1
- a1++;
- break;
- case 0x84: //按第一列第二行鍵a1-1
- a1--;
- break;
- case 0x82: //交換比分
- t=a1;
- a1=a2;
- a2=t ;
- break;
- case 0x81: // ft=1,切換比分/時間
- ft=1;
- break;
- case 0x48: //按第二列第一行鍵a2+1
- a2++;
- break;
- case 0x44: //按第二列第一行鍵a2-1
- a2--;;
- break;
- case 0x42: //clear,比分置零
- a1 = 0;
- a2 = 0;
- break;
- case 0x41: //ft=0,按第二列第四行鍵切換比分
- ft=0;
- break;
- default:
- break;
- }
- }
- while(ft==1) //當ft=1時,即定義切換成時間顯示函數
- {
- Year =ReadByte(0x8D); //讀小時
- Month =ReadByte(0x89); //讀分鐘
- Day =ReadByte(0x87); //讀秒
- Hour =ReadByte(0x85); //讀小時
- Minute=ReadByte(0x83); //讀分鐘
- Sec =ReadByte(0x81); //讀秒
- if((Minute/16*10+Minute%16)<=21) {
- led_buf[0] = 0; //0
- led_buf[1] = jie; //節
- led_buf[2] = 20; //短橫線
- led_buf[3] = 1;
- led_buf[4] = 1-Minute%16; //11分
- led_buf[5] = 20; //短橫線
- led_buf[6] = 5-Sec/16;
- led_buf[7] = 9-Sec%16; //59秒
- }
- else{
- led_buf[0] = 0; //0
- led_buf[1] = jie; //jie
- led_buf[2] = 20; //-
- led_buf[3] = 0; //0
- if(11-Minute%16<10){
- led_buf[4] = 11-Minute%16;
- }
- else{
- led_buf[4] = 1-Minute%16; //1
- }
- led_buf[5] = 20; //-
- led_buf[6] = 5-Sec/16; //5
- led_buf[7] = 9-Sec%16; //9
- }
- Write_595();
- key_value = Scan_Key();
- //keydown();
- //Delay();
- switch(key_value) //鍵盤掃描函數
- {
- case 0:
- break;
- case 0x81: // 按第一列第四行鍵 ft=1; 比分和時間轉換
- ft=1;
- break;
- case 0x41: // 按第二列第四行ft=0;時間/比分轉換
- ft=0;
- break;
- case 0x21: //按第三列第四行鍵,jie+1
- jie++;
- break;
- case 0x11:
- jie--; //按第四列第四行jie-1
- break;
- default:
- break;
- }
- }
-
-
- }
- }
- // Some Functions
- void Delay(void) //延時子程序
- {
- unsigned char m,n;
- for(m=200;m>0;m--)
- for(n=200;n>0;n--);
- }
-
- //***************************************************************************************
- //* FunctionName : Write_595() **
- //* Descriptions : write 595 **
- //* Input : led_buf[]&bit_buf[] **
- //* Output : None **
- //***************************************************************************************
- void Write_595(void) //定義595寫入函數
- {
- uchar i,j;
- uint dat;
- for(i=0;i<8;i++) //發送命令字
- {
- RCK_595_PIN=0;
- dat =bit_buf[i];
- dat =dat<<8;
- dat |= num_buf[led_buf[i]];
- for(j=0;j<16;j++)
- {
- SCK_595_PIN = 0;
- if(dat & 0x8000)
- {
- DAT_595_PIN = 1;
- }else{
- DAT_595_PIN = 0;
- }
- dat=dat<<1;
- SCK_595_PIN = 1;
- }
- RCK_595_PIN = 1;
- }
- }
- //***************************************************************************************
- //* FunctionName : Num_change() **
- //* Descriptions : Num_change **
- //* Input : **
- //* Output : None **
- //***************************************************************************************
- uchar Scan_Key(void)
- {
- uchar sm; //存放行掃描代碼,該函數的返回值的低四位
- uchar fh; //該函數的返回值的高四位
- P2 = 0xf0;
- if((P2&0xf0)!=0xf0) //判斷是否有按鍵按下
- {
- Delay(); //去抖動延時(1~10ms)
- if((P2&0xf0)!=0xf0)
- {
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼完整論文下載(word格式可編輯):
籃球計分器.doc
(920.5 KB, 下載次數: 152)
2017-4-22 14:29 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|
|