|
技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
菜鳥學(xué)PIC單片機(jī)(二):LCD 時(shí)鐘 (功能設(shè)計(jì)過(guò)程中的致命bug) |
作者:碧水長(zhǎng)天 欄目:單片機(jī) |
結(jié)合昨天LCM的驅(qū)動(dòng)編寫過(guò)程,小弟今天準(zhǔn)備利用定時(shí)器用LCM來(lái)顯示時(shí)鐘. 呵呵,下午邊調(diào)變改,有些收獲和疑問(wèn),現(xiàn)一并寫出來(lái),請(qǐng)行家指點(diǎn). 功能很明確:利用TMR0實(shí)現(xiàn)精確定時(shí),_clock子程序更新時(shí)間,LCM顯示時(shí)間 但是,遇到了一些問(wèn)題: 1.在ICD和DEMO板上調(diào)試運(yùn)行,結(jié)果顯示應(yīng)為 HH MM SS 00:00:00 且ss對(duì)應(yīng)下的秒?yún)^(qū)字符應(yīng)該每1秒改變一次.但是,運(yùn)行的結(jié)果如下: 1) 參考本例的源程序,其他一切不變,只是預(yù)分頻為1:8(原來(lái)設(shè)計(jì)為1:16) 那么,應(yīng)該是每0.5秒變化一次,但是據(jù)小弟多次觀察,運(yùn)行的時(shí)候,SS的秒?yún)^(qū) 為每分鐘(人工大概估計(jì))計(jì)數(shù)一次,及秒表變成了分表,另外,在每分鐘里,SS區(qū)的字符會(huì)有2到3次調(diào)變 比如0x(x為當(dāng)前計(jì)數(shù)顯示值)變成24,一晃而過(guò),又恢復(fù)顯示0x. (a)小弟仔細(xì)檢查定時(shí),轉(zhuǎn)換,顯示的程序流程,沒(méi)有發(fā)現(xiàn)為何沒(méi)半秒顯示計(jì)數(shù)變成了每分鐘顯示計(jì)數(shù)的原因; (b)至于SS秒?yún)^(qū)的字符會(huì)跳變,小弟認(rèn)為可能是LCM的控制問(wèn)題. 2. 在主程序main中,loop循環(huán)中的第一條指令clrwdt會(huì)引起一些問(wèn)題: main nop call _init ; 調(diào)用初始化子程序 call _disp1 ; 調(diào)用顯示字符" HH MM SS "的子程序 loop clrwdt ; ★★★注意!!該語(yǔ)句的功能,小弟很疑惑 call _clock ; 調(diào)用時(shí)鐘計(jì)算子程序 call _convert ; 調(diào)用時(shí)鐘的小時(shí),分,秒的BCD碼轉(zhuǎn)換子程序 call _disp2 ; 調(diào)用轉(zhuǎn)換后的小時(shí):分:秒字符的顯示子程序 goto loop 所引起的問(wèn)題如下: 1)首先,我在ICD燒錄時(shí),在option選項(xiàng)中是關(guān)掉WDT的; 2)若去掉該語(yǔ)句,程序仍然同前文1.所描述的情況,唯一變化的是,時(shí)間顯示區(qū)的字符跳變 從SS區(qū)換成HH區(qū),即小時(shí)區(qū)下的00會(huì)在分鐘之內(nèi),好幾次跳變成52. 3)以為是偶然,于是禁用和啟用該語(yǔ)句兩次,現(xiàn)象沒(méi)變. 小弟認(rèn)為,既然分頻器給了TMR0,燒錄時(shí)也關(guān)了WDT,那么,該語(yǔ)句所起的作用是什么呢? 3. 其實(shí)該程序存在一個(gè)致命的問(wèn)題,吃晚飯時(shí),小弟想到了癥結(jié)所在. 呵呵,小弟先不點(diǎn)出來(lái),愿意和大家一起商討解決的好辦法...... 請(qǐng)各位PIC單片機(jī)愛(ài)好者看過(guò)來(lái)... 解決辦法1: 解決辦法2: 解決辦法3: 源程序和注釋請(qǐng)見(jiàn)下帖: * - 本貼最后修改時(shí)間:2004-11-25 19:43:35 修改者:碧水長(zhǎng)天 |
2樓: | >>參與討論 |
作者: 碧水長(zhǎng)天 于 2004/11/25 19:20:00 發(fā)布:
完整的源程序 ;********************************************************************** ; ; Filename:time0.asm ; Date:11-15-2004 ; File Version: V1.0 ; ; Author: Liyu ; Company: 614 ; ; ;********************************************************************** ; ; Files required: ; ; ; ;********************************************************************** ; ; Notes: ; ; ; ; ;********************************************************************** list p=16F877 ; list directive to define processor #include <p16F877.inc> ; processor specific variable definitions ;__CONFIG _CP_OFF & _WDT_ON & _BODEN_ON & _PWRTE_ON & _RC_OSC & _WRT_ENABLE_ON & _LVP_ON & _DEBUG_OFF & _CPD_OFF ; '__CONFIG' directive is used to embed configuration data within .asm file. ; The lables following the directive are located in the respective .inc file. ; See respective data sheet for additional information on configuration word. ;meanings:_CP_OFF,Code_Protect Off;_WDT_ON,WatchDog On;_BOOEN_ON, ;_PWRTE_ON,Power_On delay timer On;_RC_OSC,RC OSC surge; ;***** 變量定義 w_temp EQU 0x20 ; variable used for context saving status_temp EQU 0x21 ; variable used for context saving pclath_temp EQU 0x22 fsr_temp EQU 0x23 RS EQU 1 RW EQU 2 E EQU 3 ;************************** cblock 0x70 hour ; 定義小時(shí)變量 min ; 定義分鐘變量 sec ; 定義秒變量 MS50 ; 定義50ms變量 us :2 ; 定義微秒變量 count ; 定義計(jì)數(shù)器變量(查字符表用) tmp1 ; 定義臨時(shí)變量,顯示字符用 x ; 延時(shí)計(jì)數(shù)器變量 y ; 延時(shí)計(jì)數(shù)器變量 bin ; BCD碼轉(zhuǎn)換前的二進(jìn)制寄存器 bcd_h ; BCD碼轉(zhuǎn)換后的高位 bcd_l ; BCD碼轉(zhuǎn)換后的低位 count1 ; 計(jì)數(shù)器 endc ;*********時(shí)鐘顯示緩沖區(qū)變量定義 cblock 0x24 ; 定義LCM待顯示的時(shí)間字符緩沖區(qū) space1 space2 space3 space4 ; 前面四個(gè)空格 hour_h ; xx小時(shí)的第一個(gè)字符變量 hour_l ; xx小時(shí)的第二個(gè)字符變量 colon1 ; 冒號(hào)":" min_h ; xx分鐘的第一個(gè)字符變量 min_l ; xx分鐘的第二個(gè)字符變量 colon2 ; 冒號(hào)":" sec_h ; xx秒的第一個(gè)字符變量 sec_l ; xx秒的第二個(gè)字符變量 space5 ; 后面四個(gè)空格 space6 space7 space8 endc ;*******************************************************************888 ORG 0x000 ; processor reset vector nop ; ICD need goto main ; go to beginning of program ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf PCLATH,w movwf pclath_temp movf FSR,w movwf fsr_temp ; 保護(hù)現(xiàn)場(chǎng)(此處恢復(fù)現(xiàn)場(chǎng)時(shí),應(yīng)將W最后從w_temp中恢復(fù),謝版的提醒) ;********TMR0中斷服務(wù)代碼 btfss INTCON,T0IE ; 判斷是否為T0中斷 goto other_int btfss INTCON,T0IF ; T0是否溢出 goto other_int bcf INTCON,T0IF ; 是T0中斷,清除中斷標(biāo)志 movlw&nbs |
3樓: | >>參與討論 |
作者: 碧水長(zhǎng)天 于 2004/11/25 19:41:00 發(fā)布:
謝謝 為了方便大家批閱,源程序小弟在記事本中排版得非常整齊,然后copy過(guò)來(lái),結(jié)果排版好象有點(diǎn)變了...請(qǐng)見(jiàn)諒. 小弟也知道,讀程序,看電路圖是件很枯燥也很乏味的過(guò)程,所以,小弟盡量多加注釋,以利于和我差不多的初學(xué)者閱讀... 小弟學(xué)PIC不長(zhǎng),很多地方仍然弄不清楚,<<菜鳥學(xué)PIC單片機(jī)>>系列是我竭盡全力在工作之余(當(dāng)然,工作不太忙,小弟原為機(jī)械電子工程專業(yè))自學(xué)過(guò)程中的感想和疑問(wèn),費(fèi)盡心思,寫在這里最大的愿望是渴望得到行家的指點(diǎn),并和PIC單片機(jī)愛(ài)好者和初學(xué)者一起進(jìn)步. 小弟對(duì)所有關(guān)注偶的帖子的站友表示忠心的感謝,對(duì)那些指點(diǎn)小弟的先輩更是感激涕零... 小弟將繼續(xù)把自學(xué)過(guò)程的感想和收獲給帖出來(lái). 再次希望能得到大家的理解和支援,尤其是新老斑竹,還有hotpower,十步殺一人,cf100,笑蒼天,su_mj000,highend,wwllzz,skyer,BLACKHILL,time2,sosomj等等這些小弟無(wú)限敬仰的俠客高人,你們都到哪里去了啊..... |
4樓: | >>參與討論 |
作者: xieyuanbin 于 2004/11/26 7:50:00 發(fā)布:
大約看了一下, 中斷保護(hù)和中斷恢復(fù)的順序和方法都錯(cuò)了. |
5樓: | >>參與討論 |
作者: 碧水長(zhǎng)天 于 2004/11/26 12:39:00 發(fā)布:
謝謝斑竹的關(guān)注 謝謝您的啟發(fā),我來(lái)分析一下程序中的“中斷保護(hù)與恢復(fù)”是否錯(cuò)。 ORG 0x004 ; interrupt vector location movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf PCLATH,w movwf pclath_temp movf FSR,w movwf fsr_temp ; 保護(hù)現(xiàn)場(chǎng) ;保存W到w_temp中去 ;STATUS通過(guò)w保存到status_temp中去 ;PCLATH通過(guò)w保存到pclath_temp中去 ;FSR通過(guò)w保存到fsr_temp中去 ;這里好象沒(méi)有錯(cuò). ; return from interrupt end_int ; 恢復(fù)現(xiàn)場(chǎng) movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents movf pclath_temp,W movwf PCLATH movf fsr_temp,W movwf FSR retfie ; 恩,這里有錯(cuò)了,斑竹提醒得對(duì)... ; W寄存器應(yīng)該最后恢復(fù),因?yàn)榛謴?fù)PCLATH,FSR都要用到W... ; 謝謝謝版,由于程序模板中保存現(xiàn)場(chǎng)時(shí)只考慮了W和STATUS,所以,我在添加保存和恢復(fù)FSR,PCLATH時(shí),沒(méi)有留意其恢復(fù)的先后次序... 真的很謝謝斑竹的指點(diǎn).... 按下面改變應(yīng)該沒(méi)錯(cuò)... end_int ; 恢復(fù)現(xiàn)場(chǎng) movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents movf pclath_temp,W movwf PCLATH movf fsr_temp,W movwf FSR swapf w_temp,f swapf w_temp,w ; restore pre-isr W register contents retfie |
6樓: | >>參與討論 |
作者: xieyuanbin 于 2004/11/26 17:38:00 發(fā)布:
還不行. |
7樓: | >>參與討論 |
作者: xieyuanbin 于 2004/11/26 17:48:00 發(fā)布:
還不行. 次序還是錯(cuò)了. 你要知道MOVF這個(gè)指令會(huì)影響STATUS的Z位,所以會(huì)有后面的兩個(gè)SWAPF的指令來(lái)恢復(fù)W寄存器.仔細(xì)揣摩一下SWAPF指令的含義. 無(wú)論在什么情況下中斷保護(hù)中第一是保護(hù)W,然后保護(hù)STATUS.然后再保護(hù)其它...恢復(fù)的順序相反,最后恢復(fù)W,之前是恢復(fù)STATUS.STATUS會(huì)影響到許多運(yùn)算的結(jié)果,還有寄存器的頁(yè)面等也由STATUS來(lái)決定. |
8樓: | >>參與討論 |
作者: 碧水長(zhǎng)天 于 2004/11/26 18:17:00 發(fā)布:
恩..謝謝... 下午上班時(shí)小弟發(fā)現(xiàn)w_temp等變量不是定義在70H后的快速存取區(qū),因此,斑竹說(shuō)得對(duì),這樣保存和恢復(fù)現(xiàn)場(chǎng)還是存在問(wèn)題... 今天下午通過(guò)調(diào)試,又發(fā)現(xiàn)了更多的問(wèn)題... 仍然請(qǐng)斑竹和各位大哥關(guān)注 |
9樓: | >>參與討論 |
作者: xieyuanbin 于 2004/11/27 19:21:00 發(fā)布:
其實(shí) W_TEMP定義在哪個(gè)區(qū)塊并不重要,只是定義了W_TEMP之后,在其它區(qū)塊的同一個(gè)位置不得定義其它變量,這樣才能保證中斷保護(hù)的正常執(zhí)行.其中的原因是在寄存器直接尋址時(shí),其地址只有低7位有效. |
免費(fèi)注冊(cè)為維庫(kù)電子開發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 www.udpf.com.cn 浙ICP證030469號(hào) |