 LIST P=16F876 #INCLUDE P16F876.INC ;以下采用塊定義的方法定義單片機(jī)內(nèi)部寄存器 CBLOCK 0X20 ;自定義寄存器從0X20開始 FLAG1 ;FLAG1作為標(biāo)志寄存器 VOLTAGEH ;電池電壓高位寄存器 VOLTAGEL ;電池電壓低位寄存器 TSH ;手柄電壓高位寄存器 TSL ;手柄電壓低位寄存器 STATE1 ;霍爾信號(hào)采樣暫存器1 STATE2 ;霍爾信號(hào)采樣暫存器2 STATE3 ;霍爾信號(hào)采樣暫存器3 DELAY ;延時(shí)計(jì)數(shù)器 COUNT_VOL ;低電壓采樣次數(shù)計(jì)數(shù)器 ACCaLO ;ACCa~ACCd為運(yùn)算用的寄存器 ACCaHI ACCbLO ACCbHI ACCcLO ACCcHI ACCdLO ACCdHI TEMP ;臨時(shí)寄存器 TEMP1 ;臨時(shí)寄存器(中斷用) SIGN ;符號(hào)寄存器 COUNT ;臨時(shí)寄存器 W_STACK ;中斷時(shí)用于暫存W寄存器值 ST_STACK ;中斷時(shí)用于暫存STATUS寄存器值 ENDC ;***********標(biāo)志寄存器位定義以及程序中常數(shù)定義*********** CONSTANT VOLTAGE=0 ;采電池電壓標(biāo)志位 CONSTANT PWM=1 ;輸出下一次PWM信號(hào)標(biāo)志位 CONSTANT LOWPOWER=2 ;低電壓標(biāo)志位 CONSTANT SHUTDOWN=3 ;剎車標(biāo)志位 CONSTANT OFF=4 ;復(fù)位標(biāo)志位 CONSTANT AND=0XE0 ;AND用于獲取有效霍爾信號(hào) CONSTANT FULLPWM=0XFF ;當(dāng)PWM輸出全高時(shí),輸入CCPR1L中的值 CONSTANT VOLOFFH=0X02 ;當(dāng)電池電壓低于24AH時(shí), 低壓保護(hù)2.86 V/31.5 V CONSTANT VOLOFFL=0X4A CONSTANT VOLONH=0X02 ;當(dāng)電池電壓大于266H時(shí),允許電機(jī)重開3V/33V CONSTANT VOLONL=0X66 CONSTANT TSONH=0X01 ;剎車后手柄復(fù)位值低于133H,則允許電機(jī)重新啟動(dòng) CONSTANT TSONL=0X33 ;***復(fù)位矢量入口(單片機(jī)復(fù)位時(shí),PC指針指向程序存儲(chǔ)器0X0000單元)*** ORG 0X0000 START GOTO MAIN ;復(fù)位后程序進(jìn)入主程序 ;***中斷矢量入口程序(PIC單片機(jī)的中斷矢量入口為0X0004)*** ORG 0X0004 ;中斷矢量入口 BTFSC INTCON,RBIF ;是否為RB口電平變化中斷? GOTO SAMPLERB ;是,進(jìn)入RB口電平變化中斷服務(wù)程序 BTFSC PIR1,ADIF ;是否為AD采樣中斷 GOTO AD ;是,進(jìn)入AD中斷服務(wù)程序 BTFSC INTCON,INTF ;是否為剎車中斷 GOTO BRAKE ;是,剎車中斷處理 RETFIE ;如都不是,則中斷返回 ;************逆變橋輸出控制表************* ;逆變橋輸出控制表,其輸出對(duì)應(yīng)6種狀態(tài),霍爾信號(hào)來(lái)自B口RB7、RB6、RB5,C口輸出低電平有 ;效,其中RC1,RC2不作為觸發(fā)電路輸出口,故表中使其為高電平 ORG 0X0020 ;表程序從0X0020單元開始存放(也可以不從這開始) OUT_TABLE ADDWF PCL,1 RETLW 0X0AF ;如霍爾信號(hào)為0、0、0,則使RC4、RC6為低電平 RETLW 0X0BE ;如霍爾信號(hào)為0、0、1,則使RC0、RC6為低電平 RETLW 0X0FF ;沒有為0、1、0的霍爾信號(hào)對(duì)應(yīng)電機(jī)狀態(tài) RETLW 0X07E ;如霍爾信號(hào)為0、1、1,則使RC0、RC7為低電平 RETLW 0X0CF ;如霍爾信號(hào)為1、0、0,則使RC4、RC5為低電平 RETLW 0X0FF ;沒有為1、0、1的霍爾信號(hào)對(duì)應(yīng)電機(jī)狀態(tài) RETLW 0X0D7 ;如霍爾信號(hào)為1、1、0則使RC3、RC5為低電平 RETLW 0X077 ;如霍爾信號(hào)為1、1、1則使RC3、RC7為低電平 ;***************主程序***************** ORG 0X0100 ;主程序從0X0100單元開始存儲(chǔ) MAIN MOVLW 0X0FF ;由于C口上電復(fù)位值不確定,必須先關(guān)閉所有MOS管 MOVWF PORTC BSF STATUS,RP0 ;選擇存儲(chǔ)體1 MOVLW 0X02 ;設(shè)置RC1為輸入口,其它為輸出口,其中RC2為PWM MOVWF TRISC ;輸出口,其它位為觸發(fā)信號(hào)輸出 BCF STATUS,RP0 ;選擇存儲(chǔ)體0 CLRF PIR1 ;清所有中斷標(biāo)志位 CLRF INTCON ;禁止所有中斷 MOVLW 0X01 ;設(shè)置TMR2預(yù)分頻值為4 MOVWF T2CON MOVLW FULLPWM ;初始化PWM工作循環(huán)寄存器,使PWM占空比為1 MOVWF CCPR1L ;輸出電壓為零 MOVLW 0XFF ;設(shè)置CCP1工作于PWM方式 MOVWF CCP1CON MOVLW 0X0B ;CCP2工作于特殊事件觸發(fā)方式,用作AD采樣周期寄存 MOVWF CCP2CON ;器 MOVLW 0X081 ;選擇AD轉(zhuǎn)換時(shí)鐘為32分頻,選擇AN0通道,并使AD MOVWF ADCON0 ;轉(zhuǎn)換允許 CLRF TMR2 ;TMR2計(jì)數(shù)器清零 CLRF TMR1H ;TMR1計(jì)數(shù)器清零 CLRF TMR1L CLRF T1CON ;TMR1預(yù)分頻為1,關(guān)閉振蕩器,工作于定時(shí)工作方式 MOVLW 0X08 ;初始化AD采樣周期寄存器,T=512 μs MOVWF CCPR2H MOVLW 0X00 MOVWF CCPR2L BSF STATUS,RP0 ;選擇存儲(chǔ)體1 MOVLW 0XEF ;RB口高3位用于采樣霍爾信號(hào),RB0為剎車中斷,設(shè)置為 MOVWF TRISB ;輸入,其它未用 MOVLW 0XC7 ;初始化PWM頻率為5 kHz MOVWF PR2 MOVLW 0X082 ;AD采樣結(jié)果右移,RA口引腳均為模擬輸入 MOVWF ADCON1 BSF OPTION_REG,INTEDG ;選擇INT在下降沿產(chǎn)生中斷 BCF STATUS,RP0 CALL SAMPLE ;確定當(dāng)前轉(zhuǎn)子位置 CALL OUTPUT ;根據(jù)采得的狀態(tài)值觸發(fā)相應(yīng)的MOSFET MOVLW 0X0D8 ;開總中斷、外圍中斷、INT中斷和RB口電平變化中斷允 MOVWF INTCON ;許 BCF PIE2,CCP2IE ;CCP2中斷禁止 BSF PIE1,ADIE ;打開AD采樣中斷 CLRF FLAG1 ;清標(biāo)志位寄存器 CLRF COUNT_VOL ;清電池電壓采樣計(jì)數(shù)器 BSF T1CON,TMR1ON ;開CCP2,對(duì)手柄進(jìn)行等間隔采樣 BSF T2CON,TMR2ON ;開CCP1 RETEST BTFSS FLAG1,PWM ;TS采樣完畢? GOTO NEXT1 ;沒有,轉(zhuǎn)NEXT1 CALL OUT_PWM ;TS采樣完畢,送出相應(yīng)的PWM信號(hào) BCF FLAG1,PWM ;清PWM允許標(biāo)志 NEXT1 BTFSS FLAG1,LOWPOWER;電壓采樣完畢? GOTO NEXT2 ;沒有轉(zhuǎn)NEXT2 CALL POWER ;是,調(diào)用電壓保護(hù)子程序處理數(shù)據(jù) BTFSC FLAG1,OFF ;是否需要復(fù)位? GOTO MAIN ;是,單片機(jī)復(fù)位 NEXT2 BTFSS FLAG1,SHUTDOWN;剎車中斷到來(lái)? GOTO RETEST ;否,回轉(zhuǎn)RETEST CALL BRAKEON ;是,調(diào)用剎車處理子程序 CLRWDT BTFSC FLAG1,OFF ;OFF=0? GOTO MAIN ;否,單片機(jī)復(fù)位 GOTO RETEST ;是,回轉(zhuǎn)RETEST ;***************剎車處理子程序****************** BRAKEON BCF FLAG1,OFF ;清復(fù)位標(biāo)志 BCF FLAG1,SHUTDOWN;是,清相應(yīng)標(biāo)志位 BTFSS PORTB,0 ;INT引腳仍為1? RETURN ;否,中斷是由干擾引起的,返回 BSF STATUS,RP0 BCF PIE1,ADIE ;禁止AD采樣中斷 BCF STATUS,RP0 BCF INTCON,INTE ;關(guān)RB0中斷 MOVLW FULLPWM ;PWM輸出全高 MOVWF CCPR1L BCF T1CON,TMR1ON ;關(guān)閉手柄采樣 BREAK2 BTFSC ADCON0,GO ;正在進(jìn)行AD采樣? GOTO BREAK2 ;是,等待AD采樣完畢 BCF ADCON0,CHS0 BCF ADCON0,CHS1 ;選擇0采樣通道,準(zhǔn)備采樣手柄電壓 BCF PIR1,ADIF ;清AD采樣中斷標(biāo)志位 MOVLW 0X06 ;延時(shí) MOVWF COUNT BREAK3 DECFSZ COUNT GOTO BREAK3 BREAK5 BSF ADCON0,GO ;采樣TS值 BREAK4 BTFSS PIR1,ADIF ;采樣完畢? GOTO BREAK4 BCF PIR1,ADIF BCF STATUS,C MOVF ADRESH,0 ;當(dāng)前TS值送被減數(shù) MOVWF ACCbHI BSF STATUS,RP0 MOVF ADRESL,0 BCF STATUS,RP0 MOVWF ACCbLO MOVLW TSONH ;1.5 V所對(duì)應(yīng)的采樣值送減數(shù) MOVWF ACCaHI MOVLW TSONL MOVWF ACCaLO CALL D_sub ;當(dāng)前TS值減1.5V MOVLW FULLPWM MOVWF CCPR1L CLRWDT BTFSS ACCbHI,7 ;當(dāng)前電壓值大于1.5V? GOTO BREAK5 ;是,重新采樣 BTFSC PORTB,0 GOTO BREAK5 BSF FLAG1,OFF ;否,置相應(yīng)的標(biāo)志位 RETURN ;返回 ;***************開環(huán)PWM輸出子程序**************** OUT_PWM BCF FLAG1,PWM ;清相應(yīng)的標(biāo)志位 MOVF TSH,0 ;將調(diào)速手柄采樣值送至被加數(shù) MOVWF ACCaHI MOVF TSL,0 MOVWF ACCaLO MOVLW 0XFF ;FF1F補(bǔ)碼為0XE1,即1.1 V MOVWF ACCbHI MOVLW 0X1F MOVWF ACCbLO CALL D_add BTFSS ACCbHI,7 ;TS>1.1V? GOTO PWM1 ;是,轉(zhuǎn)PWM1 MOVLW FULLPWM ;否則輸出全高 MOVWF CCPR1L RETURN PWM1 MOVLW 0XFD ;0X27B=3.1V MOVWF ACCbHI MOVLW 0X85 MOVWF ACCbLO CALL D_add BTFSC ACCbHI,7 ;TS>3.1V? GOTO PWM3 PWM2 CLRF CCPR1L BCF CCP1CON,4 BCF CCP1CON,5 RETURN PWM3 MOVLW 0X0FF ;1.1 V對(duì)應(yīng)的采樣值補(bǔ)碼送加數(shù) MOVWF ACCbHI MOVLW 0X1F MOVWF ACCbLO CALL D_add ;TS-1.1V CLRF ACCaHI ;系數(shù)K=56=38H送乘數(shù) MOVLW 0X3F MOVWF ACCaLO CALL D_mpy ;得到放大128倍的低電平時(shí)間K*(TS-1.1V) MOVF ACCcHI,0 ;將結(jié)果取出 MOVWF ACCaHI MOVF ACCcLO,0 MOVWF ACCaLO MOVLW 0X64 ;PWM周期T減去低電平時(shí)間,得到高電平時(shí)間 MOVWF ACCbHI CLRF ACCbLO CALL D_sub BTFSC ACCbHI,7 ;低電平時(shí)間是否大于周期? GOTO PWM2 ;是,輸出全壓 RLF ACCbLO ;否則,輸出與低電平時(shí)間對(duì)應(yīng)的高電平時(shí)間 RLF ACCbHI MOVF ACCbHI,0 ;D10~D2位送CCPR1L MOVWF CCPR1L BCF CCP1CON,5 ;D0位送CCP1CON5 BTFSC ACCbLO,7 BSF CCP1CON,5 BCF CCP1CON,4 ;D.1位送CCP1CON4 BTFSC ACCbLO,6 BSF CCP1CON,4 RETURN ;返回 ;****************剎車中斷服務(wù)程序*************** BRAKE CALL PUSH ;保存現(xiàn)場(chǎng) BCF STATUS,RP0 ;回存儲(chǔ)區(qū)0 BSF FLAG1,SHUTDOWN;置相應(yīng)標(biāo)志位 BCF INTCON,INTF ;清中斷標(biāo)志位 CALL POP ;恢復(fù)現(xiàn)場(chǎng) RETFIE ;中斷返回 ;***************低電壓保護(hù)處理子程序***************** POWER BCF FLAG1,LOWPOWER;清相應(yīng)的標(biāo)志位 MOVF VOLTAGEH,0 MOVWF ACCaHI MOVF VOLTAGEL,0 MOVWF ACCaLO MOVLW VOLOFFH MOVWF ACCbHI MOVLW VOLOFFL MOVWF ACCbLO CALL D_sub BTFSC ACCbLO,7 ;判斷當(dāng)前電池電壓值是否低于保護(hù)電壓(32V) RETURN ;不是,返回 BCF INTCON,INTE BCF T1CON,TMR1ON ;關(guān)閉電流采樣 MOVLW FULLPWM MOVWF CCPR1L BSF STATUS,RP0 BCF PIE1,ADIE ;禁止AD采樣中斷 BCF STATUS,RP0 POWER3 BTFSC ADCON0,GO ;正在進(jìn)行AD采樣? GOTO POWER3 ;是,等待AD采樣完畢 BCF PIR1,ADIF ;清AD采樣中斷標(biāo)志位 BCF ADCON0,CHS0 BSF ADCON0,CHS1 ;選擇電壓采樣通道 MOVLW 0X06 ;延時(shí)等待通道轉(zhuǎn)換完成 MOVWF COUNT POWER4 DECFSZ COUNT GOTO POWER4 POWER6 BSF ADCON0,GO ;采樣電池電壓值 POWER5 BTFSS PIR1,ADIF ;采樣完畢? GOTO POWER5 BCF PIR1,ADIF ;清AD中斷標(biāo)志位 BCF STATUS,C MOVF ADRESH,0 ;當(dāng)前電壓值送被加數(shù) MOVWF ACCbHI BSF STATUS,RP0 MOVF ADRESL,0 BCF STATUS,RP0 MOVWF ACCbLO MOVLW VOLONH ;35V電壓值送被加數(shù) MOVWF ACCaHI MOVLW VOLONL MOVWF ACCaLO CALL D_sub ;當(dāng)前電壓值減35,與重開電壓進(jìn)行比較 MOVLW FULLPWM MOVWF CCPR1L CLRWDT BTFSC ACCbHI,7 ;當(dāng)前電壓值大于35? GOTO POWER6 ;否,重新采樣 BSF FLAG1,OFF ;是,置相應(yīng)的標(biāo)志位 RETURN ;返回 ;***電機(jī)轉(zhuǎn)子位置采樣子程序,狀態(tài)采樣子程序,出口地址:STATE1*** SAMPLE MOVLW AND ;讀RB口 ANDWF PORTB,0 ;分離出有效信息 MOVWF STATE1 ;暫存狀態(tài)值 MOVLW 0X08 MOVWF DELAY DEL1 DECFSZ DELAY ;延時(shí)6 μs GOTO DEL1 MOVLW AND ;讀RB口 ANDWF PORTB,0 ;分離出有效信息,并暫存 MOVWF STATE2 XORWF STATE1,0 ;與上一次狀態(tài)值相異或 BTFSC STATUS,Z RETURN ;兩個(gè)狀態(tài)值相等則返回 MOVLW 0X06 ;否則延時(shí)4 μs MOVWF DELAY DEL2 DECFSZ DELAY GOTO DEL2 MOVLW AND ;讀RB口 ANDWF PORTB,0 ;提取有效信息并暫存 MOVWF STATE3 XORWF STATE1,0 ;與第一次狀態(tài)相同嗎? BTFSC STATUS,Z RETURN ;相同則返回 MOVF STATE2,0 ;否則再與第二次狀態(tài)相比較 XORWF STATE3,0 BTFSS STATUS,Z GOTO SAMPLE ;三次狀態(tài)均不相同則重新采樣 MOVF STATE2,0 ;第三次狀態(tài)與第二次相同,則將正確狀態(tài)賦予STATE1并 MOVWF STATE1 ;返回 RETURN ;************** MOSFET觸發(fā)信號(hào)輸出子程序************** OUTPUT SWAPF STATE1,1 ;STATE1寄存器高低半字節(jié)互換 BCF STATUS,C ;清C位,并將STATE1寄存器左移一位 RRF STATE1,0 ;將采樣所得結(jié)果放至W低三位 CALL OUT_TABLE ;查表獲得輸出值 MOVWF PORTC ;將輸出值輸出至RC口 RETURN ;*************** RB口電平變化中斷服務(wù)程序************** SAMPRB CALL PUSH ;現(xiàn)場(chǎng)保護(hù) BCF STATUS,RP0 CALL SAMPLE ;采樣RB口狀態(tài) CALL OUTPUT ;根據(jù)RB口狀態(tài)觸發(fā)相應(yīng)的MOSFET CALL POP ;恢復(fù)現(xiàn)場(chǎng) BCF INTCON,RBIF ;清RB口電平變化中斷標(biāo)志 RETFIE ;中斷返回 ;************ AD采樣中斷服務(wù)程序*************** AD CALL PUSH ;保護(hù)現(xiàn)場(chǎng) BTFSC FLAG1,VOLTAGE ;是電壓采樣? GOTO SET_VOL ;是,作相應(yīng)的處理 SET_TS BCF ADCON0,CHS0 ;AD采樣值是TS,則選擇1采樣通道 INCF COUNT_VOL ;電壓采樣周期寄存器值加1 BTFSS STATUS,Z ;電壓采樣周期到? GOTO AD4 BCF ADCON0,CHS0 ;是,選擇2采樣通道 BSF ADCON0,CHS1 BSF FLAG1,VOLTAGE ;置相應(yīng)的標(biāo)志位 AD4 BCF PIR1,ADIF ;清AD中斷標(biāo)志 MOVF ADRESH,0 ;采樣值送寄存器暫存 MOVWF TSH BSF STATUS,RP0 MOVF ADRESL,0 BCF STATUS,RP0 MOVWF TSL BSF FLAG1,PWM BTFSS FLAG1,VOLTAGE ;是否需要進(jìn)行電壓采樣? GOTO AD6 MOVLW 0X05 ;是,延時(shí)后采樣電壓 MOVWF TEMP1 AD5 DECFSZ TEMP1 GOTO AD5 BSF ADCON0,GO AD6 CALL POP ;恢復(fù)現(xiàn)場(chǎng),中斷返回 RETFIE SET_VOL BCF ADCON0,CHS1 ;如果采樣值為電壓值,則選擇0通道 BCF ADCON0,CHS0 BCF PIR1,ADIF ;清中斷標(biāo)志位 BCF FLAG1,VOLTAGE ;清相應(yīng)標(biāo)志位 MOVF ADRESH,0 ;將采樣結(jié)果放入被減數(shù)寄存器 MOVWF VOLTAGEH BSF STATUS,RP0 MOVF ADRESL,0 BCF STATUS,RP0 MOVWF VOLTAGEL BSF FLAG1,LOWPOWER;是,置相應(yīng)標(biāo)志位 CALL POP ;中斷返回 RETFIE ;**************中斷保護(hù)現(xiàn)場(chǎng)子程序****************** PUSH MOVWF W_STACK ;暫存W寄存器 MOVF STATUS,0 ;暫存STATUS寄存器 MOVWF ST_STACK RETURN ;子程序返回 ;**************中斷恢復(fù)現(xiàn)場(chǎng)子程序************** POP MOVF ST_STACK,0 ;恢復(fù)STATUS寄存器值 MOVWF STATUS MOVF W_STACK,0 ;恢復(fù)W寄存器值 RETURN ;子程序返回 ;**************初始化子程序**************** SETUP MOVLW .15 ;初始化TEMP MOVWF TEMP MOVF ACCbHI,0 ;ACCb送ACCd MOVWF ACCdHI MOVF ACCbLO,0 MOVWF ACCdLO CLRF ACCbHI ;清ACCb CLRF ACCbLO RETLW 0 ;**********乘除法運(yùn)算確定結(jié)果符號(hào)子程序********** S_SIGN MOVF ACCaHI,0 ;ACCaHI異或ACCbHI,結(jié)果送SIGN單元 XORWF ACCbHI,0 MOVWF SIGN BTFSS ACCbHI,7 ;ACCb為負(fù)? GOTO CHEK_A ;否,檢查ACCa CALL NEG_B CHEK_A BTFSS ACCaHI,7 ;ACCa為負(fù)? RETLW 0 ;ACCa和ACCb均為負(fù),返回 GOTO NEG_A ;ACCa為負(fù),取補(bǔ)
|