當前位置:編程學習大全網 - 編程語言 - 求壹個單片機程序

求壹個單片機程序

#include "p16f877A.inc"

errorlevel -302

;***********************************

__CONFIG _DEBUG_OFF&_CP_ALL&_WRT_HALF&_CPD_ON&_LVP_OFF&_BODEN_OFF&_PWRTE_ON&_WDT_OFF&_HS_OSC;

;************************************

disbuf equ 20h ;顯示緩沖區20,21,22

ledtemp equ 29h

vrevh equ 2Ah

vrevl equ 2Bh

SOUH equ 40h ;子程序入口高位

SOU equ 41h ;子程序入口低位

RLTH equ 42h ;子程序入口高位

RLT equ 43h ;子程序入口低位

CNT equ 44h ;子程序用寄存器

TEMP1 equ 45h ;子程序用

TEMP2 equ 46h ;同上

TEMP3 equ 47h ;同上

TEMP4 equ 48h ;同上

;*****************************************

org 0000h

NOP

goto start

org 0005H

start:

banksel TRISA

movlw B'00000001' ;AN0>>>>DC input DC通道上輸入,註意,這裏是打開RA0,但是在ICD上RA0 控制第二個LED.RA1

movwf TRISA ;對應第壹個LED,這壹點在顯示結果時請自已區分

movlw B'00000000'

movwf TRISC

movlw B'10000111' ;預分頻器給TMRO,且分頻比為1:256

movwf OPTION_REG

clrf STATUS

movlw 0xa0 ;TMRO初值

movwf TMR0

;***** ***************ADC初始化

;***** *****************

ATOD:

banksel ADCON1

movlw B'10001110' ;轉換結果右對齊,除RA0為模擬輸入口外,其他RA口跟RE口均為普通數字口

movwf ADCON1

CLRF STATUS

movlw B'01000001' ;轉換時鐘頻率為內部時鐘的1/8,AN0通道,允許ADC工作,暫時不開啟AD轉換

movwf ADCON0

;***** ************************

movlw 0x00

movwf disbuf

movwf disbuf+1

movwf disbuf+2

CLRF STATUS

BTFSS INTCON,T0IF ;等待和循環檢測TMR0溢出中斷標誌位

GOTO $-1 ;如果沒有發生TMR0溢出中斷則返回循環檢測

BCF INTCON,T0IF ;保證足夠的采樣時間

movlw 0xa0 ;TMRO初值

movwf TMR0

bsf ADCON0,GO ;開始轉換

ADWAIT:

btfsc ADCON0,GO

goto ADWAIT ;等待轉換完成

banksel ADRESH

movf ADRESH,w ;讀電壓值高2位

CLRF STATUS

movwf vrevh

BANKSEL ADRESL

movf ADRESL,w ;讀電壓低8位

CLRF STATUS

movwf vrevl ;裝值放入接收寄存器VERVH,VERVL,為節省時間

;采樣值可以直接放入SOUH,SOU,但運算不方便

;*******測試用B'1100001111'**********************

; movlw 0x03 ;這裏可以手動往VREVH,VrevL兩個寄存器輸入10位AD值,以便用來測試是否能

;在LED上顯示正確的電壓值,如:30F=B'1100001111'(10位采樣AD值);

;30F的實際值是3.823V,那麽在LED上將顯示3.82,寄存器21,22,23的值分別為3,8,2

;movwf vrevh ;程序正常采樣時這四句話要屏蔽;

; movlw 0x0f

; movwf vrevl

;************************************************

movf vrevh,w

movwf SOUH ;將被乘數放入SOUH,SOU

movf vrevl,w

movwf SOU

movlw 0x00 ;乘數放入RLTH,RLT

movwf RLTH

movlw 0x05 ;

movwf RLT ;這裏表示:30F*5,結果放入RLTH,RLT,SOUH,SOU;

call DUMUL ;>>>>>>5*V_gather,result>>>RLTH,RLT SOUH,SOU

movlw 0x04 ;準備除1024(400),放數入RLTH,RLT!!!!關鍵所以,要理解為重.....以下三步都是這樣的操作

movwf RLTH ;除法子程序用SOUH,SOU除以RLTH,RLT,因為上面的乘法程序不會超過兩個字節

movlw 0x00 ;5V*3FF(10位滿值)=13FB,所以在調用除法程序前不用考慮RLTH,RLT是否有其他值而被值

movwf RLT ;0X0400沖掉

call DUDIV ;調用除法程序,商在SOUH,SOU,余數在RLTH,RLT,對於余數再*0A處理.然後再除 0x0400

movf SOU,w ;這樣的話除兩次就是小數點後兩位精度

movwf disbuf ;這裏得到電壓整數值

movf RLTH,w

movwf SOUH ;送余數到SOUH,SOU,然後*0A,為小數點後壹位的運算作準備

movf RLT,w

movwf SOU

movlw 0x00

movwf RLTH

movlw 0x0A

movwf RLT

call DUMUL; >>>余數*10>>>RLTH,RLT SOUH,SOU,這裏壹般在souh,sou兩個字節,為除法作準備

movlw 0x04 ;放除數0X0400

movwf RLTH

movlw 0x00

movwf RLT

call DUDIV ;原來的余數再除以0X400

movf SOU,w

movwf disbuf+1 ;//取商到第二位電壓值,這裏是小數點的後壹位

movf RLTH,w ;然後將余數放到SOUH,SOU,為下壹次乘法作準備

movwf SOUH

movf RLT,w

movwf SOU

movlw 0x00

movwf RLTH

movlw 0x0A ;SOUH,SOU,RLTH,RLT為乘法入口

movwf RLT

call DUMUL ;>>>*10>>>RLTH,RLT SOUH,SOU,再乘以0A,出口在RLTH,RLT,SOUH,SOU

movlw 0x04

movwf RLTH

movlw 0x00

movwf RLT

call DUDIV ;再除以0X0400,除完這壹次後就不要再除了,因為是保留小數點後兩位

movf SOU,w

movwf disbuf+2 ;取電壓值,這裏是小數點後兩位值

call Led_scan

call delay_same1

goto ATOD ;循環轉換

;*********************led scan*************************

;LED掃描程序,對應於ICD,下面程序可以優化,請自已進行優化

Led_scan:

movlw ledtable ;取得表頭地址

movwf ledtemp

movf disbuf+2,w ;取得偏移量

addwf ledtemp,w ;表頭地址加上偏移量做為跳轉地址

call ledconvert ;查表

movwf PORTC ;送數碼管顯示

movlw B'11101111'

movwf PORTA ;點亮相應的數碼管

call delay_same ;延時壹段時間,保證顯示足夠亮度

movlw 0ffh

movwf PORTC ;清除顯示,防止幹擾其他位顯示

movlw ledtable

movwf ledtemp

movf disbuf+1,w

addwf ledtemp,w

call ledconvert

movwf PORTC

movlw B'11011111'

movwf PORTA

call delay_same

movlw 0ffh

movwf PORTC

movlw ledtable

movwf ledtemp

movf disbuf,w

addwf ledtemp,w

call ledconvert

andlw b'01111111' ;加上小數點

movwf PORTC

movlw B'11111011'

movwf PORTA

call delay_same

movlw 0ffh

movwf PORTC

movlw 0ffh ;關閉所有顯示

movwf PORTA

return

;*******end for led send***************************************

;;----------------數碼管查表程序-------------------------------

ledconvert

movwf 2

ledtable

RETLW 0c0h ;0

RETLW 0f9h ;1

RETLW 0a4h ;2

RETLW 0b0h ;3

RETLW 099h ;4

RETLW 092h ;5

RETLW 082h ;6

RETLW 0F8h ;7

RETLW 080h ;8

RETLW 090h ;9

return

delay_same ;延時

movlw 0F0h

movwf 70h

lop0 decfsz 70h,1

goto lop0

return

delay_same1

movlw 0F0h

movwf 71h

lop1 decfsz 71h,1

goto lop1

return

;********************************************************************************

;//是16*16進制,如果要十進制,則要進行BCD轉換

;********************DUMUL test Date:0808,ok*************************************

;具體可參考相關子程序庫

;最大實現FFFF*FFFF=FFFE0001的算法 比如:0X08 0X43 * 0X00 0X10>>>0X84 0X30

;本程序實現雙字節無符號數乘法。

;入口參數:被乘數在SOUH:SOU中,乘數在RLTH:RLT中。

;出口參數:結果在RLTH:RLT:SOUH:SOU中。

IFNDEF DUMUL1

#DEFINE DUMUL1

DUMUL MOVLW .16

MOVWF CNT

MOVF SOU,W

MOVWF TEMP3

MOVF SOUH,W

MOVWF TEMP4

CLRF SOU ;用於暫

CLRF SOUH ;存

CLRF TEMP1 ;結

CLRF TEMP2 ;果

BCF STATUS,C

LOOP3 RRF TEMP4,F

RRF TEMP3,F ;將被乘數的某壹位送到C中

BTFSC STATUS,C

CALL DUADD ;將RLTH:RLT中的被乘數加上

RRF SOUH,F

RRF SOU,F

RRF TEMP2,F

RRF TEMP1,F ;被乘數右移

DECFSZ CNT,F

GOTO LOOP3

MOVF SOUH,W ;保存結果

MOVWF RLTH

MOVF SOU,W

MOVWF RLT

MOVF TEMP2,W

MOVWF SOUH

MOVF TEMP1,W

MOVWF SOU

RETURN

;INCLUDE "DUADD.ASM"

ENDIF

;********************DUADD*********************

;本程序實現雙字節無符號數加法。

;入口參數:被加數在SOUH:SOU中,加數在RLTH:RLT中。

;出口參數:結果在SOUH:SOU中,進位位在STATUS:C中。

;占用資源:W,024H,025H,026H,027H,壹重堆棧。

IFNDEF DUADD1

#DEFINE DUADD1

DUADD MOVF RLT,W

ADDWF SOU,F

MOVF RLTH,W

BTFSC STATUS,C

INCFSZ RLTH,W

ADDWF SOUH,F

RETURN

ENDIF

;********************DUDIV*********************

;本程序實現雙字節無符號數除法。

;入口參數:被除數在SOUH:SOU中,除數在RLTH:RLT中。

;出口參數:商在SOUH:SOU中,余數在RLTH:RLT中.

;占用資源:W,STATUS,023H,024H,025H,026H,027H,028H,029H,壹重堆棧。

;說 明: 用戶在調用該子程序之前必須確定除數不為零,否則得不到正確結果.

IFNDEF DUDIV1

#DEFINE DUDIV1

DUDIV MOVLW .16 ;循環16次

MOVWF CNT

CLRF TEMP2

CLRF TEMP1 ;TEMP2:TEMP1得到余數

BCF STATUS,C

RLF SOU,F

RLF SOUH,F

RLF TEMP1,F

RLF TEMP2,F

LOOP79 MOVF RLTH,W

SUBWF TEMP2,W ;檢測是否余數大於除數

BTFSS STATUS,Z

GOTO NOCHK

MOVF RLT,W

SUBWF TEMP1,W ;如果高位相等則檢測低位

NOCHK BTFSS STATUS,C

GOTO NOGO

MOVF RLT,W ;余數減除數

SUBWF TEMP1,F

BTFSS STATUS,C

DECF TEMP2,F

MOVF RLTH,W

SUBWF TEMP2,F

BSF STATUS,C ;結果中移入1

NOGO RLF SOU,F

RLF SOUH,F

RLF TEMP1,F

RLF TEMP2,F

DECFSZ CNT,F

GOTO LOOP79

BCF STATUS,C

RRF TEMP2,W

MOVWF RLTH

RRF TEMP1,W ;恢復余數

MOVWF RLT

RETLW 0

ENDIF

;**************************************************

end

  • 上一篇:有人說學java只能成碼農,那還要學什麽呢
  • 下一篇:合肥電氣工程職業技術學校怎麽樣
  • copyright 2024編程學習大全網