《簡易四路搶答器》
;該搶答器供不多于4個參賽隊或者個人的搶答比賽場合使用。每個參賽隊的座位前
;安裝1只搶答按鈕開關(guān)(用板上的S9、S10、S11、S12)和一個信號燈(D4、D5、D6、D7)。
;主持人座位前裝一只復原開關(guān)(板上S3)、1只蜂鳴器(板上BUZ1)和一個搶答器工作狀態(tài)
;指示燈(D10),每當主持人口頭發(fā)出號令之后.哪個隊先按下座位上的按鈕開關(guān),該座位的信
;號燈就先被點亮,同時封鎖其他按鈕開關(guān)的活動.并且熄滅主持人座位上的狀態(tài)指示燈和發(fā)出
;三聲類似于電話振鈴的提示聲,以聲明此次搶答動作已經(jīng)完成.在主持人確認后,按下復原按鈕
;,狀態(tài)指示燈重新點亮,并且同時發(fā)出"笛-笛-"聲,為下一次搶答作好準備.
;程序文件名:"MCD-INTBUZ.ASM"
;*********************************************************************
;程序清單
;*********************************************************************
tmr0 equ 1h ;定義定時器/計數(shù)器0寄存器地址
status equ 3h ;定義狀態(tài)寄存器地址
option_reg equ 81h ;定義選項寄存器地址
option_temp equ 0a6h ;(在BACK1)定義選項寄存器的備份寄存器的地址
intcon equ 0bh ;定義中斷控制寄存器地址
portc equ 7h ;定義端口RC的數(shù)據(jù)寄存器地址
trisc equ 87h ;定義端口RC的方向控制寄存器地址
portb equ 06h ;定義端口RB的數(shù)據(jù)寄存器地址
trisb equ 86h ;定義端口RB的方向控制寄存器地址
c equ 0 ;定義進位標志位的位地址
z equ 2 ;定義0標志位的位地址
w equ 0 ;定義傳送目標寄存器為W的指示位
f equ 1 ;定義傳送目標寄存器為RAM的指示位
t0if equ 2 ;定義TMR0中斷標志位的位地址
t0ie equ 5 ;定義TMR0中斷使能位的位地址
inte equ 4 ;定義外部中斷使能位的位地址
intf equ 1 ;定義外部中斷標志位的位地址
count equ 20h ;定義一個計數(shù)器變量
count1 equ 24h ;定義一個計數(shù)器變量
count2 equ 25h ;定義一個計數(shù)器變量
count3 equ 27h ;定義一個計數(shù)器變量
count4 equ 28h ;定義一個計數(shù)器變量
portb_b equ 21h ;為PORTC定義一個備份寄存器
w_temp equ 7fh ;為W在體0和體1定義2個備份寄存器
;w_temp equ 0ffh ;(若是16F873/4,則需保留FFH單元)
status_temp equ 23h ;為STATUS定義一個備份寄存器
rp0 equ 5h ;定義狀態(tài)寄存器中的頁選位RP0
;******************復位向量和中斷向量***********************
org 000h ;
nop ;設置一條ICD必須的空操作指令
goto main ;
org 0004h ;
goto serv ;跳轉(zhuǎn)到中斷服務子程序
;*******************主程序************************************
main
bsf status,rp0 ;
movlw 0 ;
movwf trisc ;設置RC口全部為輸出
movlw 0ffh ;
movwf trisb ;設置RB口全部為輸入
movlw 02h ;設置選項寄存器:上拉電阻啟用;INT下降沿觸發(fā)
movwf option_reg ;分頻器給TMR0;分頻比1:8
bcf status,rp0 ;
movlw 90h ;
movwf intcon ;開發(fā)INT中斷
clrf portc ;RC口燈全滅
loop
movf portb,w ;讀取RB口數(shù)據(jù)
iorlw b'11100001' ;送RB口的數(shù)到備份寄存器并將除S9、S10、S11、S12以外的位全部送1
movwf portb_b ;
xorlw 0ffh ;沒有鍵按下轉(zhuǎn)LOOP繼續(xù)檢測
btfsc status,z ;
goto loop ;
call delay10ms ;防抖動廷時
movf portb,w ;
iorlw b'11100001' ;
xorwf portb_b,0 ;再次讀取RB口的數(shù)據(jù),與前一次讀的數(shù)相同則鍵值有效
btfsc status,z ;
goto loop ;
comf portb_b,w ;取反以便使被按下按鍵的位為1,其它位為0
movwf portc ;送RC口顯示
call tone3t ;調(diào)用發(fā)聲三次子程序
loop1
comf portb,w ;檢測按鍵是否有松開
andlw b'00011110' ;
btfsc status,z ;
goto loop ;松開了返回
goto loop1 ;沒松開繼續(xù)檢測
;*********************中斷服務子程序*****************************
serv
;********************保存護現(xiàn)場部分*******************************
movwf w_temp ;保護W
swapf status,w ;保護STATUS
clrf status ;選擇體0
movwf status_temp ;將STATUS存入體0的備份寄存器
;********************* 調(diào)查中斷源**********************************
btfsc intcon,intf ;檢查不是INT中斷,返回
goto intserv ;是!轉(zhuǎn)到INT中斷處理部分
goto retfie0 ;
;*********************INT中斷處理部分******************************
intserv
clrf portc ;令全部燈熄滅
bsf portc,7 ;點亮D10,表示就緒
call tone630 ;調(diào)用高音子程序
call delay ;調(diào)用1S廷時子程序
call tone630 ;調(diào)用低音子程序
bcf intcon,intf ;清除INT中斷標志位
;*************************恢復現(xiàn)場部分*****************************
retfie0
swapf status_temp,w ;恢復STATUS
movwf status ;
swapf w_temp,f ;恢復W
swapf w_temp,w ;
retfie ;中斷返加
;*************************低音調(diào)發(fā)生子程序(500HZ/50MS)*************
tone500
movlw .50 ;循環(huán)次數(shù)寄存器賦初值
movwf count ;50=500HZx0.05Sx2
t5lop
bcf intcon,t0if ;清除TRM0溢出中斷標志位
movlw .131 ;給TMR0裝入初值256-125=131
movwf tmr0 ;啟動定時器
t5here
btfss intcon,t0if ;定時器溢出否
goto t5here ;否!循環(huán)栓測
movlw b'01000000' ;只將BIT6置位
xorwf portc,f ;只將RC6(BUZ)腳電平反轉(zhuǎn),其余不變
decfsz count,f ;循環(huán)次數(shù)遞減,為0,跳一步
goto t5lop ;不為0,跳回
return ;返回
;**************************高音調(diào)發(fā)生子程序(630HZ/50MS)*****************
tone630
movlw .63 ;循環(huán)次數(shù)寄存器賦初值
movwf count1 ;63=630HZx0.05Sx2
t6lop
bcf intcon,t0if ;清除TRM0溢出中斷標志位
movlw .157 ;給TMR0裝入初值157=256-99
movwf tmr0 ;啟動定時器
t6here
btfss intcon,t0if ;定時器溢出否
goto t6here ;否!循環(huán)栓測
movlw b'01000000' ;只將BIT6置位
xorwf portc,f ;只將RC6(BUZ)腳電平反轉(zhuǎn),其余不變
decfsz count1,f ;循環(huán)次數(shù)遞減,為0,跳一步
goto t6lop ;不為0,跳回
return ;返回
;*********************發(fā)聲1S子程序(1S=10x(50ms+50ms)***********
tonels
movlw .10 ;循環(huán)次數(shù)寄存器賦初值
movwf count2 ;
t1lop
call tone500 ;調(diào)用低音子程序
call tone630 ;調(diào)用高音子程序
decfsz count2,f ;循環(huán)次數(shù)遞減,為0,跳一步
goto t1lop ;不為0,跳回
return ;返回
;*********************TMR0廷時子程序1S(1S=16x256x(256-12)US)********
delay
bsf status,rp0 ;設置文件寄存器體1
movf option_reg,w ;保護選項寄存器內(nèi)容
movwf option_temp ;
movlw 07h ;重設選項寄存器;上拉電阻啟用,INT下降沿觸發(fā)
movwf option_reg ;分頻器給TRM0;分頻比值設為1:256
bcf status,rp0 ;恢復到文件寄存器體0
movlw .16 ;循環(huán)利用TMROP定時16次
movwf count3 ;溢出次數(shù)寄存器
d1lop
bcf intcon,t0if ;清除TMR0溢出中斷標志位
bcf intcon,t0ie ;清除TMR0溢出中斷使能位
movlw .12 ;給TMR0裝入初值12=256-244
movwf tmr0 ;啟動定時器
here
btfss intcon,t0if ;用查詢法檢測TMR0溢出否
goto here ;否!返回
decfsz count3,f ;是!溢出次數(shù)減1,為0,跳一步
goto d1lop ;否!循環(huán)利用TMR0
bsf status,rp0 ;設置文件寄存器體1
movf option_temp,w ;恢復選項寄存器內(nèi)容
movwf option_reg ;
bcf status,rp0 ;恢復到文件寄存器體0
return ;返回
;*************************斷續(xù)發(fā)聲3次報警子程序***********************
tone3t
movlw .3 ;循環(huán)次數(shù)寄存器賦初值
movwf count4 ;
t3lop
call tonels ;調(diào)用發(fā)聲1S子程序
call delay ;調(diào)用廷時1S子程序
decfsz count4,f ;循環(huán)次數(shù)遞減,為0,跳一步
goto t3lop ;不為0,跳回
return ;返回
;**************************軟件廷時10MS子程序****************************
delay10ms
movlw .13 ;將外層循環(huán)參數(shù)值送到30H
movwf 30h ;
lp0
movlw 0ffh ;將內(nèi)層循環(huán)參數(shù)值送到31H
movwf 31h ;
lp1
decfsz 31h,1 ;變量31H內(nèi)容遞減,若為0則跳躍
goto lp1 ;跳轉(zhuǎn)到LP1
decfsz 30h,1 ;變量30H內(nèi)容遞減,若為0則跳躍
goto lp0 ;跳轉(zhuǎn)到LP0
return ;返回主程序
end ;源程序結(jié)束
;***************************************************
; 進入該實戰(zhàn)演練的工序流程如下:
; 1.創(chuàng)建源文件和編輯源文件;在此介紹一種不同于前面講的創(chuàng)建源文件的方法,用Windows附件中的”記事本”
; 這個為大家所熟知和好用的文件編輯器,并且可以方便的加入中文注釋.不過有兩點需要注意,一是注釋前面的
; 分號”;”必須用西文半角輸入;二是必須用”.asm”擴展名存儲到事先建立的一個專用子目錄下.
; 2.打開MPLAB集成開發(fā)環(huán)境:首先在WINDOWS環(huán)境下,選用開始>程序>Microchip MPLAB>MPLAB命令,啟動MPLAB
; 并進入MPLAB的桌面.
; 3.創(chuàng)建項目:選用菜單File>New或Project>New Project,在事先建立的一個專用子目錄下創(chuàng)建一個新項目,將
; 用記事本創(chuàng)建的源文件加入到該項目中.
; 4.建立項目中的目標文件:選擇菜單Project >Build All(項目>建立所有文件),MPLAB將自動調(diào)用MPASM將項目
; 文件管理下的源文件(.asm)匯編成十六進制的目標文件(.hex).
; 5.ICD參數(shù)設置:通過菜單命令Project>Edit Project或者Option>Development Mode,將開發(fā)模式設置為
; ”MPLAB ICD Debugger”,點擊OK按鈕,打開ICD的工作窗口,在調(diào)試階段,可以按照說明書圖2-10設置各項,但需注意
; OSCILLATOR應設置為XT方式,尤其需要說明的是,選中“Enable Debug Mode”(使能調(diào)試模式)選項,在向目
; 標單片機燒寫機器碼程序時,會將調(diào)試臨控程序同時寫入單片機的指定程序存儲器區(qū)域,然后才允許用ICD方式調(diào)試。
; 6.電路設置:將演示板的S1全部拔到ON,S4全部拔到OFF,S13的第1、第5拔到ON,第6、第7拔到OFF ,LCD不要插在演示板上,
; 以使端口C只與8只發(fā)光二極管接通;將用于選擇頻率的插針跳線插到”XT OSC”位置上,板上93CXX、24CXX應拿下。
; 7.向目標單片機燒寫目標程序:用戶在點擊功能按鈕”Program”向目標單片機燒寫機器碼程序時,會等待一段時間,
; 并且在條狀的狀態(tài)信息欄中,出現(xiàn)提示信息。有一點需要引起注意,就是PIC16F87X單片機的FLASH程序存儲器的擦寫
; 周期是有限的,大約為1000次,應盡量節(jié)省它的使用壽命。
; 8.運行和調(diào)試用戶程序和用戶電路:在各項參數(shù)設置好后,將ICD的工作窗口最小化,利用前面講的”運行及調(diào)試”中介
; 紹的幾種方法進行調(diào)試.當用自動單步方式調(diào)試時,建議臨時禁止廷時子程序發(fā)揮作用,具體的方法是,可在CALL DELAY指
; 令前添加一個分號,并且重新匯編一次.為了學習目的,在調(diào)試過程中可以人為地加入一些軟件漏洞(BUG)或硬件故障,來模
; 仿單片機端口引腳的片內(nèi)或片外故障.
; 9.定型燒寫目標單片機;經(jīng)過多次重復上述步驟的反復修改和調(diào)試,使得程序和電路在聯(lián)機狀態(tài)完全正常,這時可以進行
; 定型燒寫,即將ICD窗口中的”Enable Debug Mode”(使能調(diào)試模式)選項消除,不再將調(diào)試臨控程序?qū)懭雴纹瑱C中.
; 10.獨立運行驗收:上一步中的燒寫過程完成后,即可將ICD模塊和ICD仿真頭(或演示板)之間的6芯電纜斷開,讓單片機在
; 演示板獨立運行,觀察實際效果.
;
;