?? mcu.asm
字號:
;觸發外部中斷0。
call ENABLEINT0 ;開啟外部中斷0。
mov a,MENUINDEX ;取得功能序號。
mov dptr,#FUNCTABLE ;
rl a ;
rl a ;
jmp @a+dptr ;按功能序號轉移至相應功能處。
FUNCTABLE: ljmp FUNCTION0 ;一定要強制使用ljmp指令,以保證每個
;小段都是4個字節。
nop ;
ljmp FUNCTION1 ;
nop ;
ljmp FUNCTION2 ;
nop ;
ljmp FUNCTION3 ;
nop ;
ljmp FUNCTION4 ;
nop ;
ljmp FUNCTION5 ;
nop ;
ljmp FUNCTION6 ;
nop ;
ljmp FUNCTION7 ;
nop ;
ljmp FUNCTION8 ;
nop ;
ljmp FUNCTION9 ;
nop ;
ljmp FUNCTION10 ;
nop ;
ljmp FUNCTION11 ;
nop ;
ljmp FUNCTION12 ;
nop ;
ljmp FUNCTION13 ;
nop ;
;;;;;;;;;;;;;;;;功能選擇子程序結束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;歡迎子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>資源占用報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>臨時占用a,dptr
;>>>>>>>>>>>>>>>報告完畢>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FUNCTION0: mov dptr,#8000h ;
mov a,#81h ;
movx @dptr,a ;命令自建元器件進入歡迎狀態。
;再啰嗦幾句,如果您要使用自建
;元器件,那么必須自己改寫動態
;庫,作者提供一個簡單的動態庫
;開源項目。
mov a,#80h ;
movx @dptr,a ;命令自建元器件進入待機狀態。
mov a,#LCD_CLS ;
call WRCMD ;清屏。
mov dptr,#WELCOME_1 ;
call WRSTR ;初始化LCD屏幕,顯示第一行。
mov a,#LCD_SETDDADDR+64 ;換行。
call WRCMD ;
inc dptr ;
call WRSTR ;
FUNCTION0_1: mov a,RETURNFLAG ;檢查返回標志,決定是否返回。
jz FUNCTION0_CON ;如果為零,繼續執行。CON=CONTINUE。
jmp main ;
FUNCTION0_CON: jmp FUNCTION0_1 ;
;;;;;;;;;;;;;;;;歡迎子程序結束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;測量電壓功能子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>資源占用報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>臨時占用a,b,c,dptr,bank0區r0~r7
;>>>>>>>>>>>>>>>報告完畢>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FUNCTION1: call DISABLEINT1 ;屏蔽外部中斷1。
;作者沒有使用中斷的方法處理ADC0804的
;$INTR$引腳變化,所以必須屏蔽外部中
;斷1。
mov a,STATUS ;取得外部電設備狀態字。
orl a,#01h ;進入測量電壓狀態。
anl a,#0FDh ;
mov STATUS,a ;保存外部電設備狀態字。
mov dptr,#8100h ;
movx @dptr,a ;
nop ;稍微停頓一下。
nop ;
FUNCTION1_1: mov a,RETURNFLAG ;檢查返回標志,決定是否返回。
jz FUNCTION1_CON ;如果為零,繼續執行。
jmp main ;
FUNCTION1_CON: call ADCIO ;調用ADC0804讀寫操作子程序。
;讀取的數值放在a和地址ADCOUTCUR中。
cjne a,ADCOUTBAK,FUNCTION1_2 ;比較當前和上一次ADC0804輸出,如果
;相同,那么表明外部電壓沒有發生改
;變,也就沒有必要刷新顯示,這樣視覺
;效果比較舒服。
jmp FUNCTION1 ;
FUNCTION1_2: mov r3,a ;ADC0804的數值乘以5,除以255就是對應
;的模擬電壓值。現在將這個模擬電壓值
;的單位換算為mV,也就是擴大1000倍,
;然后取得4位計算結果。當然了,最后
;那一位沒有意義,因為ADC0804只有8
;bit精度,您可以算算它對應的最小電
;壓分辨率是多少。
mov r2,#00h ;
mov r7,#88h ;
mov r6,#13h ;十六進制1388等于十進制5000。
call MULD2 ;調用雙字節無符號乘法子程序。
mov r0,#DIVD4ADDRESS0 ;以下準備調用4字節無符號除法子程序,
;將剛才的乘法結果除以255。下面是一些
;賦初始值的準備工作。
mov r1,#DIVD4ADDRESS4 ;
mov a,r2 ;
movx @r1,a ;
inc r1 ;
mov a,r3 ;
mov @r1,a ;
inc r1 ;
mov a,r4 ;
mov @r1,a ;
inc r1 ;
mov a,r5 ;
mov @r1,a ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0FFh ;準備除以的255。
call DIVD4 ;調用4字節無符號除法子程序。
;除法結束之后就應該顯示結果了,對吧!
;可是您別著急,在內存中的數值是二進制
;的,一個字節對應2個十六進制數字,所
;以必須先做一些轉換工作。有兩種方法。
;第一種:將運算結果連續的進行除以10的操
;作,依次取得個位、十位、百位等等,就
;像下面的程序那樣,這么做比較浪費處理
;器的時間,因為您做的是除法。第二種方
;法:對結果進行BCD調整。這個方法應該簡
;單,留給您自己思考了,我沒有編寫。
mov r1,#DIVD4ADDRESS8 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0Ah ;準備除以10。
mov dptr,#LCD0 ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;DIVD4ADDRESS3單元存放的是除法后的最低位
;余數,由于是除以10的余數,只能是0123456
;789之一。
movc a,@a+dptr ;要是直接顯示這個數字的話,恐怕您什么都
;看不到。LCD1602不認識啊,它只認識ASCII
;碼,所以還得取得這個數字對應的ASCII碼才
;行。作者已經在前面列出了必要的ASCII碼表。
;也許作者這個處理方法復雜了,要是您有好的
;方法,不吝賜教哦!作者QQ66410070。
mov RESULT5,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT4,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT3,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT1,a ;
mov a,#0Dh ;小數點。
movc a,@a+dptr ;
mov RESULT2,a ;
mov a,#0Ch ;
movc a,@a+dptr ;
mov RESULT6,a ;單位V。
mov a,#00h ;
mov RESULT7,a ;空終止。后面的程序類似,不再解釋。
mov a,#LCD_CLS ;清屏。
call WRCMD ;
call WRRESULT ;調用寫結果字符串子程序。
jmp FUNCTION1_1 ;
;;;;;;;;;;;;;;;;測量電壓功能子程序結束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;ADC讀寫子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>資源占用報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>臨時占用a,dptr,c,r7
;>>>>>>>>>>>>>>>報告完畢>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ADCIO: mov a,ADCOUTCUR ;
mov ADCOUTBAK,a ;前一次結果保存在ADCOUTBAK中。
mov dptr,#8200h ;選擇ADC0804,一定要保證P2.7處于高
;電平,禁止ADC的輸出。作者把啟動
;ADC0804轉換的操作映射為外部內存的
;空寫操作(隨便;寫任何數值)。但是
;作者沒有將ADC0804的的讀取映射為外
;部內存的讀操作。作者曾經試圖這么
;做,但是失敗了!也許是Proteus軟件
;在時序方面的問題,也許是ADC0804器
;件的問題,當然也可能是作者水平有
;限,沒能找到解決方案。如果您有好的
;設計,千萬告知作者,謝謝!
movx @dptr,a ;空寫ADC0804,啟動轉換。
setb c ;
mov p3.3,c ;讀取數據必須先寫1。
ADCIO_1: mov c,P3.3 ;等待ADC0804轉換完成。
jc ADCIO_1 ;
mov p0,#0FFh ;讀取數據必須先寫1。
clr c ;
mov p2.7,c ;開啟ADC0804的輸出允許。
nop ;不要馬上讀取。
nop ;ADC0804轉換結束與輸出需要間隔幾個
;時鐘周期。
nop ;具體需要幾個時鐘周期請參考手冊,自
nop ;行調整。
nop ;
nop ;
nop ;
nop ;
mov a,p0 ;讀端口,取得轉換的數字值。
mov ADCOUTCUR,a ;寫入ADCOUTCUR。
setb c ;
mov p2.7,c ;關閉ADC0804的輸出允許,以免影響后
;續對其它器件的操作。一定要關閉啊!
ret ;
;;;;;;;;;;;;;;;;ADC讀寫子程序結束;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;測量電阻功能子程序;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;>>>>>>>>>>>>>>>資源占用報告>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;>>>>>>>>>>>>>>>臨時占用a,b,c,dptr,bank0區r0~r7
;>>>>>>>>>>>>>>>>>報告完畢>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
FUNCTION2: call DISABLEINT1 ;屏蔽外部中斷1。
mov a,STATUS ;取得外部電設備狀態字。
orl a,#03h ;進入測量電阻狀態。
mov STATUS,a ;保存外部電設備狀態字。
mov dptr,#8100h ;
movx @dptr,a ;
nop ;稍微停頓一下。
nop
FUNCTION2_1: mov a,RETURNFLAG ;檢查返回標志,決定是否返回。
jz FUNCTION2_CON ;
jmp main ;
FUNCTION2_CON: call ADCIO ;調用ADC0804讀寫操作子程序。
;讀取的數值放在a和地址ADCOUTCUR中。
cjne a,ADCOUTBAK,FUNCTION2_2 ;比較當前和上一次ADC0804輸出,如果
;相同,那么表明外部電壓沒有發生改
;變,也就沒有必要刷新顯示,這樣視
;覺效果比較舒服。
jmp FUNCTION2 ;
FUNCTION2_2: mov r3,a ;ADC0804的數值乘以23500,除以3060,
;再減去910,就是待測電阻值。參考電
;路圖,您可以自己思考為什么是這個算
;式?以下的程序與測電壓大同小異,不
;再多解釋。
mov r2,#00h ;
mov r7,#0CCh ;
mov r6,#5Bh ;十六進制5BCC等于十進制23500。
call MULD2 ;調用雙字節無符號乘法子程序。
mov r0,#DIVD4ADDRESS0 ;
mov r1,#DIVD4ADDRESS4 ;
mov a,r2 ;
movx @r1,a ;
inc r1 ;
mov a,r3 ;
mov @r1,a ;
inc r1 ;
mov a,r4 ;
mov @r1,a ;
inc r1 ;
mov a,r5 ;
mov @r1,a ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0Bh ;
inc r1 ;
mov @r1,#0F4h ;十六進制0BF4等于十進制3060。
call DIVD4 ;
clr c ;清除c。
mov r1,#DIVD4ADDRESS7 ;以下減去910,四個字節減法。
mov a,@r1 ;
subb a,#8Eh ;
mov @r1,a ;
dec r1 ;
mov a,@r1 ;
subb a,#03h ;
mov @r1,a ;
dec r1 ;
mov a,@r1 ;
subb a,#00h ;
mov @r1,a ;
dec r1 ;
mov a,@r1 ;
subb a,#00h ;
mov @r1,a ;
mov r1,#DIVD4ADDRESS8 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#00h ;
inc r1 ;
mov @r1,#0Ah ;
mov dptr,#LCD0 ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT3,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT2,a ;
call DIVD4 ;
mov a,DIVD4ADDRESS3 ;
movc a,@a+dptr ;
mov RESULT1,a ;
mov a,#0Bh ;R的字符。
movc a,@a+dptr ;
mov RESULT4,a ;
mov a,#00h ;
mov RESULT5,a ;
mov a,RESULT1 ;滅零處理。比如待測的電阻是20R,
;希望顯示結果20R,而不是020R,滅
;掉前導零。
cjne a,#30h,FUNCTION2_3 ;先取得最高位字符,如果是零(ASCII
;碼30h),那么滅掉,其后的字符依次
;前移一位。否則不滅零,直接顯示。
mov a,RESULT2 ;
mov RESULT1,a ;
mov a,RESULT3 ;
mov RESULT2,a ;
mov a,RESULT4 ;
mov RESULT3,a ;
mov a,RESULT5 ;
mov RESULT4,a ;
mov a,RESULT1 ;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -