利用INT0和計時器0做轉數計算 |
答題得分者是:阿信
|
cheng07
一般會員 發表:8 回覆:12 積分:4 註冊:2005-05-09 發送簡訊給我 |
這是我畢業專題要做的東西
構想是以風力驅動風扇,帶動光柵使光遮斷器產生方波,再將方波送到INT0,計時器0計時1秒後,將總方波數除以光柵數,乘以60轉換成轉速RPM,再送到20*2的LCD上顯示。如果允許的話再將轉速轉換成風速一起顯示在LCD上。
程式的寫法是將中斷副程式作對A+1的動作來做計數,目前卡到的問題是A計數的值是2進位還是16進位?A的值要如何做計算?還有要怎麼將計算的結果顯示在LCD特定的位置上?例如第一行第幾個字等等。 現在剩下一個月的時間可以做了,可是感覺程式怎麼樣都搞不定,所以來版上請教各位
以下附上程式碼及電路圖
ORG 0000H JMP START ORG 0003H JMP INT0 START: ACALL INIT MOV TCON,#00000001B MOV IP,#00000010B SETB EA SETB EX0 SETB ET0 ACALL TIME0 INIT: ACALL DELAY MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#08H ACALL WRINS MOV A,#01H ACALL WRINS MOV A,#06H ACALL WRINS MOV A,#0CH ACALL WRINS ACALL LINE1 MOV DPTR,#TAB1 ACALL DISPLAY ACALL LINE2 MOV DPTR,#TAB2 ACALL DISPLAY CLR A RET ; DISPLAY:MOV R7,#00H NEXT: MOV A,R7 MOVC A,@A+DPTR CJNE A,#10H,DSP RET DSP: ACALL WRDATA INC R7 AJMP NEXT INT0: INC A RETI LINE1: MOV A,#10000000B ACALL WRINS RET LINE2: MOV A,#11000000B ACALL WRINS RET WRINS: MOV P2,#00011111B ;RS=0,R/W=0,E=0 NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 ACALL DLY1 RET WRDATA: MOV P2,#10011111B ;RS=1,R/W=0,E=0 NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 ACALL DLY2 RET ; DELAY: MOV R6,#100 DL: MOV R7,#200 DJNZ R7,$ DJNZ R6,DL RET ; DLY1: MOV R6,#20 DL1: MOV R7,#200 DJNZ R7,$ DJNZ R6,DL1 RET ; DLY2: MOV R6,#80 DJNZ R6,$ RET TIME0: MOV TMOD,#00000001B MOV TH1,#0 MOV TL1,#0 MOV TCON,#01000000B DEL1S: MOV R7,#20 A2: MOV TH0,#>(65536-50000) MOV TL0,#<(65536-50000) SETB TR0 A1: JNB TF0,A1 CLR TR0 CLR TF0 DJNE R7,A2 RET ; TAB1: DB 'Speed: R.P.M' DB 10H TAB2: DB 'Wind: m/s' DB 10H END很感謝各位能把我的問題看完,小弟絞盡腦汁能寫出的程式碼就只有如上了,還望板上各位板友幫忙,謝謝! |
阿信
版主 發表:111 回覆:983 積分:813 註冊:2005-03-10 發送簡訊給我 |
你的程式還差很多的樣子
計時器都沒有設定 首先要產生1秒的計時中斷
累加器要16位元 下面是一個基本的程式架構
程式要模組化
org 0000H jmp START org 0003H jmp INT0 org 000BH jmp Timer0 ;------------------------- org 0030H Start: ;啟動 call Init Loop: ;無窮迴圈 jmp Loop ;------------------------- Init: ;初始化設定 ret ;------------------------- INT0: ;外部中斷副程式 PUSH A PUSH PSW POP PSW POP A reti ;------------------------- Timer0: ;計時中斷副程式 PUSH A PUSH PSW POP PSW POP A reti ;------------------------- |
阿信
版主 發表:111 回覆:983 積分:813 註冊:2005-03-10 發送簡訊給我 |
下面是我修改的程式
你的光柵是幾格跟RPM與風速的比例關係為何 你去找到4位數的16進制轉BCD程式
跟16位元除8位元除法程式
再把它補進去
-------------------------------- ;R3:PULSE_HIGH(脈波計數高位元組) ;R4:PULSE_LOW (脈波計數低位元組) DISP10 EQU 40H ;LCM緩衝區 第一列 DISP20 EQU 50H ;LCM緩衝區 第二列 fg_1S .REG 20H.0 ;1秒旗標 CNT_1S EQU 30H ;1秒的計數器 ;-------------------------------- ORG 0000H JMP START ORG 0003H JMP INT0 ORG 000BH JMP INT_TIMER0 ;-------------------------------- ORG 0030H START: CALL INIT LOOP: JNB fg_1S,LOOP CLR fg_1S CALL DISP_RPM JMP LOOP ;-------------------------------- INIT: ;初始化 CALL INIT_RAM CALL INIT_LCM CALL INIT_INT RET ;-------------------------------- DISP_RPM: ;設光柵為60格 則RPM=1秒脈波數*60/60格 ;RPM=(R6,R5) ;將(R6,R5)轉為4位數字顯示在LCM上 ;----- DISP_SP: ;設風速為RPM/100(M/S) CALL DISPLAY RET ;-------------------------------- INIT_RAM: ;RAM初始化 CLR A MOV R0,#7FH IR_LP: MOV @R0,A DJNZ R0,IR_LP CLR R3 CLR R4 MOV CNT_1S,#50 RET ;-------------------------------- INIT_LCM: ;LCM初始化 ACALL DELAY MOV A,#38H ;8位元 雙排 5*7 ACALL WRINS MOV A,#08H ;關閉LCD顯示 ACALL WRINS MOV A,#01H ;清除DD RAM ACALL WRINS MOV A,#06H ;寫入字元時 AC=AC 1 ACALL WRINS MOV A,#0CH ;開啟LCD顯示 游標不顯示 ACALL WRINS CALL LOAD ;載入顯示資料 CALL DISPLAY ;顯示 RET ;-------------------------------- INIT_INT: ;中斷初始化 MOV SP,#60H ;堆疊指標於60H MOV TMOD,#01H ;TIMER0為模式1 MOV IE,#10000011B ;致能主中斷,外部中斷及TIMER0中斷 MOV TH0,#>(65536-20000) ;TIMER0中斷 每20mS MOV Tl0,#<(65536-20000) MOV TCON,#00010001B ;TIMER0啟動 INT0為負緣觸發 MOV IP,#00000010B ;TIMER0為高優先權 RET ;-------------------------------- LOAD: ;載入預設字元到顯示緩衝區 MOV DPTR,#TAB1 MOV R0,#DISP10 CALL STRBUF MOV DPTR,#TAB2 MOV R0,#DISP20 CALL STRBUF RET ;-------------------------------- STRBUF: ;由DPTR載入16BYTE到R0顯示緩衝區 MOV R2,#10H STR1: CLR A MOVC A,@A DPTR MOV @R0,A INC R0 INC DPTR DJNZ R2,STR1 RET |
cheng07
一般會員 發表:8 回覆:12 積分:4 註冊:2005-05-09 發送簡訊給我 |
很謝謝阿信大大撥空幫我修改程式
我這兩天也照您的方法把程式重新改過,不知道這樣子會不會好一點
如下
ORG 0000H JMP START ORG 0003H JMP INT0 ORG 000BH JMP Timer0 ;------------------------- ORG 0030H Start: ;啟動 CALL Init ;初始化lcd ACALL LINE1 ;設定顯示第一行第一字 MOV DPTR,#TAB1 ;設定顯示 ACALL DISPLAY ;將字元碼送到lcd ACALL LINE2 ;設定顯示第二行第一字 MOV DPTR,#TAB2 ACALL DISPLAY ;將字元碼送到lcd MOV IE,#10000011 ;設定int0 timer0中段致能 MOV IP,#00000010 ;設定timer0高優先權 MOV R4,#20 ;令r4=20,以便延時50ms*20=1000ms=1杪 ACALL SETUP ;設定timer0計時時間 Loop: ;無窮迴圈 JMP Loop ;------------------------- Init: ACALL DELAY ;lcd初始化設定 MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#38H ACALL WRINS MOV A,#08H ACALL WRINS MOV A,#01H ACALL WRINS MOV A,#06H ACALL WRINS MOV A,#0CH ACALL WRINS RET ;------------------------- DISPLAY:MOV R7,#00H ;將字串字元碼送到lcd NEXT: MOV A,R7 MOVC A,@A DPTR CJNE A,#10H,DSP RET DSP: ACALL WRDATA INC R7 AJMP NEXT ;------------------------- SETUP: MOV TMOD,#00000001B ;計時器設定計時50ms MOV TL0,#<(65536-50000) MOV TH0,#>(65536-50000) RET ;------------------------- LINE1: MOV A,#10000000B ;設定從00h開始顯示 ACALL WRINS RET ;------------------------- LINE2: MOV A,#11000000B ;設定從40h開始顯示 ACALL WRINS RET ;------------------------- LINE3: MOV A,#10000110B ;設定從06h開始顯示轉速 ACALL WRINS RET ;------------------------- LINE4: MOV A,#11000110B ;設定從46h開始顯示風速 ACALL WRINS RET ;------------------------- INT0: ;外部中斷副程式 INC A RETI ;------------------------- Timer0: ;計時中斷副程式 PUSH A PUSH PSW ACALL SETUP ;重新設定計時值 DJNZ R4,#CONT ;若r4-1不為0則跳至cont MOV R4,#20 ;重新設定r4值 ACALL CALCU ;跳到計算副程式 POP PSW POP A CLR A CONT: RETI ;------------------------- WRINS: MOV P2,#00011111B ;RS=0,R/W=0,E=0寫入指令 NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 ACALL DLY1 RET ;------------------------- WRDATA: MOV P2,#10011111B ;RS=1,R/W=0,E=0送入資料至lcd NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 ACALL DLY2 RET ;------------------------- CALCU: ;計算轉速副程式(還沒有寫出來) ;------------------------- DELAY: MOV R6,#100 ;延時40ms DL: MOV R7,#200 DJNZ R7,$ DJNZ R6,DL RE ;------------------------- DLY2: MOV R6,#80 ;延時160us DJNZ R6,$ RET ;------------------------- TAB1: DB 'Speed: R.P.M' ;顯示轉速 DB 10H ;------------------------- TAB2: DB 'Wind : m/s' ;顯示風速 DB 10H ;------------------------- END我先用市面上的風速計測轉速與風速的關係是1rpm=0.001m/s,等到成品做出來以後,我會再用風速計來校正這個比例的關係 光柵因為我是用厚紙板剪的...所以應該是沒辦法到60格,我只有剪6格來做光柵(不知道這樣會不會有什麼影響?) 我會再去找出4位數16進位轉BCD程式和16位元除8位元除法的程式來補上 還有阿信大您所修改的程式 ;R3:PULSE_HIGH(脈波計數高位元組) ;R4:PULSE_LOW (脈波計數低位元組) DISP10 EQU 40H ;LCM緩衝區 第一列 DISP20 EQU 50H ;LCM緩衝區 第二列 fg_1S .REG 20H.0 ;1秒旗標 CNT_1S EQU 30H ;1秒的計數器這一部分我找了很多書的指令,都看不出來是在做什麼,可以再麻煩您解釋嗎? 再次感謝各位願意把這一大串文章看完... 希望各位能給小弟一些意見 感激不盡 發表人 - CHENG07 於 2005/11/30 22:07:36 |
阿信
版主 發表:111 回覆:983 積分:813 註冊:2005-03-10 發送簡訊給我 |
//fg_1S .REG 20H.0 ;1秒旗標
這是定義位元(bit)位址在20H.0 //CNT_1S EQU 30H ;1秒的計數器
這是定義位元組(byte)位址在30H //我只有剪6格來做光柵(不知道這樣會不會有什麼影響?)
會影響解析度 6格的解析度是10RPM
不過這樣程式反而好寫
設在最高轉速為2550RPM就只要用1個位元組就可以計算了
做除法時也簡單 也不用16位元除法副程式了 下面是昨天沒po完的
DISPLAY: ;顯示緩衝區資料 顯示在LCM上 CALL LINE1 ;第一列 MOV R0,#DISP10 MOV R2,#10H DP1: MOV A,@R0 CALL WRDATA INC R0 DJNZ R2,DP1 ;--- CALL LINE2 ;第二列 MOV R0,#DISP20 MOV R2,#10H DP2: MOV A,@R0 CALL WRDATA INC R0 DJNZ R2,DP2 RET ;-------------------------------- LINE1: MOV A,#10000000B ACALL WRINS RET ;-------------------------------- LINE2: MOV A,#11000000B ACALL WRINS RET ;-------------------------------- WRINS: ;寫指令 CALL CKBUSY MOV P2,#00011111B ;RS=0,R/W=0,E=0 NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 RET ;-------------------------------- WRDATA: ;寫資料 CALL CKBUSY MOV P2,#10011111B ;RS=1,R/W=0,E=0 NOP SETB P2.5 ;E=1 MOV P0,A NOP CLR P2.5 ;E=0 RET ;-------------------------------- CKBUSY: ;讀取BUZY旗標 MOV P0,#0FFH CLR P2.7 ;RS SETB P2.6 ;RW SETB P2.5 ;EN MOV C,P0.7 CLR P2.5 ;EN JC CKBUSY RET ;-------------------------------- DELAY: MOV R6,#100 DL: MOV R7,#200 DJNZ R7,$ DJNZ R6,DL RET ;-------------------------------- TIME0: MOV TMOD,#00000001B MOV TH1,#0 MOV TL1,#0 MOV TCON,#01000000B DEL1S: MOV R7,#20 A2: MOV TH0,#>(65536-50000) MOV TL0,#<(65536-50000) SETB TR0 A1: JNB TF0,A1 CLR TR0 CLR TF0 DJNE R7,A2 RET ;-------------------------------- INT0: ;外部中斷 PUSH A ;PUSH PSW INC R3 ;16位元脈波累加 MOV A,R3 JNZ INT0_EX INC R4 INT0_EX: ;POP PSW POP A RETI ;-------------------------------- INT_TMR0: ;TIMER0中斷 20mS PUSH A PUSH PSW DJNZ CNT_1S,IT0_EX MOV CNT_1S,#50 ;1秒到 MOV R5,R3 ;取出計數的值 MOV R6,R4 CLR R3 CLR R4 SET fg_1S ;設定1秒旗標 IT0_EX: POP PSW POP A RETI |
阿信
版主 發表:111 回覆:983 積分:813 註冊:2005-03-10 發送簡訊給我 |
把下面這段DISP_RPM的副程式補上
應該就能顯示轉速跟風速了
程式不是很嚴謹
但學生專題應該可以了
你把程式看懂
再做後續修改 把程式做最佳化! PS.完成後拍張照片來看看ㄋㄟ
;-------------------------------- DISP_RPM: ;光柵為6格 則RPM=1秒脈波數*60/6格 ;RPM=(R6,R5) ;將(R6,R5)轉為4位數字顯示在LCM上 DR_1000: ;取千位數 R5/100的商 MOV A,R5 MOV B,#100 DIV AB AND A,#30H MOV 47H,A ;把千位數放到第一列第7位 DR_100: ;取百位數 餘數/10 MOV A,B MOV B,#10 DIV AB AND A,#30H MOV 48H,A ;把百位數放到第一列第8位 DR_10: ;取十位數 餘數 MOV A,B AND A,#30H MOV 49H,A ;把十位數放到第一列第9位 DR_1: ;個位數 固定為0 MOV 4AH,#30H;把個位數放到第一列第10位 ;----- DISP_SP: ;設風速為RPM/80(M/S) (以10的倍數比例 以簡化程式) DS_10: ;取十位數 MOV A,R5 MOV B,#80 ;<-風速比 DIV AB AND A,#30H MOV 57H,A ;把十位數放到第二列第7位 DS_1: ;取個位數 MOV A,B MOV B,#8 ;<-風速比 DIV AB AND A,#30H MOV 58H,A ;把個位數放到第二列第8位 DS_DOT: ;小數點 MOV 59H,#2EH;把小數點放到第二列第9位 DS_DOT1: ;取小數 MOV A,B MOV B,#10 MUL AB ;先乘10 才能取小數 MOV B,#8 ;<-風速比 DIV AB AND A,#30H MOV 5AH,A ;把小數放到第二列第10位 CALL DISPLAY RET ;-------------------------------- |
cheng07
一般會員 發表:8 回覆:12 積分:4 註冊:2005-05-09 發送簡訊給我 |
|
阿信
版主 發表:111 回覆:983 積分:813 註冊:2005-03-10 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |