📄 sensbldc.asm
字号:
;**********************************************************************
;* *
;用此软件控制高压直流无刷电机的运转(2007/5/7)
;* *
;**********************************************************************
; Filename: SensBLDC.asm *
;**********************************************************************
; Files required: p16f877.inc *
;**********************************************************************
; Notes: Sensored brushless motor control *
;**********************************************************************
list p=16f877 ; list directive to define processor
#include <p16f877.inc> ; processor specific variable definitions
;**********************************************************************
;*
;* Define variable storage
;*
CBLOCK 0x20
ADC ; PWM threshold is ADC result
adctemp ;当前ADC的值
LastSensor ; last read motor sensor data
DriveWord ; six bit motor drive data
sensortemp
flag
delaycount1
delaycount2
timer2ifcount
ENDC
;**********************************************************************
;*
;* Define I/O
;*
#define OffMask B'00000000'
#define DrivePort PORTB
#define DrivePortTris TRISB
#define SensorMask B'00000111' ;RA2,RA3,RA4分别对应SA,SB,SC
#define SensorPort PORTA
#define led1 portd,0 ;灯1
#define led2 portd,1 ;灯2
#define led3 portd,2 ;灯3
#define RUNSTOPKEY PORTD,6 ;运行停止键
#define directionkey portd,7 ;改变方向键
#define directionbit flag,0 ;方向标志位
#define runstopbit flag,1 ;运行标志,1代表运行,0代表停止
#define starttime flag,2 ;软启动开始
#define errorflag flag,3 ;错误标志
#define led4 portc,0 ;灯4
#define overcurrent portc,1 ;过流检测
#define voltagefault portc,2 ;电压检测
#define overtemp porte,2 ;IGBT模块温度检测
#define startadc d'40' ;电机启动时的ADC
#define startendadc d'200' ;电机启动结束时的ADC
#define deltadc d'8' ;启动时增加的ADC
#define adcmin d'40'
#define deltstopadc d'8' ;停止时减小的ADC
;**********************************************************************
org 0x000 ; startup vector
nop ; required for ICD operation
clrf PCLATH ; ensure page bits are cleared
goto Initialize ; go to beginning of program
ORG 0x004 ; interrupt vector location
retfie ; return from interrupt
;**********************************************************************
;*
;* Initialize I/O ports and peripherals
;*
Initialize
clrf DrivePort ; all drivers off
banksel TRISA
; setup I/O
MOVLW B'11000000' ;PORTD7,6输入,其他输出
movwf trisd
MOVLW B'11111110' ;PORTC0输出,其他输入
MOVWF TRISC
clrf DrivePortTris ; set motor drivers as outputs
movlw B'00011111' ; A/D on RA1, Motor sensors on RA<4:2>
movwf TRISA ;
; setup Timer0
movlw B'11010000' ; Timer0: Fosc, 1:2
movwf OPTION_REG
; Setup ADC (bank1)
movlw B'00001110' ; ADC left justified, AN0 ONLY
movwf ADCON1
banksel ADCON0
; setup ADC (bank0)
movlw B'11000001' ; ADC clock from int RC, AN0, ADC on
movwf ADCON0
bsf ADCON0,GO ; start ADC
movlw b'01111111' ;timer2的prescale为1:16,后分频比为1:16,on,
movwf t2con ;用于判断电机是否堵转
clrf portd
clrf flag
clrf LastSensor ; initialize last sensor reading
call Commutate ; determine present motor positon
clrf ADC ; start speed control threshold at zero until first ADC reading
bsf led1 ;灯1亮
bcf led2
bcf led3
bcf led4
mainloop
btfss runstopkey ;按下runstopkey?
goto mainrunloop
btfss directionkey ;按下DIRECTIONKEY
call directionsub ;是的则DIRECTIONSUB
goto mainloop
mainrunloop ;运行
bcf errorflag
bcf led2
bcf led3
bcf led4
call readadcsub
bsf led2
clrf tmr2
clrf timer2ifcount
clrf tmr1L ;TIMER1为0
clrf tmr1h
bsf t1con,tmr1on ;启动TIMER1
bsf starttime ;电机处于起动时间
movlw STARTADC ;开始启动时ADC的值
movwf adc
increaserun ;加速运行(软启动)
btfss starttime ;起动结束?
goto normalrun ;正常运转
BTFSs PIR1,TMR1IF ;TIMER1时间到
goto normalrun ;正常运转
bcf pir1,tmr1if ;清除tmr1if
movlw deltadc
addwf adc,f
btfsc status,c ;是否超过255?
goto adcgeadctemp ;是的则ADC>=ADCTEMP
movlw startendadc ;没有超过则比较startendadc
subwf adc,w
btfss status,c
goto normalrun ;adc<startendadc
adcgeadctemp ;adc>=startendadc
movf adctemp,w
movwf adc
bcf starttime
bcf t1con,tmr1on ;关闭TIMER1的运行
normalrun
btfss starttime
call readadcsub ;运行时读取ADCTEMP
call runsub
btfss voltagefault ;如电压超过242V或低于170V则电机停止运转
goto voltagefaultstoprun
btfsc errorflag
goto errorstoprun
btfsc directionkey ;是否停止?
goto increaserun
goto stoprun
errorstoprun
bsf led4
goto stoprun
voltagefaultstoprun
bsf led4
bsf led3
stoprun
call norunsub ;减速停止
bcf led2
call delaysub
call delaysub
goto mainloop
;运行停止标志改变子程序
RUNSTOPSUB
CALL DELAYSUB ;
btfsc runstopkey
return
movlw b'00000010'
xorwf flag,f
return
;方向标志改变子程序
directionsub
call delaysub
btfsc directionkey
return
movlw b'00000001'
xorwf flag,f
return
delaysub
movlw d'50'
movwf delaycount1
delayloop1
movlw d'100'
movwf delaycount2
delayloop2
decfsz delaycount2
goto delayloop2
decfsz delaycount1
goto delayloop1
return
norunsub
clrf tmr1L ;TIMER1为0
clrf tmr1h
bsf t1con,tmr1on ;启动TIMER1
decreaserun ;减速运行(软停止)
BTFSs PIR1,TMR1IF ;TIMER1时间到
goto decreaserunbranch1 ;正常运转
bcf pir1,tmr1if ;清除tmr1if
movlw deltstopadc
subwf adc,f
btfss status,c ;是否小于0
goto enddecreaserun
decreaserunbranch1
call runsub
goto decreaserun
enddecreaserun
bcf t1con,tmr1on ;关闭TIMER1的运行
clrf driveport
bcf runstopbit
return
;运行子程序
runsub
call Commutate ; test for commutation change
incfsz ADC,w ; if ADC is 0xFF we're at full speed - skip timer add
goto PWM ; add timer 0 to ADC for PWM
movf DriveWord,w ; force on condition
goto Drive ; continue
PWM
movf ADC,w ; restore ADC reading
addwf TMR0,w ; add it to current timer0
movf DriveWord,w ; restore commutation drive data
btfss STATUS,C ; test if ADC + timer0 resulted in carry
andlw OffMask ; no carry - supress high,low drivers
Drive
btfsc overcurrent ;过流?
goto drive2
andlw offmask
bsf led3
goto drive1
drive2
bcf led3
drive1
movwf DrivePort ; enable motor drivers
; return
lockcheck
btfss pir1,tmr2if ;timer2溢出
return ;没有则返回
bcf pir1,tmr2if
incf timer2ifcount,f
movlw d'100'
subwf timer2ifcount,w
btfss status,c ;timer2ifcount>某一固定值
return ;不是则返回
bsf errorflag ;是则电机发生错误
clrf driveport ;电机停止运转
clrf timer2ifcount
clrf tmr2
bsf led4
return
ReadADCsub
;**********************************************************************
;*
;* If the ADC is ready then read the speed control potentiometer
;* and start the next reading
;*
btfsc ADCON0,NOT_DONE ; is ADC ready?
return ; no - return
movf ADRESH,w ; get ADC result
bsf ADCON0,GO ; restart ADC
movwf ADC ; save result in speed control threshold
movlw adcmin
subwf adc,w ;adc<adcmin?
btfsc status,c
goto adcgeadcmin
movlw adcmin ;adc<adcmin则ADC=ADCMIN
movwf adctemp
movwf adc
return
adcgeadcmin ;adc>=adcmin
movf adc,w
movwf adctemp
return
;**********************************************************************
;*
;* Read the sensor inputs and if a change is sensed then get the
;* corresponding drive word from the drive table
;*
Commutate
movf sensorport,w
movwf sensortemp
rrf sensortemp,f
rrf sensortemp,f
movlw SensorMask ; retain only the sensor bits
andwf Sensortemp,w ; get sensor data
xorwf LastSensor,w ; test if motion sensed
btfsc STATUS,Z ; zero if no change
return ; no change - back to the PWM loop
clrf tmr2
clrf timer2ifcount
xorwf LastSensor,f ; replace last sensor data with current
btfss DirectionBit ; test direction bit
goto FwdCom ; bit is zero - do forward commutation
; reverse commutation
movlw HIGH RevTable ; get MS byte of table
movwf PCLATH ; prepare for computed GOTO
movlw LOW RevTable ; get LS byte of table
goto Com2
FwdCom ; forward commutation
movlw HIGH FwdTable ; get MS byte of table
movwf PCLATH ; prepare for computed GOTO
movlw LOW FwdTable ; get LS byte of table
Com2
addwf LastSensor,w ; add sensor offset
btfsc STATUS,C ; page change in table?
incf PCLATH,f ; yes - adjust MS byte
call GetDrive ; get drive word from table
movwf DriveWord ; save as current drive word
return
GetDrive
movwf PCL
;**********************************************************************
;*
;* The drive tables are built based on the following assumptions:
;* 1) There are six drivers in three pairs of two
;* 2) Each driver pair consists of a high side (+V to motor) and low side (motor to ground) drive
;*3)ra2=sa,ra3=sb,ra4=sc
;*4)portb(5.4.3.2.1.0)控制L3.H3.H2.L2.H1.L1
FwdTable
retlw B'00000000' ; invalid(000)
retlw B'00100010' ; scsbsa(001)
retlw B'00001001' ; scsbsa(010)
retlw B'00101000' ; scsbsa(011)
retlw B'00010100' ; scsbsa(100)
retlw B'00000110' ; scsbsa(101)
retlw B'00010001' ; scsbsa(110)
retlw B'00000000' ; invalid(111)
RevTable
retlw B'00000000' ; invalid(000)
retlw B'00010001' ; scsbsa(001)/
retlw B'00000110' ; scsbsa(010)/
retlw B'00010100' ; scsbsa(011)/
retlw B'00101000' ; scsbsa(100)/
retlw B'00001001' ; scsbsa(101)/
retlw B'00100010' ; scsbsa(110)/
retlw B'00000000' ; invalid(111)
END ; directive 'end of program'
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -