这里涉及到一些定时器,PCA,说明一下它们的使用:
; 主时钟是内部24MHz振荡器(或48MHz,以下时间减半)
; 虽然代码中使用了 24/48,但确切的时钟频率是 24.5MHz 或 49.0 MHz
; 定时器 0(41.67ns 计数)始终向上计数并用于
; - RC输入信号脉冲测量
; 定时器 1(41.67ns 计数)始终向上计数并用于
; - DShot 帧同步检测
; 定时器 2(计数 500ns)始终向上计数,用于
; - RC输入信号脉冲超时计数和换相时间
; 定时器 3(计数 500ns)始终向上计数,用于
; - 换相超时
; PCA0(41.67ns 计数)始终向上计数并用于
; - 硬件 PWM 生成
; - 使用了两个道通CEX0和CEX1, 两个pwm互补。
上一篇在检查comp_out超时的时候,会调用一下零位扫描的。这里继续一起读一下。
这个 wait_before_zc_scan,其实比较简单,就是从把timer3的超时设置为Comm_Period4x_L和Comm_Period4x_H, 只有在STARTUP_PHASE和 SHL INITIAL_RUN_PHASE阶段才会设置。
特别地,如果是STARTUP_PHASE,timer3的高位寄存器会加上 64(40h).
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; 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
换相之后有一个等待,就是等t3超时
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Wait for commutation routine
;
; No assumptions
;
; Waits from zero cross to commutation
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
wait_for_comm:
; Update demag metric
mov Temp1, #0
jnb Flags0.DEMAG_DETECTED, ($+5)
mov Temp1, #1
mov A, Demag_Detected_Metric ; Sliding average of 8, 256 when demag and 0 when not. Limited to minimum 120
mov B, #7
mul AB ; Multiply by 7
mov Temp2, A
mov A, B ; Add new value for current demag status
add A,
mov B, A
mov A, Temp2
mov C, B.0 ; Divide by 8
rrc A
mov C, B.1
rrc A
mov C, B.2
rrc A
mov Demag_Detected_Metric, A
clr C
subb A, #120 ; Limit to minimum 120
jnc ($+5)
mov Demag_Detected_Metric, #120
clr C
mov A, Demag_Detected_Metric ; Check demag metric
subb A, Demag_Pwr_Off_Thresh
jc wait_for_comm_wait ; Cut power if many consecutive demags. This will help retain sync during hard accelerations
All_pwmFETs_off
Set_Pwms_Off
wait_for_comm_wait:
jnb Flags0.T3_PENDING, ($+5)
ajmp wait_for_comm_wait
; Setup next wait time
mov TMR3RLL, Wt_Zc_Scan_Start_L
mov TMR3RLH, Wt_Zc_Scan_Start_H
setb Flags0.T3_PENDING
orl EIE1, #80h ; Enable timer 3 interrupts
ret
然后我们去看看换相操作函数, 基本上就是开关fet, 设置pwm ,然后设置com,然后要是反向的话,开关的相会有所不同。
1. A/B/CcomFET_on/off的操作就是打开关闭端口,这个比较简单。
2. Set_Comp_Phase_A/B/C, 这个是通过设置CMP0MX来切换哪两个端口给比较器使用,这个上一篇有详细说明了。这里就不重复了。
3. Set_Pwm_A/B/C则是通过操作crossbar的SKIP寄存来控制pca的pwm在哪个端口输出。对P.INC的针脚布局,P0SKIP在一开始就给设置成0xFF了,就是说外设不会在P0的端口输出。 于是这里就只需要操作 P1SKIP就可以了。 如Set_Pwm_C, P1SKIP = 37h(00110111b), 即P1.3 P1.6和 P1.7会给外设使用, 根据优先度,PCA0的CEX0会使用P1.3(CpwmFET)输出 CEX1 会在P1.6(CcomFET)输出。 其它类似。Set_Pwm_B是 5Bh (01011011 BpwmFET p.2 , BcomFET P1.5 ),Set_Pwm_A 是6Dh (0110 1101 ApwmFET p.1 AcomFET p1.4.
;**** **** **** **** **** **** **** **** **** **** **** **** ****
;
; Commutation routines
;
; No assumptions
;
; Performs commutation switching
;
;**** **** **** **** **** **** **** **** **** **** **** **** ****
; Comm phase 1 to comm phase 2
comm1comm2:
Set_RPM_Out
jb Flags3.PGM_DIR_REV, comm12_rev
clr IE_EA ; Disable all interrupts
BcomFET_off ; Turn off comfet
AcomFET_on ; Turn on comfet
Set_Pwm_C ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_B ; Set comparator phase
jmp comm_exit
comm12_rev:
clr IE_EA ; Disable all interrupts
BcomFET_off ; Turn off comfet
CcomFET_on ; Turn on comfet (reverse)
Set_Pwm_A ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_B ; Set comparator phase
jmp comm_exit
; Comm phase 2 to comm phase 3
comm2comm3:
Clear_RPM_Out
jb Flags3.PGM_DIR_REV, comm23_rev
clr IE_EA ; Disable all interrupts
CpwmFET_off ; Turn off pwmfet
Set_Pwm_B ; To reapply power after a demag cut
AcomFET_on
setb IE_EA
Set_Comp_Phase_C ; Set comparator phase
ajmp comm_exit
comm23_rev:
clr IE_EA ; Disable all interrupts
ApwmFET_off ; Turn off pwmfet (reverse)
Set_Pwm_B ; To reapply power after a demag cut
CcomFET_on
setb IE_EA
Set_Comp_Phase_A ; Set comparator phase (reverse)
ajmp comm_exit
; Comm phase 3 to comm phase 4
comm3comm4:
Set_RPM_Out
jb Flags3.PGM_DIR_REV, comm34_rev
clr IE_EA ; Disable all interrupts
AcomFET_off ; Turn off comfet
CcomFET_on ; Turn on comfet
Set_Pwm_B ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_A ; Set comparator phase
jmp comm_exit
comm34_rev:
clr IE_EA ; Disable all interrupts
CcomFET_off ; Turn off comfet (reverse)
AcomFET_on ; Turn on comfet (reverse)
Set_Pwm_B ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_C ; Set comparator phase (reverse)
jmp comm_exit
; Comm phase 4 to comm phase 5
comm4comm5:
Clear_RPM_Out
jb Flags3.PGM_DIR_REV, comm45_rev
clr IE_EA ; Disable all interrupts
BpwmFET_off ; Turn off pwmfet
Set_Pwm_A ; To reapply power after a demag cut
CcomFET_on
setb IE_EA
Set_Comp_Phase_B ; Set comparator phase
jmp comm_exit
comm45_rev:
clr IE_EA ; Disable all interrupts
BpwmFET_off ; Turn off pwmfet
Set_Pwm_C
AcomFET_on ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_B ; Set comparator phase
jmp comm_exit
; Comm phase 5 to comm phase 6
comm5comm6:
Set_RPM_Out
jb Flags3.PGM_DIR_REV, comm56_rev
clr IE_EA ; Disable all interrupts
CcomFET_off ; Turn off comfet
BcomFET_on ; Turn on comfet
Set_Pwm_A ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_C ; Set comparator phase
jmp comm_exit
comm56_rev:
clr IE_EA ; Disable all interrupts
AcomFET_off ; Turn off comfet (reverse)
BcomFET_on ; Turn on comfet
Set_Pwm_C ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_A ; Set comparator phase (reverse)
jmp comm_exit
; Comm phase 6 to comm phase 1
comm6comm1:
Clear_RPM_Out
jb Flags3.PGM_DIR_REV, comm61_rev
clr IE_EA ; Disable all interrupts
ApwmFET_off ; Turn off pwmfet
Set_Pwm_C
BcomFET_on ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_A ; Set comparator phase
jmp comm_exit
comm61_rev:
clr IE_EA ; Disable all interrupts
CpwmFET_off ; Turn off pwmfet (reverse)
Set_Pwm_A
BcomFET_on ; To reapply power after a demag cut
setb IE_EA
Set_Comp_Phase_C ; Set comparator phase (reverse)
comm_exit:
ret
下面是换相时间计算,
未完待续,