![]() |
發(fā)布時間: 2023-11-12 17:22
正文摘要:多功能秒表系統(tǒng)設(shè)計 設(shè)計要求: (1)兩位LED顯示,顯示時間為00~99秒。 (2)具有開始、暫停、復(fù)位功能。 (3)在秒表工作過程中能通過按鍵多次(不少于4次)記錄當前的時間。 (4)可以通過按鈕查看記錄的 ... |
鵜鶘 發(fā)表于 2023-11-17 15:27 試了,符合我想的功能 |
呵呵你試沒試,結(jié)果怎樣?你是不是這個意思,達沒達到目的? 另外,我的那個中斷程序中前半部分不甚合理,應(yīng)該把對stp_run的判斷放在最外層,還有就是count和miao的+1都沒不要單獨存在,都可以合并到條件判斷中,這樣程序就更簡潔清晰,也更符合C風(fēng)范: void time0() interrupt 1 { static bit dp; TH0=(65536-10000)/256; TL0=(65536-10000)%256; P0=0x00; //xiao timer++; if (stp_run) { if(++count==100) { count=0; if (++miao==100) { miao=0; } } } if (dp=~dp) { P0=table[c]; w0=0,w1=1; } else { P0=table[d]; w1=0,w0=1; } } |
鵜鶘 發(fā)表于 2023-11-15 21:30 太牛了,大佬 |
原理更重要吧,清楚了原理怎樣做是很自由的,我先把原理說下,一個修改方案提供給你,你也不必照搬的,可隨意修改試驗。 這種LED數(shù)碼管的直接驅(qū)動都是以掃描方式實現(xiàn)的,且掃描的頻率要穩(wěn)定不受其他程序部分的干擾,你的程序之所以僅在秒表時看起來正常,是因為它就是在快速重復(fù)掃描,但你這種掃描太易受到干擾而停頓,即在主函數(shù)的while中循環(huán),當你不按按鍵或只按s1-s3時,scankeys可以快速返回,顯示會連續(xù),但按下s4或者s5我上面那貼說過因為延遲和判斷是否抬起它就會延遲返回或者按著不放它就不返回,顯示就不正常。 所以這種數(shù)碼管的顯示一般都是分兩個部分,驅(qū)動和賦值是分開的,驅(qū)動部分只是將顯示緩沖區(qū)的內(nèi)容依次輪換送數(shù)碼管顯示,而向顯示緩沖區(qū)賦值是另一部分,可以在程序的任何地方、任何時候執(zhí)行(在這里顯示緩沖區(qū)就是c、d兩個無符號字符變量)。驅(qū)動部分又必須等頻率不斷重復(fù)執(zhí)行,這樣數(shù)碼管才會看起來常亮且不受干擾而停頓,要做到這點驅(qū)動部分就只能放在計時器的中斷程序里,這樣,你的display函數(shù)就要修改,把它分成兩部分,計算和賦值部分(實際只有兩句)留下,其余都移到中斷程序中。 但這還不夠,引起這個中斷的是計時器,而你啟停秒表是靠啟停這個計時器實現(xiàn)的,這又不行,因為計時器一停中斷就消失,數(shù)碼管沒了驅(qū)動就立即不亮了,所以這個也要改,計時器只要一上電初始化后就必須立即工作直到斷電,這樣才能使顯示驅(qū)動不停地等間隔刷新數(shù)碼管,并且頻率要足夠高以使眼睛覺察不出閃爍。這又引來了一個問題,看你的程序參數(shù),你用的是12兆的晶振,計時器0,模式1,中斷頻率是20Hz,作為秒表用,這個沒問題,但兼作顯示驅(qū)動頻率太低,數(shù)碼管肯定會閃,,,所以兼顧編程方便和人眼的視覺暫留特性,這個頻率應(yīng)該提高到100Hz,為此 timedr0init 函數(shù)中的50000應(yīng)改成10000,對應(yīng)的,中斷函數(shù)中的 if(count==20)改成 if(count==100),即每100次中斷為一秒到。由于計時器一上電初始化后就要立即工作,所以這個函數(shù)中的另一處TR0=0;要改成TR0=1;。既然TR0不能再=0了,那么啟停秒表就用更常規(guī)的辦法:設(shè)置一個全局的標志位,比如Bit Stop_run,加在程序頭部的說明區(qū)中;而且作為顯示緩沖區(qū)的變量c、d也要全局化,因為主函數(shù)要向它賦值,中斷函數(shù)也要用到它,為此將他倆的定義從display函數(shù)中取出也放置在此處。啟停秒表就靠標志位Stop_run被置1/清零來實現(xiàn),置1表示秒表啟動;清零表示暫停/停止,反過來當然也可以,,,相應(yīng)的中斷程序中miao++;和下面的兩句改為: if (Stop_run) { miao++; if(miao==100) miao=0; } 如果Stop_run的01定義與此相反的話前面加個非號就行了。Stop_run的置1/清零就用你的scankeys函數(shù)中的s1-s3處理語句來執(zhí)行,將TR0=0或1改成相應(yīng)的Stop_run=0或1。 另外,你也沒說你想達到什么目的,秒表就不用說了,主要是回顯那幾個記錄值用什么方式、要達到什么效果,根據(jù)你貼出的程序看,你大概想以這樣的方式回顯:按下s5健,就立即在數(shù)碼管上依次顯示所有記錄值,每個記錄值顯示的時間由delay(100);控制。你的display函數(shù)在scankeys函數(shù)中的這種用法根本達不到目的,且邏輯還很混亂,并且delay函數(shù)的性能究竟怎樣,delay(100)究竟能延時多長時間這都不知道,直覺看它遠不會達到1秒,如果你真想用這種方式回顯,那么每個記錄值顯示的時間怎么也應(yīng)該超過1秒吧。 根據(jù)這些條件我給你提供一個修改方案供你參考: 在變量聲明區(qū)后面再附加兩句: bit stp_run=0; uchar c,d,timer; 函數(shù)timedr0init改為: void timedr0init() { TMOD=0x01; TH0=(65536-10000)/256; TL0=(65536-10000)%256; TR0=1; ET0=1; EA=1; } 增加一個延時函數(shù): void wait(unsigned char t)//t單位為10ms,當t=200時,即延時2秒。 { timer=0; while (timer<t); } 函數(shù)display改為: void display(uchar n) { c=n/10; d=n%10; } 函數(shù)scankey改為: void scankeys() {static bit recordFlag = 0; //聲明了一個靜態(tài)的位變量 recordFlag,并將其初始化為 0 static unsigned char recordIndex = 0;//靜態(tài)無字符變量 if(s1==0)//啟動 { stp_run=1; } if(s2==0)//暫停 { stp_run=0; } if(s3==0)//清零 { stp_run=miao=count=0; } if (s4 == 0) { // 記錄 if (!recordFlag && recordIndex < 4) { recordFlag = 1; recordTimes[recordIndex++] = miao; while (s4 == 0); delay(100); // 等待按鍵釋放,防止重復(fù)記錄 } } else { recordFlag = 0; } if (s5 == 0) { // 查看記錄 if (recordIndex > 0) { uchar i; for (i = 0; i < recordIndex; i++) { display(recordTimes[ i]); wait(150); //延時1.5秒,即每個數(shù)字顯示1.5秒。 } } } } 中斷程序改動比較大,但大部分代碼可以復(fù)制/粘貼過來: void time0() interrupt 1 { static bit dp; TH0=(65536-10000)/256; TL0=(65536-10000)%256; P0=0x00; //xiao timer++; count++; if(count==100) { count=0; if (stp_run) { miao++; if (miao==100) miao=0; } } if (dp=~dp) { P0=table[c]; w0=0,w1=1; } else { P0=table[d]; w1=0,w0=1; } } 未提及的,就保留原文。 |
參與人數(shù) 1 | 黑幣 +100 | 收起 理由 |
---|---|---|
![]() | + 100 | 回帖助人的獎勵! |
1556544 發(fā)表于 2023-11-14 21:19 上面呢位大佬講的二維數(shù)組沒有聽說過,剛學(xué)得新手 ![]() |
鵜鶘 發(fā)表于 2023-11-14 11:19 大佬,可以幫忙修改一下嗎,新手不是特別懂 |
他已經(jīng)建立數(shù)組了,只是沒必要二維吧,序號就可以作為記錄的數(shù)據(jù)是第幾個。問題是他這個程序?qū)嵲谑翘銖娏,直接?qū)動數(shù)碼管不是這種方法,他的 display 函數(shù)這樣寫是不對的,只能在不按S4和S5的情況下正常,但也只是看似正常,這就是我說的“勉強”的意思,當按下S4或S5時,在按下的這段時間里有一個數(shù)碼管會滅,而亮的那個數(shù)碼管會保持,不會變化,尤其是S4,只要不抬起來一直保持這樣不變,這恐怕并不是你需要的功能吧,按下S5鍵情況就更復(fù)雜了,按下不動基本上是亂顯示,這取決于你的delay函數(shù),delay(100)究竟會延遲多長時間,如果時間很短,那就是亂顯示,如果時間很長比如超過0.5秒,會看到兩個數(shù)碼管閃亮幾次,次數(shù)由記錄的次數(shù)決定,最多4次,閃亮的時間很短由display函數(shù)中的delay(5);決定,基本也看不清,如果按著S5不放就是這個過程反復(fù)循環(huán)。 由這個分析能夠猜出你的用意,想的是挺美,但這個程序做不到,僅僅是秒表勉強能用。要修改的話,量也不是很大,但框架就變了。。。 |
本帖最后由 yzwzfyz 于 2023-11-15 09:36 編輯 1、建立一個二維數(shù)組【P,2】,P記錄你歷史上記錄的秒表數(shù)據(jù)是第幾個。2秒表讀數(shù)0-99。 2、建立三個指針P1\P2\P3:P1=當前的秒表P號,P2=【記錄】按鍵指向的P號,P3=【查詢】按鍵指向的P號。 3、顯示程序,只從【P1,2】取數(shù)字顯示,也即只顯示P1所指向的數(shù)據(jù)。 鍵操作: 1、按下【記錄】鍵:P2=P2+1(表示進行到第幾個記錄了),P1=P2(顯示指向新的P2記錄)。 2、按下【查詢】鍵:P3=P3+1(表示查詢到第幾個記錄了),P1=P3(對查詢到的記錄進行顯示)。 3、按下【開始、清0、暫定】鍵:加一條 P1 = P2 (顯示改為【記錄】所指定的記錄號,并在此記錄上進行操作,這樣保證【查詢】后,能回到之前的記錄號,不致混亂),其它操作與你的定義相同。 如此: 能讓你記錄到P組秒表數(shù)據(jù)(循環(huán)使用1-P),做到P組數(shù)據(jù)互不干擾,可查可詢,且查詢不影響當前的操作,甚至在讀秒時查詢也不影響當前的秒表計秒工作。 |
建產(chǎn)數(shù)組存儲數(shù)據(jù),再修改按鍵程序,上下翻看 |
wulin 發(fā)表于 2023-11-12 20:12 求大佬指導(dǎo),純萌新 |
wulin 發(fā)表于 2023-11-12 20:12 if (s4 == 0) { // 記錄 if (!recordFlag && recordIndex < 4) { recordFlag = 1; // 將記錄后移 for ( i = 3; i > 0; i--) { recordTimes[ i] = recordTimes[i-1]; } // 記錄當前時間 recordTimes[0] = miao; while (s4 == 0); delay(100); // 等待按鍵釋放,防止重復(fù)記錄 } } else { recordFlag = 0; } |
wulin 發(fā)表于 2023-11-12 20:12 大佬,程序添加在哪里,求指導(dǎo),純新手,不是特別熟練 |
按下記錄鍵,緩存recordTimes[3]=recordTimes[2];recordTimes[2]=recordTimes[1];recordTimes[1]=recordTimes[0];全部后移,再將當前秒數(shù)存在recordTimes[0]。始終保存最近4次的記錄 |
Powered by 單片機教程網(wǎng)