⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bl-4428.asm

📁 Atmel Atmega128 processor brushless controller source code with compiler hints.
💻 ASM
📖 第 1 页 / 共 2 页
字号:

nFET_off:	sbr	flags0, (1<<I_OFF_CYCLE) ; PWM state = off cycle

	; switch appropriate nFET off
		sbrs	flags0, C_FET
		rjmp	test_AnFET

; C_FET is active
		sbrs	flags1, FULL_POWER
		CnFET_off		; Cn off
		rjmp	reload_t0_off_cycle

test_AnFET:	sbrs	flags0, A_FET
		rjmp	switch_BnFET

; A_FET is active
switch_AnFET:	sbrs	flags1, FULL_POWER
		AnFET_off		; An off
		rjmp	reload_t0_off_cycle

; B_FET is active
switch_BnFET:	sbrs	flags1, FULL_POWER
		BnFET_off		; Bn off

	; reload timer0 with the appropriate value
reload_t0_off_cycle:
		mov	i_temp1, tcnt0_power_on
		subi	i_temp1, -POWER_RANGE	; adi i_temp1, POWER_RANGE
		com	i_temp1			; timer0 increments
		out	TCNT0, i_temp1

		rjmp	t0_int_exit

; reload timer90 + switch appropriate nFET on
t0_on_cycle:	mov	i_temp1, tcnt0_power_on
		out	TCNT0, i_temp1		; reload t0
		cbr	flags0, (1<<I_OFF_CYCLE) ; PWM state = on cycle (no off cycle)

; switch appropriate nFET on
nFET_on:	sbrs	flags0, C_FET		; is Cn choppered ?
		rjmp	test_AnFET_on			; .. no - test An
		sbrs	flags1, POWER_OFF
		CnFET_on		; Cn on
		rjmp	eval_power_state
test_AnFET_on:	sbrs	flags0, A_FET		; is An choppered ?
		rjmp	sw_BnFET_on			; .. no - Bn has to be choppered
		sbrs	flags1, POWER_OFF
		AnFET_on		; An on
		rjmp	eval_power_state
sw_BnFET_on:	sbrs	flags1, POWER_OFF
		BnFET_on		; Bn on

	; evaluate power state
eval_power_state:
		cpi	i_temp1, MAX_POWER+1
		brsh	not_full_power
	; FULL POWER
		sbr	flags1, (1<<FULL_POWER)	; tcnt0_power_on = MAX_POWER means FULL_POWER
		cbr	flags1, (1<<POWER_OFF)
		rjmp	t0_int_exit
not_full_power:	cpi	i_temp1, NO_POWER
		brlo	neither_full_nor_off
	; POWER OFF
		cbr	flags1, (1<<FULL_POWER)	; tcnt0_power_on = NO_POWER means power off
		sbr	flags1, (1<<POWER_OFF)
		rjmp	t0_int_exit
neither_full_nor_off:
		cbr	flags1, (1<<FULL_POWER)	; tcnt0_power_on = MAX_POWER means FULL_POWER
		cbr	flags1, (1<<POWER_OFF)

t0_int_exit:	sbrc	flags2, POFF_CYCLE
		sbr	flags1, (1<<POWER_OFF)
		out	SREG, i_sreg
		reti
;-----bko-----------------------------------------------------------------
urxc:		in	i_sreg, SREG
		in	i_temp1, UDR

		dec motor_total ; #HH#

		cpi	i_temp1, 0xf5
		breq	x3d_sync
		brcc	unknown_cmd

		sbrc	flags2, NO_SYNC
		rjmp	urxc_exit		; trough away
		dec	motor_count
		brne	urxc_exit

; 10kHz do nothing range is 0-200
;		mov	ZH, i_temp1

; 16kHz range is 0-125 - divide by 2 and add a quarter
		lsr	i_temp1				; 0-200 ==> 0-100
		mov	i_temp2, i_temp1
		lsr	i_temp2
		lsr	i_temp2
		add	i_temp1, i_temp2
		mov	ZH, i_temp1

; 20kHz range is 0-100 - divide by 2
;		lsr	i_temp1				; 0-200 ==> 0-100
;		mov	ZH, i_temp1

		ldi	i_temp2, MOTOR_NUMBER
		mov	motor_count, i_temp2
		sbr	flags2, (1<<NO_SYNC)
		ldi	i_temp1, CONTROL_TOT
		mov	control_timeout, i_temp1
		rjmp	urxc_exit

unknown_cmd:	sts	uart_command, i_temp1
		rjmp	urxc_exit

x3d_sync:	cbr	flags2, (1<<NO_SYNC)
    mov i_temp1, motor_total
    cpi i_temp1, 0x00
    breq x3d_sync_ok
    
    HHDEBUGLED_on
    rjmp x3d_sync_finish
    
x3d_sync_ok: HHDEBUGLED_off

x3d_sync_finish:
    ldi i_temp1, MOTOR_MAX
    mov motor_total, i_temp1

urxc_exit:	out	SREG, i_sreg
		reti

utxc:		in	i_sreg, SREG
		ld	i_temp1,X+
		out	UDR, i_temp1
		dec	uart_cnt
		brne	utxc_90
		cbi	UCSRB, TXCIE		; disable irq
utxc_90:	out	SREG, i_sreg
		reti
;-----bko-----------------------------------------------------------------
; beeper: timer0 is set to 1祍/count
beep_f1:	ldi	temp4, 200
		ldi	temp2, 80
		rjmp	beep

beep_f2:	ldi	temp4, 180
		ldi	temp2, 100
		rjmp	beep

beep_f3:	ldi	temp4, 160
		ldi	temp2, 120
		rjmp	beep

beep_f4:	ldi	temp4, 100
		ldi	temp2, 200
		rjmp	beep

beep:		clr	temp1
		out	TCNT0, temp1
		BpFET_on		; BpFET on
		AnFET_on		; CnFET on
beep_BpCn10:	in	temp1, TCNT0
		cpi	temp1, 64		; 32祍 on
		brne	beep_BpCn10
		BpFET_off		; BpFET off
		AnFET_off		; CnFET off
		ldi	temp3, 16		; 2040祍 off
beep_BpCn12:	clr	temp1
		out	TCNT0, temp1
beep_BpCn13:	in	temp1, TCNT0
		cp	temp1, temp4
		brne	beep_BpCn13
		dec	temp3
		brne	beep_BpCn12
		dec	temp2
		brne	beep
		ret

wait30ms:	ldi	temp2, 30
beep_BpCn20:	ldi	temp3, 16
beep_BpCn21:	clr	temp1
		out	TCNT0, temp1
beep_BpCn22:	in	temp1, TCNT0
		cpi	temp1, 255
		brne	beep_BpCn22
		dec	temp3
		brne	beep_BpCn21
		dec	temp2
		brne	beep_BpCn20
		ret

	; 256 periods = 261ms silence
wait260ms:	ldi	temp2, 0	; = 256
beep2_BpCn20:	ldi	temp3, 16
beep2_BpCn21:	clr	temp1
		out	TCNT0, temp1
beep2_BpCn22:	in	temp1, TCNT0
		cpi	temp1, 255
		brne	beep2_BpCn22
		dec	temp3
		brne	beep2_BpCn21
		dec	temp2
		brne	beep2_BpCn20
		ret
;-----bko-----------------------------------------------------------------
tcnt1_to_temp:	ldi	temp4, T1STOP		; stop timer1
		out	TCCR1B, temp4
		ldi	temp4, T1CK8		; preload temp with restart timer1
		in	temp1, TCNT1L		;  - the preload cycle is needed to complete stop operation
		in	temp2, TCNT1H
		out	TCCR1B, temp4
		ret				; !!! ext0int stays disabled - must be enabled again by caller
	; there seems to be only one TEMP register in the AVR
	; if the ext0int interrupt falls between readad LOW value while HIGH value is captured in TEMP and
	; read HIGH value, TEMP register is changed in ext0int routine
;-----bko-----------------------------------------------------------------
evaluate_sys_state:
		cbr	flags1, (1<<EVAL_SYS_STATE)
		sbrs	flags0, T1OVFL_FLAG
		rjmp	eval_sys_s99

	; do it not more often as every 32祍
		cbr	flags0, (1<<T1OVFL_FLAG)

		rjmp	eval_sys_s99		; disabled ;-)

	; control current
eval_sys_i:	rjmp	eval_sys_i_ok

		mov	temp1, current_err
		cpi	temp1, CURRENT_ERR_MAX
		brcc	panic_exit
		inc	current_err
		rjmp	eval_sys_ub

eval_sys_i_ok:	tst	current_err
		breq	eval_sys_ub
		dec	current_err

	; control voltage
eval_sys_ub:	rjmp	eval_sys_ub_ok

		mov	temp1, sys_control
		cpi	temp1, POWER_RANGE
		brcc	eval_sys_s99
		inc	sys_control
		rjmp	eval_sys_s99

eval_sys_ub_ok:	tst	sys_control
		breq	eval_sys_s99
		dec	sys_control
		
eval_sys_s99:	ret

panic_exit:	; !!!!!! OVERCURRENT !!!!!!!!
		cli
		rjmp	reset
;-----bko-----------------------------------------------------------------
set_new_duty:	mov	temp1, ZH
		sub	temp1, sys_control
		brcc	set_new_duty10
		ldi	temp1, MIN_DUTY-1
	; evaluate RPM range
set_new_duty10:	lds	temp2, timing_x
		tst	temp2
		brne	set_new_duty12
		lds	temp2, timing_h	; get actual RPM reference high
		cpi	temp2, PWR_RANGE1	; lower range1 ?
		brcs	set_new_duty20		; on carry - test next range
	; lower as range1
set_new_duty12:	sbr	flags2, (1<<RPM_RANGE1)
		sbr	flags2, (1<<RPM_RANGE2)
		ldi	temp2, PWR_MAX_RPM1	; higher than range1 power max ?
		cp	temp1, temp2
		brcs	set_new_duty40		; on carry - not higher, no restriction
		mov	temp1, temp2		; low (range1) RPM - set PWR_MAX_RPM1
		rjmp	set_new_duty40
	; higher as range1
set_new_duty20:	cpi	temp2, PWR_RANGE2	; lower range2 ?
		brcs	set_new_duty30		; on carry - not lower, no restriction
set_new_duty22:	cbr	flags2, (1<<RPM_RANGE1)
		sbr	flags2, (1<<RPM_RANGE2)
		ldi	temp2, PWR_MAX_RPM2	; higher than range2 power max ?
		cp	temp1, temp2
		brcs	set_new_duty40		; on carry - not higher, no restriction
		mov	temp1, temp2		; low (range2) RPM - set PWR_MAX_RPM2
		rjmp	set_new_duty40
	; higher as range2
set_new_duty30:	cbr	flags2, (1<<RPM_RANGE1)+(1<<RPM_RANGE2)
	; range limits are evaluated - look for STARTUP conditions
set_new_duty40:	sbrs	flags2, STARTUP
		rjmp	set_new_duty50
		ldi	temp3, PWR_STARTUP	; at least PWR_STARTUP ?
		cp	temp1, temp3
		brcc	set_new_duty42		; on no carry - higher than PWR_STARTUP, test PWR_MAX_STARTUP
		ldi	temp1, PWR_STARTUP	; lower - set to PWR_STARTUP
		rjmp	set_new_duty50
set_new_duty42:	ldi	temp3, PWR_MAX_STARTUP	; limit power in startup phase
		cp	temp1, temp3
		brcs	set_new_duty50		; on carry - not higher, test range 2
		mov	temp1, temp3		; set PWR_MAX_STARTUP limit

set_new_duty50:	com	temp1			; down-count to up-count (T0)
		mov	tcnt0_pwron_next, temp1	; save in next
	; tcnt0_power_on is updated to tcnt0_pwron_next in acceptable steps
		ret
;-----bko-----------------------------------------------------------------
evaluate_rpm:	cbr	flags1, (1<<EVAL_RPM)
		lds	temp3, rpm_x
		lds	temp2, rpm_h

		lds	temp1, rpm_l	; subtract 1/256
		sub	temp1, temp2
		sts	rpm_l, temp1
		lds	temp1, rpm_h
		sbc	temp1, temp3
		sts	rpm_h, temp1
		lds	temp1, rpm_x
		sbci	temp1, 0
		sts	rpm_x, temp1

		lds	temp3, timing_acc_x
		lds	temp2, timing_acc_h
		lds	temp1, timing_acc_l
		lsr	temp3		; make one complete commutation cycle
		ror	temp2
		ror	temp1
		lsr	temp3
		ror	temp2
		ror	temp1
	; temp3 is zero now - for sure !!
		sts	timing_acc_x, temp3
		sts	timing_acc_h, temp3
		sts	timing_acc_l, temp3
	; and add the result as 1/256
		lds	temp3, rpm_l
		add	temp3, temp1
		sts	rpm_l, temp3
		lds	temp3, rpm_h
		adc	temp3, temp2
		sts	rpm_h, temp3
		ldi	temp1, 0
		lds	temp3, rpm_x
		adc	temp3, temp1
		sts	rpm_x, temp3

		ret
;-----bko-----------------------------------------------------------------
set_all_timings:
		ldi	YL, low  (timeoutSTART)
		ldi	YH, high (timeoutSTART)
		sts	wt_OCT1_tot_l, YL
		sts	wt_OCT1_tot_h, YH
		ldi	temp3, 0xff
		ldi	temp4, 0x1f
		sts	wt_comp_scan_l, temp3
		sts	wt_comp_scan_h, temp4
		sts	com_timing_l, temp3
		sts	com_timing_h, temp4

set_timing_v:	ldi	ZL, 0x03
		sts	timing_x, ZL
		ldi	temp4, 0xff
		sts	timing_h, temp4
		ldi	temp3, 0xff
		sts	timing_l, temp3

		ret
;-----bko-----------------------------------------------------------------
update_timing:	rcall	tcnt1_to_temp
		sts	tcnt1_sav_l, temp1
		sts	tcnt1_sav_h, temp2
		add	temp1, YL
		adc	temp2, YH
		ldi	temp4, (1<<TOIE1)+(1<<TOIE0)
		out	TIMSK, temp4
		out	OCR1AH, temp2
		out	OCR1AL, temp1
		sbr	flags0, (1<<OCT1_PENDING)
		ldi	temp4, (1<<TOIE1)+(1<<OCIE1A)+(1<<TOIE0) ; enable interrupt again
		out	TIMSK, temp4

	; calculate next waiting times - timing(-l-h-x) holds the time of 4 commutations
		lds	temp1, timing_l
		lds	temp2, timing_h
		lds	ZL, timing_x

		sts	zero_wt_l, temp1	; save for zero crossing timeout
		sts	zero_wt_h, temp2
		tst	ZL
		breq	update_t00
		ldi	temp4, 0xff
		sts	zero_wt_l, temp4	; save for zero crossing timeout
		sts	zero_wt_h, temp4
update_t00:
		lsr	ZL			; build a quarter
		ror	temp2
		ror	temp1

		lsr	ZL
		ror	temp2
		ror	temp1
		lds	temp3, timing_l		; .. and subtract from timing
		lds	temp4, timing_h
		lds	ZL, timing_x
		sub	temp3, temp1
		sbc	temp4, temp2
		sbci	ZL, 0

		lds	temp1, tcnt1_sav_l	; calculate this commutation time
		lds	temp2, tcnt1_sav_h
		lds	YL, last_tcnt1_l
		lds	YH, last_tcnt1_h
		sts	last_tcnt1_l, temp1
		sts	last_tcnt1_h, temp2
		sub	temp1, YL
		sbc	temp2, YH
		sts	last_com_l, temp1
		sts	last_com_h, temp2

		add	temp3, temp1		; .. and add to timing
		adc	temp4, temp2
		ldi	temp2, 0
		adc	ZL, temp2

	; limit RPM to 120.000
		tst	ZL
		brne	update_t90
		tst	temp4
		breq	update_t10
		cpi	temp4, 0x02
		brne	update_t90
		cpi	temp3, 0x98		; 0x298 = 120.000 RPM
		brcc	update_t90
	; set RPM to 120.000
update_t10:	ldi	temp4, 0x02
		ldi	temp3, 0x98
		tst	run_control 
		brne	update_t90		; just active
		ldi	temp1, 0xff		; not active - reactivate
		mov	run_control, temp1

update_t90:	sts	timing_l, temp3
		sts	timing_h, temp4
		sts	timing_x, ZL
		cpi	ZL, 4		; limit range to 0x3ffff
		brcs	update_t99
		rcall	set_timing_v

update_t99:	lds	temp1, timing_acc_l
		add	temp1, temp3
		sts	timing_acc_l, temp1
		lds	temp1, timing_acc_h
		adc	temp1, temp4
		sts	timing_acc_h, temp1
		lds	temp1, timing_acc_x
		adc	temp1, ZL
		sts	timing_acc_x, temp1

		lsr	ZL			; a 16th is the next wait before scan
		ror	temp4
		ror	temp3
		lsr	ZL
		ror	temp4
		ror	temp3
		lsr	ZL
		ror	temp4
		ror	temp3
		lsr	ZL
		ror	temp4
		ror	temp3
		sts	wt_comp_scan_l, temp3
		sts	wt_comp_scan_h, temp4

	; use the same value for commutation timing (15

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -