📄 bl-4428.asm
字号:
;**** **** **** **** ****
;
;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 + -