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

📄 bl-4428.asm

📁 Atmel Atmega128 processor brushless controller source code with compiler hints.
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;**** **** **** **** ****
;
;Die Benutzung der Software ist mit folgenden Bedingungen verbunden:
;
;1. Da ich alles kostenlos zur Verf黦ung stelle, gebe ich keinerlei Garantie
;   und 黚ernehme auch keinerlei Haftung f黵 die Folgen der Benutzung.
;
;2. Die Software ist ausschlie遧ich zur privaten Nutzung bestimmt. Ich
;   habe nicht gepr黤t, ob bei gewerblicher Nutzung irgendwelche Patentrechte
;   verletzt werden oder sonstige rechtliche Einschr鋘kungen vorliegen.
;
;3. Jeder darf 膎derungen vornehmen, z.B. um die Funktion seinen Bed黵fnissen
;   anzupassen oder zu erweitern. Ich w黵de mich freuen, wenn ich weiterhin als
;   Co-Autor in den Unterlagen erscheine und mir ein Link zur entprechenden Seite
;   (falls vorhanden) mitgeteilt wird.
;
;4. Auch nach den 膎derungen sollen die Software weiterhin frei sein, d.h. kostenlos bleiben.
;
;!! Wer mit den Nutzungbedingungen nicht einverstanden ist, darf die Software nicht nutzen !!
;
; Dezember 2006
; autor: Bernhard Konze
; email: bernhard.konze@versanet.de
; minor changes: Oct 2007, Hans Haider, h.haider@comdesign.at - marked with #HH#
;
;**** **** **** **** ****
; Device
;**** **** **** **** ****
;
; z.Z. Nur f黵 den QUAX-4428_V01 mit 16 MHz geeignet
;
;**** **** **** **** ****
.include "m8def.inc"
.include "QUAX-4428.inc"
;
; 8K Bytes of In-System Self-Programmable Flash
; 512 Bytes EEPROM
; 1K Byte Internal SRAM
;
;**** **** **** **** ****


.include "m1\mnum.inc"

;.equ MOTOR_NUMBER = 1
;.equ MOTOR_NUMBER = 2
;.equ MOTOR_NUMBER = 3
;.equ MOTOR_NUMBER = 4

.equ MOTOR_MAX = 5 ; #HH# must be 1 larger than motorcount

.equ	CHANGE_TIMEOUT	= 0x01
.equ	CHANGE_TOT_LOW	= 0x01

;.equ	POWER_RANGE	= 200			; full range of tcnt0 setting 10kHz
.equ	POWER_RANGE	= 125			; full range of tcnt0 setting 16kHz
;.equ	POWER_RANGE	= 100			; full range of tcnt0 setting 20kHz
;.equ	MIN_DUTY	= 15			; no power 10kHz
.equ	MIN_DUTY	= 14			; no power 16kHz
;.equ	MIN_DUTY	= 13			; no power 20kHz
.equ	NO_POWER	= 256-MIN_DUTY		; (POWER_OFF)
.equ	MAX_POWER	= 256-POWER_RANGE	; (FULL_POWER)

.equ	PWR_MAX_RPM1	= POWER_RANGE/4
.equ	PWR_MAX_RPM2	= POWER_RANGE/2

;.equ	PWR_STARTUP	= 40			; startup power 10kHz
;.equ	PWR_MAX_STARTUP	= PWR_STARTUP+20
.equ	PWR_STARTUP	= 20			; startup power 16kHz ; bko: 25
.equ	PWR_MAX_STARTUP	= PWR_STARTUP+13
;.equ	PWR_STARTUP	= 20			; startup power 20kHz
;.equ	PWR_MAX_STARTUP	= PWR_STARTUP+10


.equ	timeoutSTART	= 65000
.equ	timeoutMIN	= 48000

.equ	T1STOP	= 0x00
.equ	T1CK8	= 0x02

; timing(-l-h-x) holds the time of 4 commutations
; e.g.: timing = 0x010000 = 65536 * 0.5祍 (timer1)
; 1 commutation = 8192祍
; 1/RPS (round per secone) = 6 commutations = 49152祍
; RPS = 20,34 ==> RPM = 1221
; PWR_RANGEx refers to timing_h if (timing_x==0)
;.equ	PWR_RANGE1	= 0x80	; ( ~2400 RPM )
;.equ	PWR_RANGE2	= 0x40	; ( ~4800 RPM )
.equ	PWR_RANGE1	= 0xc0	; ( ~1800 RPM )
.equ	PWR_RANGE2	= 0x80	; ( ~2400 RPM )

.equ	ENOUGH_GOODIES	= 60

;**** **** **** **** ****
; Register Definitions
.def	i_sreg		 = r1	; status register save in interrupts
.def	tcnt0_power_on	 = r2	; timer0 counts nFETs are switched on
.def	tcnt0_change_tot = r3	; when zero, tcnt0_power_on is changed by one (inc or dec)
.def	byte_cnt	 = r4
.def	uart_cnt	 = r5
.def	tcnt0_pwron_next = r6

.def	start_rcpuls_l	 = r7
.def	start_rcpuls_h	 = r8
.def	motor_count 	 = r9
.def	motor_total = r10 ;
.def	control_timeout	 = r11
;.equ	CONTROL_TOT	 = 50	; time = NUMBER x 65ms
.equ	CONTROL_TOT	 = 4	; time = NUMBER x 65ms

.def	current_err	 = r12	; counts consecutive current errors
.equ	CURRENT_ERR_MAX  = 3	; performs a reset after MAX errors

.def	sys_control	 = r13
.def	t1_timeout	 = r14
.def	run_control	 = r15


.def	temp1	= r16			; main temporary
.def	temp2	= r17			; main temporary
.def	temp3	= r18			; main temporary
.def	temp4	= r19			; main temporary

.def	i_temp1	= r20			; interrupt temporary
.def	i_temp2	= r21			; interrupt temporary
.def	i_temp3	= r22			; interrupt temporary

.def	flags0	= r23	; state flags
	.equ	OCT1_PENDING	= 0	; if set, output compare interrunpt is pending
	.equ	UB_LOW 		= 1	; set if accu voltage low
	.equ	I_pFET_HIGH	= 2	; set if over-current detect
	.equ	GET_STATE	= 3	; set if state is to be send
	.equ	C_FET		= 4	; if set, C-FET state is to be changed
	.equ	A_FET		= 5	; if set, A-FET state is to be changed
	     ; if neither 1 nor 2 is set, B-FET state is to be changed
	.equ	I_OFF_CYCLE	= 6	; if set, current off cycle is active
	.equ	T1OVFL_FLAG	= 7	; each timer1 overflow sets this flag - used for voltage + current watch

.def	flags1	= r24	; state flags
	.equ	POWER_OFF	= 0	; switch fets on disabled
	.equ	FULL_POWER	= 1	; 100% on - don't switch off, but do OFF_CYCLE working
	.equ	CALC_NEXT_OCT1	= 2	; calculate OCT1 offset, when wait_OCT1_before_switch is called
	.equ	RC_PULS_UPDATED	= 3	; new rc-puls value available
	.equ	EVAL_SYS_STATE	= 4	; if set, overcurrent and undervoltage are checked
	.equ	EVAL_RPM	= 5	; if set, next PWM on should look for current
	.equ	EVAL_PWM	= 6	; if set, PWM should be updated

.def	flags2	= r25
	.equ	RPM_RANGE1	= 0	; if set RPM is lower than 1831 RPM
	.equ	RPM_RANGE2	= 1	; if set RPM is between 1831 RPM and 3662 RPM
	.equ	SCAN_TIMEOUT	= 2	; if set a startup timeout occurred
	.equ	POFF_CYCLE	= 3	; if set one commutation cycle is performed without power
	.equ	COMP_SAVE	= 4	; if set ACO was high
	.equ	STARTUP		= 5	; if set startup-phase is active
	.equ	RC_INTERVAL_OK	= 6	; 
	.equ	NO_SYNC		= 7	; 

; here the XYZ registers are placed ( r26-r31)

; ZH = new_duty		; PWM destination


;**** **** **** **** ****
; RAM Definitions
.dseg					;EEPROM segment
.org SRAM_START

tcnt1_sav_l:	.byte	1	; actual timer1 value
tcnt1_sav_h:	.byte	1
last_tcnt1_l:	.byte	1	; last timer1 value
last_tcnt1_h:	.byte	1
timing_l:	.byte	1	; holds time of 4 commutations 
timing_h:	.byte	1
timing_x:	.byte	1

timing_acc_l:	.byte	1	; holds the average time of 4 commutations 
timing_acc_h:	.byte	1
timing_acc_x:	.byte	1

rpm_l:		.byte	1	; holds the average time of 4 commutations 
rpm_h:		.byte	1
rpm_x:		.byte	1

wt_comp_scan_l:	.byte	1	; time from switch to comparator scan
wt_comp_scan_h:	.byte	1       
com_timing_l:	.byte	1	; time from zero-crossing to switch of the appropriate FET
com_timing_h:	.byte	1
wt_OCT1_tot_l:	.byte	1	; OCT1 waiting time
wt_OCT1_tot_h:	.byte	1
zero_wt_l:	.byte	1
zero_wt_h:	.byte	1
last_com_l:	.byte	1
last_com_h:	.byte	1

stop_rcpuls_l:	.byte	1
stop_rcpuls_h:	.byte	1
new_rcpuls_l:	.byte	1
new_rcpuls_h:	.byte	1

duty_offset:	.byte	1
goodies:	.byte	1
comp_state:	.byte	1
uart_command:	.byte	1

uart_data:	.byte	100		; only for debug requirements


;**** **** **** **** ****
; ATmega8 interrupts

;.equ	INT0addr=$001	; External Interrupt0 Vector Address
;.equ	INT1addr=$002	; External Interrupt1 Vector Address
;.equ	OC2addr =$003	; Output Compare2 Interrupt Vector Address
;.equ	OVF2addr=$004	; Overflow2 Interrupt Vector Address
;.equ	ICP1addr=$005	; Input Capture1 Interrupt Vector Address
;.equ	OC1Aaddr=$006	; Output Compare1A Interrupt Vector Address
;.equ	OC1Baddr=$007	; Output Compare1B Interrupt Vector Address
;.equ	OVF1addr=$008	; Overflow1 Interrupt Vector Address
;.equ	OVF0addr=$009	; Overflow0 Interrupt Vector Address
;.equ	SPIaddr =$00a	; SPI Interrupt Vector Address
;.equ	URXCaddr=$00b	; USART Receive Complete Interrupt Vector Address
;.equ	UDREaddr=$00c	; USART Data Register Empty Interrupt Vector Address
;.equ	UTXCaddr=$00d	; USART Transmit Complete Interrupt Vector Address
;.equ	ADCCaddr=$00e	; ADC Interrupt Vector Address
;.equ	ERDYaddr=$00f	; EEPROM Interrupt Vector Address
;.equ	ACIaddr =$010	; Analog Comparator Interrupt Vector Address
;.equ	TWIaddr =$011	; Irq. vector address for Two-Wire Interface
;.equ	SPMaddr =$012	; SPM complete Interrupt Vector Address
;.equ	SPMRaddr =$012	; SPM complete Interrupt Vector Address
;-----bko-----------------------------------------------------------------

;**** **** **** **** ****
.cseg
.org 0
;**** **** **** **** ****

;-----bko-----------------------------------------------------------------
; reset and interrupt jump table
		rjmp	reset
		nop	; ext_int0
		nop	; ext_int1
		nop	; t2oc_int
		nop	; t2ovfl_int
		nop	; icp1
		rjmp	t1oca_int
		nop	; t1ocb_int
		rjmp	t1ovfl_int
		rjmp	t0ovfl_int
		nop	; spi_int
		rjmp	urxc
		nop	; udre
		nop ; utxc ; #HH# not used - only receiver in action!
; not used	nop	; adc_int
; not used	nop	; eep_int
; not used	nop	; aci_int
; not used	nop	; wire2_int
; not used	nop	; spmc_int


version:	.db	0x0d, 0x0a
		.db	"bk#",Typ,"#r01uart-p40-"
		.db	0x0d, 0x0a

;-----bko-----------------------------------------------------------------
; init after reset

reset:		ldi	temp1, high(RAMEND)	; stack = RAMEND
		out	SPH, temp1
		ldi	temp1, low(RAMEND)
		out 	SPL, temp1

	; runs with 16MHz crystal - no calibration needed

	; portB
		ldi	temp1, INIT_PB
		out	PORTB, temp1
		ldi	temp1, DIR_PB
		out	DDRB, temp1

	; portC
		ldi	temp1, INIT_PC
		out	PORTC, temp1
		ldi	temp1, DIR_PC
		out	DDRC, temp1

	; portD
		ldi	temp1, INIT_PD
		out	PORTD, temp1
		ldi	temp1, DIR_PD
		out	DDRD, temp1
		
		HHDEBUGLED_on

	; timer0: PWM + beep control = 0x02 	; start timer0 with CK/8 (0.5祍/count)
		ldi	temp1, 0x02
		out	TCCR0, temp1

	; timer1: commutation control = 0x02	; start timer1 with CK/8 (0.5祍/count)
		ldi	temp1, T1CK8
		out	TCCR1B, temp1

	; reset state flags
		clr	flags0
		clr	flags1
		clr	flags2

		ldi	temp1, MOTOR_NUMBER
		mov	motor_count, temp1
		sbr	flags2, (1<<NO_SYNC)
		
		ldi temp1, MOTOR_MAX
		mov motor_total, temp1
		
	; clear RAM
		clr	XH
		ldi	XL, low (SRAM_START)
		clr	temp1
clear_ram:	st	X+, temp1
		cpi	XL, uart_data+1
		brlo	clear_ram

	; power off
		rcall	switch_power_off

	; reset input timeout
		ldi	temp1, CONTROL_TOT
		mov	control_timeout, temp1
		
; 	rjmp	control_start		; for simulator only

		ldi	ZH,high(version*2)
		ldi	ZL,low(version*2)

;**** UART Initialization ****
		ldi	temp1, 0
		out	UBRRH, temp1

		ldi	temp1, 16 ; 115200
		out	UBRRL, temp1
		ldi	temp1, 0x02	; #BK# set U2X
		out	UCSRA, temp1

;		ldi	temp1, 34 ; 57600
;		out	UBRRL, temp1
;		ldi	temp1, 0x02	; #BK# set U2X
;		out	UCSRA, temp1

		ldi	temp1, 0x10 ; #HH# enable rx only!
		out	UCSRB, temp1	; 
		in 	temp1, UDR	; clear possibly pending rxc
		ldi	temp1, 0
		mov	uart_cnt, temp1

;   #HH# sending of version-string is commented out
;		lpm
;		adiw	ZL,1		;increment Z-pointer
;		mov	temp1, r0	; (1)
;		rcall	send_byte

		rcall	wait260ms	; wait a while
		rcall	wait260ms

		rcall	beep_f1
		rcall	wait30ms
		rcall	beep_f2
		rcall	wait30ms
		rcall	beep_f3
		rcall	wait30ms
		rcall	wait30ms
		rcall	wait30ms
		rcall	wait30ms

;   #HH# sending of version-string is commented out
;		ldi	temp2, reset-version-1
;v_str_rest:	lpm
;		adiw	ZL,1		;increment Z-pointer
;		mov	temp1, r0	; (6)
;		rcall	send_byte
;		dec	temp2
;		brne	v_str_rest

		in	temp1, UDR  ; clear serial input - if existing
		in	temp1, UDR
		sbi	UCSRA, RXC		; clear flag
		sbi	UCSRB, RXCIE		; enable reception irq

		rcall	beep_f4			; signal: rcpuls ready
		rcall	beep_f4
		rcall	beep_f4


control_start:	; init variables
		ldi	temp1, CHANGE_TIMEOUT
		mov	tcnt0_change_tot, temp1
		ldi	temp1, NO_POWER
		mov	tcnt0_power_on, temp1

		ldi	temp1, 0		; reset error counters
		mov	current_err,temp1
		mov	sys_control, temp1

	; init registers and interrupts
		ldi	temp1, (1<<TOIE1)+(1<<OCIE1A)+(1<<TOIE0)
		out	TIFR, temp1		; clear TOIE1,OCIE1A & TOIE0
		out	TIMSK, temp1		; enable TOIE1,OCIE1A & TOIE0 interrupts

		sei				; enable all interrupts

		ldi	temp1, 30
		sts	duty_offset, temp1

		rcall	set_all_timings

		rcall	wait30ms

		rjmp	init_startup
		
;-----bko-----------------------------------------------------------------
; output compare timer1 interrupt
t1oca_int:	in	i_sreg, SREG
		cbr	flags0, (1<<OCT1_PENDING) ; signal OCT1 passed
		out	SREG, i_sreg
		reti
;-----bko-----------------------------------------------------------------
; overflow timer1 / happens all 32768祍
t1ovfl_int:	in	i_sreg, SREG
		sbr	flags0, (1<<T1OVFL_FLAG)

		tst	t1_timeout
		breq	t1ovfl_10
		dec	t1_timeout

t1ovfl_10:	tst	control_timeout
		brne	t1ovfl_20
		clr	ZH
		rjmp	t1ovfl_99
t1ovfl_20:	dec	control_timeout


t1ovfl_99:	out	SREG, i_sreg
		reti
;-----bko-----------------------------------------------------------------
; timer0 overflow interrupt
t0ovfl_int:	in	i_sreg, SREG
		sbrc	flags0, I_OFF_CYCLE
		rjmp	t0_on_cycle

t0_off_cycle:	sbr	flags2, (1<<COMP_SAVE)
		sbic	ACSR, ACO		; mirror inverted ACO to bit-var
		cbr	flags2, (1<<COMP_SAVE)

		; fastest possible ; #HH# ; DANGEROUS!!!
		mov i_temp1, tcnt0_pwron_next
		rjmp set_next_pwm

	; changes in PWM ?
		mov	i_temp1, tcnt0_power_on
		mov	i_temp2, tcnt0_pwron_next
		cp	i_temp2, i_temp1
		brsh	lower_pwm		; next power-on-time is lower or same
higher_pwm:	dec	tcnt0_change_tot	; change-timeout passed ?
		brne	nFET_off		; .. no
		ldi	i_temp2, CHANGE_TIMEOUT	; .. yes - change-timeout for more power
		mov	tcnt0_change_tot, i_temp2 ; reset change-timeout and decrement
		dec	i_temp1			; <dec> increases power-on-time
	
		rjmp	set_next_pwm

lower_pwm:	breq	nFET_off		; pwm is unchanged
		dec	tcnt0_change_tot	; change-timeout passed ?
		brne	nFET_off		; .. no
		ldi	i_temp2, CHANGE_TOT_LOW ; .. yes - change-timeout for lower power
		mov	tcnt0_change_tot, i_temp2 ; reset change-timeout and increment
		inc	i_temp1			; <inc> decreases power-on-time
		
set_next_pwm:	mov	tcnt0_power_on, i_temp1

⌨️ 快捷键说明

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