我们继续来看calc_next_comm_timing, 每次操作完换相之后,这里都会调用,同时会设置timer3去等advance timing.
总体思想是根据电机运行状态计算前4次换相时间,然后根据前4次换相时间计算15度和7.5度电角度时间,换相之后延时7.5度电角度开始检测过零点,检测到过零点后延时15度电角度进行换相
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Calculate next commutation timing routine
;
; No assumptions
;
; Called immediately after each commutation
; Also sets up timer 3 to wait advance timing
; Two entry points are used
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
calc_next_comm_timing: ; Entry point for run phase
; Read commutation time
clr IE_EA
clr TMR2CN0_TR2 ; Timer 2 disabled
mov Temp1, TMR2L ; Load timer value
mov Temp2, TMR2H ; temp1, temp2取timer2当时的计数
mov Temp3, Timer2_X
jnb TMR2CN0_TF2H, ($+4) ; Check if interrupt is pending, 检查timer2的中断溢出标志要是零的话跳走,temp3不加1
inc Temp3 ; If it is pending, then timer has already wrapped, 已经超时了,Temp3+1
setb TMR2CN0_TR2 ; Timer 2 enabled, 打开timer.
setb IE_EA ;打开全部中断
IF MCU_48MHZ >= 1
clr C
mov A, Temp3
rrc A
mov Temp3, A ;Temp3 = Temp3/2
mov A, Temp2
rrc A
mov Temp2, A ;Temp2 = Temp2/2
mov A, Temp1
rrc A
mov Temp1, A ;Temp1 = Temp1/2
ENDIF
; Calculate this commutation time
mov Temp4, Prev_Comm_L ; temp4/5 赋为上次操作时间
mov Temp5, Prev_Comm_H
mov Prev_Comm_L, Temp1 ; Store timestamp as previous commutation
mov Prev_Comm_H, Temp2 ; 保存当前时间到上次操作时间到Pre_Comm_L/H
clr C
mov A, Temp1
subb A, Temp4 ; Calculate the new commutation time
mov Temp1, A
mov A, Temp2
subb A, Temp5 ;当前时间减去上次时间,结果在temp1,和A.
jb Flags1.STARTUP_PHASE, calc_next_comm_startup ;如果启动阶段,跳走。
IF MCU_48MHZ >= 1
anl A, #7Fh ;如果48Mhz, 高位 & 7Fh
ENDIF
mov Temp2, A ;保存高位到Temp2
jnb Flags1.HIGH_RPM, ($+5) ; Branch if high rpm ,
ajmp calc_next_comm_timing_fast ; 是高rpm,跳到calc_next_comm_timing_fast
ajmp calc_next_comm_normal ; 如果不是高rpm,跳到calc_next_comm_normal
calc_next_comm_startup:
mov Temp6, Prev_Comm_X
mov Prev_Comm_X, Temp3 ; Store extended timestamp as previous commutation
mov Temp2, A
mov A, Temp3
subb A, Temp6 ; Calculate the new extended commutation time
IF MCU_48MHZ >= 1
anl A, #7Fh ;如果48Mhz, 高位 & 7Fh
ENDIF
mov Temp3, A
jz calc_next_comm_startup_no_X
mov Temp1, #0FFh
mov Temp2, #0FFh
ajmp calc_next_comm_startup_average
calc_next_comm_startup_no_X:
mov Temp7, Prev_Prev_Comm_L
mov Temp8, Prev_Prev_Comm_H
mov Prev_Prev_Comm_L, Temp4
mov Prev_Prev_Comm_H, Temp5
mov Temp1, Prev_Comm_L ; Reload this commutation time
mov Temp2, Prev_Comm_H
clr C
mov A, Temp1
subb A, Temp7 ; Calculate the new commutation time based upon the two last commutations (to reduce sensitivity to offset)
mov Temp1, A
mov A, Temp2
subb A, Temp8
mov Temp2, A
calc_next_comm_startup_average:
clr C
mov A, Comm_Period4x_H ; Average with previous and save
rrc A
mov Temp4, A
mov A, Comm_Period4x_L
rrc A
mov Temp3, A
mov A, Temp1
add A, Temp3
mov Comm_Period4x_L, A
mov A, Temp2
addc A, Temp4
mov Comm_Period4x_H, A
jnc ($+8)
mov Comm_Period4x_L, #0FFh
mov Comm_Period4x_H, #0FFh
ajmp calc_new_wait_times_setup
calc_next_comm_normal:
; Calculate new commutation time
mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
mov Temp4, Comm_Period4x_H
mov Temp5, Comm_Period4x_L ; Copy variables
mov Temp6, Comm_Period4x_H
mov Temp7, #4 ; Divide Comm_Period4x 4 times as default
mov Temp8, #2 ; Divide new commutation time 2 times as default
clr C
mov A, Temp4
subb A, #04h
jc calc_next_comm_avg_period_div
dec Temp7 ; Reduce averaging time constant for low speeds
dec Temp8
clr C
mov A, Temp4
subb A, #08h
jc calc_next_comm_avg_period_div
jb Flags1.INITIAL_RUN_PHASE, calc_next_comm_avg_period_div ; Do not average very fast during initial run
dec Temp7 ; Reduce averaging time constant more for even lower speeds
dec Temp8
calc_next_comm_avg_period_div:
clr C
mov A, Temp6
rrc A ; Divide by 2
mov Temp6, A
mov A, Temp5
rrc A
mov Temp5, A
djnz Temp7, calc_next_comm_avg_period_div
clr C
mov A, Temp3
subb A, Temp5 ; Subtract a fraction
mov Temp3, A
mov A, Temp4
subb A, Temp6
mov Temp4, A
mov A, Temp8 ; Divide new time
jz calc_next_comm_new_period_div_done
calc_next_comm_new_period_div:
clr C
mov A, Temp2
rrc A ; Divide by 2
mov Temp2, A
mov A, Temp1
rrc A
mov Temp1, A
djnz Temp8, calc_next_comm_new_period_div
calc_next_comm_new_period_div_done:
mov A, Temp3
add A, Temp1 ; Add the divided new time
mov Temp3, A
mov A, Temp4
addc A, Temp2
mov Temp4, A
mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
mov Comm_Period4x_H, Temp4
jnc calc_new_wait_times_setup; If period larger than 0xffff - go to slow case
mov Temp4, #0FFh
mov Comm_Period4x_L, Temp4 ; Set commutation period registers to very slow timing (0xffff)
mov Comm_Period4x_H, Temp4
calc_new_wait_times_setup:
; Set high rpm bit (if above 156k erpm)
clr C
mov A, Temp4
subb A, #2
jnc ($+4)
setb Flags1.HIGH_RPM ; Set high rpm bit
; Load programmed commutation timing
jnb Flags1.STARTUP_PHASE, calc_new_wait_per_startup_done ; Set dedicated timing during startup
mov Temp8, #3
ajmp calc_new_wait_per_demag_done
calc_new_wait_per_startup_done:
mov Temp1, #Pgm_Comm_Timing ; Load timing setting
mov A, @Temp1
mov Temp8, A ; Store in Temp8
clr C
mov A, Demag_Detected_Metric ; Check demag metric
subb A, #130
jc calc_new_wait_per_demag_done
inc Temp8 ; Increase timing
clr C
mov A, Demag_Detected_Metric
subb A, #160
jc ($+3)
inc Temp8 ; Increase timing again
clr C
mov A, Temp8 ; Limit timing to max
subb A, #6
jc ($+4)
mov Temp8, #5 ; Set timing to max
calc_new_wait_per_demag_done:
; Set timing reduction
mov Temp7, #2
; Load current commutation timing
mov A, Comm_Period4x_H ; Divide 4 times
swap A
anl A, #00Fh
mov Temp2, A
mov A, Comm_Period4x_H
swap A
anl A, #0F0h
mov Temp1, A
mov A, Comm_Period4x_L
swap A
anl A, #00Fh
add A, Temp1
mov Temp1, A
clr C
mov A, Temp1
subb A, Temp7
mov Temp3, A
mov A, Temp2
subb A, #0
mov Temp4, A
jc load_min_time ; Check that result is still positive
clr C
mov A, Temp3
subb A, #1
mov A, Temp4
subb A, #0
jnc calc_new_wait_times_exit ; Check that result is still above minumum
load_min_time:
mov Temp3, #1
clr A
mov Temp4, A
calc_new_wait_times_exit:
ljmp wait_advance_timing
; Fast calculation (Comm_Period4x_H less than 2)
calc_next_comm_timing_fast:
; Calculate new commutation time
mov Temp3, Comm_Period4x_L ; Comm_Period4x(-l-h) holds the time of 4 commutations
mov Temp4, Comm_Period4x_H
mov A, Temp4 ; Divide by 2 4 times
swap A
mov Temp7, A
mov A, Temp3
swap A
anl A, #0Fh
orl A, Temp7
mov Temp5, A
clr C
mov A, Temp3 ; Subtract a fraction
subb A, Temp5
mov Temp3, A
mov A, Temp4
subb A, #0
mov Temp4, A
clr C
mov A, Temp1
rrc A ; Divide by 2 2 times
clr C
rrc A
mov Temp1, A
mov A, Temp3 ; Add the divided new time
add A, Temp1
mov Temp3, A
mov A, Temp4
addc A, #0
mov Temp4, A
mov Comm_Period4x_L, Temp3 ; Store Comm_Period4x_X
mov Comm_Period4x_H, Temp4
clr C
mov A, Temp4 ; If erpm below 156k - go to normal case
subb A, #2
jc ($+4)
clr Flags1.HIGH_RPM ; Clear high rpm bit
; Set timing reduction
mov Temp1, #2
mov A, Temp4 ; Divide by 2 4 times
swap A
mov Temp7, A
mov Temp4, #0
mov A, Temp3
swap A
anl A, #0Fh
orl A, Temp7
mov Temp3, A
clr C
mov A, Temp3
subb A, Temp1
mov Temp3, A
jc load_min_time_fast ; Check that result is still positive
clr C
subb A, #1
jnc calc_new_wait_times_fast_done ; Check that result is still above minumum
load_min_time_fast:
mov Temp3, #1
calc_new_wait_times_fast_done:
mov Temp1, #Pgm_Comm_Timing ; Load timing setting
mov A, @Temp1
mov Temp8, A ; Store in Temp8
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Wait advance timing routine
;
; No assumptions
; NOTE: Be VERY careful if using temp registers. They are passed over this routine
;
; Waits for the advance timing to elapse and sets up the next zero cross wait
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
wait_advance_timing:
jnb Flags0.T3_PENDING, ($+5)
ajmp wait_advance_timing
; Setup next wait time
mov TMR3RLL, Wt_ZC_Tout_Start_L
mov TMR3RLH, Wt_ZC_Tout_Start_H
setb Flags0.T3_PENDING
orl EIE1, #80h ; Enable timer 3 interrupts
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Calculate new wait times routine
;
; No assumptions
;
; Calculates new wait times
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
calc_new_wait_times:
clr C
clr A
subb A, Temp3 ; Negate
mov Temp1, A
clr A
subb A, Temp4
mov Temp2, A
IF MCU_48MHZ >= 1
clr C
mov A, Temp1 ; Multiply by 2
rlc A
mov Temp1, A
mov A, Temp2
rlc A
mov Temp2, A
ENDIF
jnb Flags1.HIGH_RPM, ($+6) ; Branch if high rpm
ljmp calc_new_wait_times_fast
mov A, Temp1 ; Copy values
mov Temp3, A
mov A, Temp2
mov Temp4, A
setb C ; Negative numbers - set carry
mov A, Temp2
rrc A ; Divide by 2
mov Temp6, A
mov A, Temp1
rrc A
mov Temp5, A
mov Wt_Zc_Tout_Start_L, Temp1; Set 15deg time for zero cross scan timeout
mov Wt_Zc_Tout_Start_H, Temp2
clr C
mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
subb A, #3 ; Is timing normal?
jz store_times_decrease ; Yes - branch
mov A, Temp8
jb ACC.0, adjust_timing_two_steps ; If an odd number - branch
mov A, Temp1 ; Add 7.5deg and store in Temp1/2
add A, Temp5
mov Temp1, A
mov A, Temp2
addc A, Temp6
mov Temp2, A
mov A, Temp5 ; Store 7.5deg in Temp3/4
mov Temp3, A
mov A, Temp6
mov Temp4, A
jmp store_times_up_or_down
adjust_timing_two_steps:
mov A, Temp1 ; Add 15deg and store in Temp1/2
add A, Temp1
mov Temp1, A
mov A, Temp2
addc A, Temp2
mov Temp2, A
clr C
mov A, Temp1
add A, #1
mov Temp1, A
mov A, Temp2
addc A, #0
mov Temp2, A
mov Temp3, #-1 ; Store minimum time in Temp3/4
mov Temp4, #0FFh
store_times_up_or_down:
clr C
mov A, Temp8
subb A, #3 ; Is timing higher than normal?
jc store_times_decrease ; No - branch
store_times_increase:
mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
mov Wt_Comm_Start_H, Temp4
mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
mov Wt_Adv_Start_H, Temp2
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
mov Wt_Zc_Scan_Start_H, Temp6
ljmp wait_before_zc_scan
store_times_decrease:
mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
mov Wt_Comm_Start_H, Temp2
mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
mov Wt_Adv_Start_H, Temp4
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
mov Wt_Zc_Scan_Start_H, Temp6
jnb Flags1.STARTUP_PHASE, store_times_exit
mov Wt_Comm_Start_L, #0F0h ; Set very short delays for all but advance time during startup, in order to widen zero cross capture range
mov Wt_Comm_Start_H, #0FFh
mov Wt_Zc_Scan_Start_L, #0F0h
mov Wt_Zc_Scan_Start_H, #0FFh
mov Wt_Zc_Tout_Start_L, #0F0h
mov Wt_Zc_Tout_Start_H, #0FFh
store_times_exit:
ljmp wait_before_zc_scan
calc_new_wait_times_fast:
mov A, Temp1 ; Copy values
mov Temp3, A
setb C ; Negative numbers - set carry
mov A, Temp1 ; Divide by 2
rrc A
mov Temp5, A
mov Wt_Zc_Tout_Start_L, Temp1; Set 15deg time for zero cross scan timeout
clr C
mov A, Temp8 ; (Temp8 has Pgm_Comm_Timing)
subb A, #3 ; Is timing normal?
jz store_times_decrease_fast; Yes - branch
mov A, Temp8
jb ACC.0, adjust_timing_two_steps_fast ; If an odd number - branch
mov A, Temp1 ; Add 7.5deg and store in Temp1
add A, Temp5
mov Temp1, A
mov A, Temp5 ; Store 7.5deg in Temp3
mov Temp3, A
ajmp store_times_up_or_down_fast
adjust_timing_two_steps_fast:
mov A, Temp1 ; Add 15deg and store in Temp1
add A, Temp1
add A, #1
mov Temp1, A
mov Temp3, #-1 ; Store minimum time in Temp3
store_times_up_or_down_fast:
clr C
mov A, Temp8
subb A, #3 ; Is timing higher than normal?
jc store_times_decrease_fast; No - branch
store_times_increase_fast:
mov Wt_Comm_Start_L, Temp3 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
mov Wt_Adv_Start_L, Temp1 ; New commutation advance time (~15deg nominal)
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
ljmp wait_before_zc_scan
store_times_decrease_fast:
mov Wt_Comm_Start_L, Temp1 ; Now commutation time (~60deg) divided by 4 (~15deg nominal)
mov Wt_Adv_Start_L, Temp3 ; New commutation advance time (~15deg nominal)
mov Wt_Zc_Scan_Start_L, Temp5 ; Use this value for zero cross scan delay (7.5deg)
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Wait before zero cross scan routine
;
; No assumptions
;
; Waits for the zero cross scan wait time to elapse
; Also sets up timer 3 for the zero cross scan timeout time
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
wait_before_zc_scan:
jnb Flags0.T3_PENDING, ($+5) ;jump if Flags0.T3_PENDING is zero
ajmp wait_before_zc_scan
mov Startup_Zc_Timeout_Cntd, #2
setup_zc_scan_timeout:
setb Flags0.T3_PENDING
orl EIE1, #80h ; Enable timer 3 interrupts
mov A, Flags1
anl A, #((1 SHL STARTUP_PHASE)+(1 SHL INITIAL_RUN_PHASE))
jz wait_before_zc_scan_exit
mov Temp1, Comm_Period4x_L ; Set long timeout when starting
mov Temp2, Comm_Period4x_H
clr C
mov A, Temp2
rrc A
mov Temp2, A
mov A, Temp1
rrc A
mov Temp1, A
IF MCU_48MHZ == 0
clr C
mov A, Temp2
rrc A
mov Temp2, A
mov A, Temp1
rrc A
mov Temp1, A
ENDIF
jnb Flags1.STARTUP_PHASE, setup_zc_scan_timeout_startup_done
mov A, Temp2
add A, #40h ; Increase timeout somewhat to avoid false wind up
mov Temp2, A
setup_zc_scan_timeout_startup_done:
clr IE_EA
anl EIE1, #7Fh ; Disable timer 3 interrupts
mov TMR3CN0, #00h ; Timer 3 disabled and interrupt flag cleared
clr C
clr A
subb A, Temp1 ; Set timeout
mov TMR3L, A
clr A
subb A, Temp2
mov TMR3H, A
mov TMR3CN0, #04h ; Timer 3 enabled and interrupt flag cleared
setb Flags0.T3_PENDING
orl EIE1, #80h ; Enable timer 3 interrupts
setb IE_EA
wait_before_zc_scan_exit:
ret