开源BLHELI-S 代码详细解读(四)

本文详细介绍了嵌入式系统中多个定时器的使用,如PCA0的PWM生成,以及定时器3在零位扫描和换相操作中的角色。重点阐述了启动阶段和初始运行阶段对定时器超时时间的设置策略。
摘要由CSDN通过智能技术生成

这里涉及到一些定时器,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

下面是换相时间计算,

未完待续,

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BLHeli_S是一种广泛用于无刷电机调速器和飞行控制器的固件。通过分析BLHeli_S代码,我们可以更好地了解其工作原理和实现方式。 首先,BLHeli_S代码分析会涉及到控制器状态机的实现。BLHeli_S使用了有限状态机来管理无刷电机调速器的工作状态。这包括检测输入信号、解码PWM信号、计算和设置电机输出等功能。通过深入理解状态机的设计原则和代码结构,可以从逻辑层面上分析BLHeli_S的工作流程。 其次,代码分析还要关注BLHeli_S的参数设置和调整方法。BLHeli_S提供了许多参数,如最大电流、响应时间和电机刷新率等,可以根据具体需求进行调整。分析这些参数的具体含义和影响,对优化电机性能和飞行控制具有重要意义。 此外,BLHeli_S还使用了P-REG调速算法来控制电机速度。该算法通过自动调整比例参数,实现电机的稳定控制,并且在快速变化的环境中具有良好的响应性和鲁棒性。代码分析可以揭示出P-REG算法的实现细节和调节方法,从而更好地理解BLHeli_S的调速策略。 最后,代码分析还可以关注BLHeli_S的通信和固件升级功能。BLHeli_S支持多种通信协议,如Oneshot125、Dshot和Proshot等,可以通过串行通信与飞行控制器进行数据交换。此外,通过分析固件升级过程,可以了解如何安全地更新BLHeli_S固件以及相关的固件版本管理策略。 总而言之,BLHeli_S代码分析可以帮助我们更好地理解和使用该固件。通过深入研究其工作原理、参数设置、调速算法和通信功能,可以优化电机调速性能,并提升飞行控制的稳定性和响应性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值