BASIC4MCU | 모터 | BLDC모터 | 쿼드콥터 변속기 - i2c_r09_01 - I2C version with sources.zip
페이지 정보
작성자 키트 작성일2017-09-05 15:03 조회1,901회 댓글0건첨부파일
본문
;**** **** **** **** ****
;
;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 !!
;
; October 2004
; autor: Bernhard Konze
; email: bernhard.konze@versanet.de
;
;**** **** **** **** ****
; Device
;
;**** **** **** **** ****
.include "m8def.inc"
;//.include "6a_i2c.inc"
;***********************************************************
;* TP-18A *
;* Mai.2007
;* http://home.versanet.de/~b-konze/ *
;***********************************************************#define Typ "6a_i2c"
; activate Motor brake
;.equ MOT_BRAKE = 0
;Select Brake Power
; 1 = min Brake
; 2 = medium Brake
; 3 = hard Brake.equ BrakeSelect = 2
.equ CALIBRATE = 1
.equ OSCAL_VALUE = 0x01ff ; eeprom position.equ FORCE_LIPO = 1 ; 1=Lipo und 0=NC wenn keine Buecke
.equ ActiveFreeRun = 0;**** **** **** **** ****
; PORT definitions
;**** **** **** **** ****;*********************
; PORT D
;*********************
;.equ = 7 ;i
.equ c_comp = 6 ;i common comparator input (AIN0)
.equ ApFET = 5 ;o
.equ CpFET = 4 ;o
.equ BpFET = 3 ;o
.equ rcp_in = 2 ;i r/c pulse input.equ INIT_PD = 0
.equ DIR_PD = (1<<ApFET)+(1<<BpFET)+(1<<CpFET)
.equ BRAKE_PD = 0#define ApFET_on sbi PORTD,5
#define ApFET_off cbi PORTD,5
#define BpFET_on sbi PORTD,3
#define BpFET_off cbi PORTD,3
#define CpFET_on sbi PORTD,4
#define CpFET_off cbi PORTD,4
;*********************
; PORT C definitions *
;*********************
;.equ = 5 ; phase input
;.equ = 4 ; ADC4
.equ mux_c = 3 ; phase input
.equ mux_b = 2 ; phase input
.equ mux_a = 1 ; ADC1 temperature control input
.equ accu_adc = 0 ; ADC0 voltage control input;*********************
; ADC only
;*********************
;.equ = 7 ; ADC7
;.equ = 6 ; ADC6.equ INIT_PC = 0x30 ; set pullup for i2c
.equ DIR_PC = 0
.equ BRAKE_PC = 0
;*********************
; PORT B definitions *
;*********************
;.equ = 7
;.equ = 6
;.equ = 5 (sck stk200 interface)
;.equ = 4 (miso stk200 interface)
;.equ = 3 (mosi stk200 interface)
;.equ = 2
;.equ = 1
;.equ = 0.equ AnFET = 2 ;o
.equ CnFET = 1 ;o
.equ BnFET = 0 ;o.equ INIT_PB = 0
.equ DIR_PB = (1<<AnFET)+(1<<BnFET)+(1<<CnFET)
.equ BRAKE_PB = (1<<AnFET)+(1<<BnFET)+(1<<CnFET)#define AnFET_on sbi PORTB,2
#define AnFET_off cbi PORTB,2
#define BnFET_on sbi PORTB,0
#define BnFET_off cbi PORTB,0
#define CnFET_on sbi PORTB,1
#define CnFET_off cbi PORTB,1;
; 8K Bytes of In-System Self-Programmable Flash
; 512 Bytes EEPROM
; 1K Byte Internal SRAM
;**** **** **** **** ****
;**** **** **** **** ****
; fuses must be set to internal calibrated oscillator = 8 mhz
;**** **** **** **** ****
;**** **** **** **** ****.equ MOT_BRAKE = 0
.equ I2C_ADR = 0x50
.equ MOTOR_ID = 1 ; 1, 2, 3 or 4.equ CHANGE_TIMEOUT = 1
.equ CHANGE_TOT_LOW = 1.equ POWER_RANGE = 100 ; full range of tcnt0 setting
.equ MIN_DUTY = 10 ; no power
.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 = MIN_DUTY
.equ PWR_MAX_STARTUP = MIN_DUTY+20.equ timeoutSTART = 48000
.equ timeoutMIN = 36000.equ T1STOP = 0x00
.equ T1CK8 = 0x02.equ EXT0_DIS = 0x00 ; disable ext0int
.equ EXT0_EN = 0x00 ; disable ext0int.equ OCT1_RANGE1 = 16 ; ( ~2400 RPM )
.equ OCT1_RANGE2 = 8 ; ( ~4800 RPM );.equ PWR_RANGE1 = 0x40 ; ( ~2400 RPM )
;.equ PWR_RANGE2 = 0x20 ; ( ~4800 RPM )
.equ PWR_RANGE1 = 0x20 ; ( ~2400 RPM )
.equ PWR_RANGE2 = 0x10 ; ( ~4800 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 = r10
.def i2c_timeout = r11
.equ I2C_TOT = 100.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_I2C = 4 ; if set, new rc puls is evaluated, while waiting for OCT1
.equ EVAL_SYS_STATE = 5 ; if set, overcurrent and undervoltage are checked
.equ EVAL_RPM = 6 ; if set, next PWM on should look for current
.equ EVAL_PWM = 7 ; 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_STARTtcnt1_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 1timing_acc_l: .byte 1 ; holds the average time of 4 commutations
timing_acc_h: .byte 1
timing_acc_x: .byte 1rpm_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 1stop_rcpuls_l: .byte 1
stop_rcpuls_h: .byte 1
new_rcpuls_l: .byte 1
new_rcpuls_h: .byte 1duty_offset: .byte 1
goodies: .byte 1
comp_state: .byte 1
uart_command: .byte 1av_current: .byte 1
max_pwm: .byte 1
i2c_pwm: .byte 1uart_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 ; 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
nop ; urxc
nop ; udre
nop ; utxc
nop ; adc_int
nop ; eep_int
nop ; aci_int
rjmp twi_int
; not used nop ; spmc_int
version: .db 0x0d, 0x0a
.db "6a_i2c_410r09 "
version_end: .db 0x0d, 0x0a
;-----bko-----------------------------------------------------------------
; init after resetreset: ldi temp1, high(RAMEND) ; stack = RAMEND ;//Rd,K // Load Immediate // Rd←K
out SPH, temp1 ;//P,Rr // Out Port // P←Rr
ldi temp1, low(RAMEND) ;//Rd,K // Load Immediate // Rd←K
out SPL, temp1 ;//P,Rr // Out Port // P←Rr
; oscillator calibration byte is written into the uppermost position
; of the eeprom - by the script 1n1p.e2s an ponyprog
;CLEARBUFFER
;LOAD-PROG 1n1p.hex
;PAUSE "Connect and powerup the circuit, are you ready?"
;READ-CALIBRATION 0x21FF DATA 3 # <EEProm 8Mhz
;ERASE-ALL
;WRITE&VERIFY-ALL
; ldi temp1,0x01 ;//Rd,K // Load Immediate // Rd←K
; out EEARH,temp1 ;//P,Rr // Out Port // P←Rr
; ldi temp1,$ff ;//Rd,K // Load Immediate // Rd←K
; out EEARL,temp1 ;//P,Rr // Out Port // P←Rr
; sbi EECR,EERE ;//P,b // Set Bit in I/O Register // I/O(P,b)←1
; in temp1,EEDR ;//Rd,P // In Port // Rd←P
; out osccal ,temp1 ;schreiben ;//P,Rr // Out Port // P←Rr; portB - all FETs off
ldi temp1, INIT_PB ; PORTB initially holds 0x00 ;//Rd,K // Load Immediate // Rd←K
out PORTB, temp1 ;//P,Rr // Out Port // P←Rr
ldi temp1, DIR_PB ;//Rd,K // Load Immediate // Rd←K
out DDRB, temp1 ;//P,Rr // Out Port // P←Rr; portC reads comparator inputs
ldi temp1, INIT_PC ;//Rd,K // Load Immediate // Rd←K
out PORTC, temp1 ;//P,Rr // Out Port // P←Rr
ldi temp1, DIR_PC ;//Rd,K // Load Immediate // Rd←K
out DDRC, temp1 ;//P,Rr // Out Port // P←Rr; portD reads rc-puls + AIN0 ( + RxD, TxD for debug )
ldi temp1, INIT_PD ;//Rd,K // Load Immediate // Rd←K
out PORTD, temp1 ;//P,Rr // Out Port // P←Rr
ldi temp1, DIR_PD ;//Rd,K // Load Immediate // Rd←K
out DDRd,temp1 ;//P,Rr // Out Port // P←Rr; timer0: PWM + beep control = 0x02 ; start timer0 with CK/8 (1탎/count)
ldi temp1, 0x02 ;//Rd,K // Load Immediate // Rd←K
out TCCR0, temp1 ;//P,Rr // Out Port // P←Rr; timer1: commutation control = 0x02 ; start timer1 with CK/8 (1탎/count)
ldi temp1, T1CK8 ;//Rd,K // Load Immediate // Rd←K
out TCCR1B, temp 1 ;//P,Rr // Out Port // P←Rr; reset state flags
clr flags0 ;//Rd // Clear Register // Rd←Rd^Rd
clr flags1 ;//Rd // Clear Register // Rd←Rd^Rd
clr flags2 ;//Rd // Clear Register // Rd←Rd^Rd; clear RAM
clr XH ;//Rd // Clear Register // Rd←Rd^Rd
ldi XL, low (SRAM_START) ;//Rd,K // Load Immediate // Rd←K
clr temp1 ;//Rd // Clear Register // Rd←Rd^Rd
clear_ram: st X+, temp1 ;//X+,Rr // Store Indirect and Post-Inc. // (X)←Rr,X←X+1
cpi XL, uart_data+1 ;//Rd,K // Compare Register with Immediate // Rd-K
brlo clear_ram ;//k // Branch if Lower // if(C=1)PC←PC+k+1; power off
rcall switch_power_off; reset rc puls timeout
ldi temp1, I2C_TOT ;//Rd,K // Load Immediate // Rd←K
mov i2c_timeout, temp1 ;//Rd,Rr // Move Between Registers // Rd←Rr
; rjmp control_start ; for simulator onlyrcall wait260ms ; wait a while
rcall wait260msrcall beep_f1
rcall wait30ms
rcall beep_f2
rcall wait30ms
rcall beep_f3
rcall wait30ms
rcall wait30ms
rcall wait30ms
rcall wait30ms
rcall beep_f4 ; signal: rcpuls ready
rcall beep_f4
rcall beep_f4control_start: ; init variables
ldi temp1, CHANGE_TIMEOUT ;//Rd,K // Load Immediate // Rd←K
mov tcnt0_change_tot, temp1 ;//Rd,Rr // Move Between Registers // Rd←Rr
ldi temp1, NO_POWER ;//Rd,K // Load Immediate // Rd←K
mov tcnt0_power_on, temp1 ;//Rd,Rr // Move Between Registers // Rd←Rrldi temp1, 0 ; reset error counters ;//Rd,K // Load Immediate // Rd←K
mov current_err,temp1 ;//Rd,Rr // Move Between Registers // Rd←Rr
mov sys_control, temp1 ;//Rd,Rr // Move Between Registers // Rd←Rr; init registers and interrupts
ldi temp1, (1<<TOIE1)+(1<<OCIE1A)+(1<<TOIE0) ;//Rd,K // Load Immediate // Rd←K
out TIFR, temp1 ; clear TOIE1,OCIE1A & TOIE0 ;//P,Rr // Out Port // P←Rr
out TIMSK, temp1 ; enable TOIE1,OCIE1A & TOIE0 interrupts ;//P,Rr // Out Port // P←Rrsei ; enable all interrupts
ldi temp1, 30 ;//Rd,K // Load Immediate // Rd←K
sts duty_offset, temp1 ;//k,Rr // Store Direct to SRAM // (k)←Rrrcall set_all_timings
rcall wait30ms
; i2c init
ldi temp1, I2C_ADR+(MOTOR_ID<<1) ;//Rd,K // Load Immediate // Rd←K
out TWAR, temp1 ;//P,Rr // Out Port // P←Rr
ldi temp1, (1<<TWINT) | (1<<TWEN) | (1<<TWIE) | (1<<TWEA) ;//Rd,K // Load Immediate // Rd←K
out TWCR, temp1 ;//P,Rr // Out Port // P←Rrrjmp init_startup
;-----bko-----------------------------------------------------------------
; output compare timer1 interrupt
t1oca_int: in i_sreg, SREG ;//Rd,P // In Port // Rd←P
cbr flags0, (1<<OCT1_PENDING) ; signal OCT1 passed ;//Rd,K // Clear Bit(s) in Register // Rd←Rd^(0xFF-K)
out SREG, i_sreg ;//P,Rr // Out Port // P←Rr
reti
;-----bko-----------------------------------------------------------------
; overflow timer1 / happens all 65536탎
t1ovfl_int: in i_sreg, SREG ;//Rd,P // In Port // Rd←P
sbr flags0, (1<<T1OVFL_FLAG) ;//Rr,b // Skip if Bit in Register is Set // if(Rr(b)=1)PC←PC+2or3tst t1_timeout ;//Rd // Test for Zero or Minus // Rd←Rd&Rd
breq t1ovfl_10 ;//k // Branch if Equal // if(Z=1)PC←PC+k+1
dec t1_timeout ;//Rd // Decrement // Rd←Rd?1t1ovfl_10: tst i2c_timeout ;//Rd // Test for Zero or Minus // Rd←Rd&Rd
breq t1ovfl_99 ;//k // Branch if Equal // if(Z=1)PC←PC+k+1
dec i2c_timeout ;//Rd // Decrement // Rd←Rd?1t1ovfl_99: out SREG, i_sreg ;//P,Rr // Out Port // P←Rr
reti
;-----bko-----------------------------------------------------------------
; timer0 overflow interrupt
t0ovfl_int: in i_sreg, SREG ;//Rd,P // In Port // Rd←P
sbrc flags0, I_OFF_CYCLE ;//Rr,b // Skip if Bit in Register Cleared // if(Rr(b)=0)PC←PC+2or3
rjmp t0_on_cyclet0_off_cycle: sbr flags2, (1<<COMP_SAVE) ;//Rr,b // Skip if Bit in Register is Set // if(Rr(b)=1)PC←PC+2or3
sbic ACSR, ACO ; mirror inverted ACO to bit-var ;//P,b // Skip if Bit in I/O Register Cleared // if(P(b)=0)PC←PC+2or3
cbr flags2, (1<<COMP_SAVE) ;//Rd,K // Clear Bit(s) in Register // Rd←Rd^(0xFF-K); changes in PWM ?
mov i_temp1, tcnt0_power_on ;//Rd,Rr // Move Between Registers // Rd←Rr
mov i_temp2, tcnt0_pwron_next ;//Rd,Rr // Move Between Registers // Rd←Rr
cp i_temp2, i_temp1 ;//Rd,Rr // Compare // Rd ? Rr
brsh lower_pwm ; next power-on-time is lower or same ;//k // Branch if Same or Higher // if(C=0)PC←PC+k+1
higher_pwm: dec tcnt0_change_tot ; change-timeout passed ? ;//Rd // Decrement // Rd←Rd?1
brne nFET_off ; .. no ;//k // Branch if Not Equal // if(Z=0)PC←PC+k+1
ldi i_temp2, CHANGE_TIMEOUT ; .. yes - change-timeout for more power ;//Rd,K // Load Immediate // Rd←K
mov tcnt0_change_tot, i_temp2 ; reset change-timeout and decrement ;//Rd,Rr // Move Between Registers // Rd←Rr
dec i_temp1 ; <dec> increases power-on-time ;//Rd // Decrement // Rd←Rd?1
rjmp set_next_pwmlower_pwm: breq nFET_off ; pwm is unchanged ;//k // Branch if Equal // if(Z=1)PC←PC+k+1
dec tcnt0_change_tot ; change-timeout passed ? ;//Rd // Decrement // Rd←Rd?1
brne nFET_off ; .. no ;//k // Branch if Not Equal // if(Z=0)PC←PC+k+1
ldi i_temp2, CHANGE_TOT_LOW ; .. yes - change-timeout for lower power ;//Rd,K // Load Immediate // Rd←K
mov tcnt0_change_tot, i_temp2 ; reset change-timeout and increment ;//Rd,Rr // Move Between Registers // Rd←Rr
inc i_temp1 ; <inc> decreases power-on-time ;//Rd // Increment // Rd←Rd+1set_next_pwm: mov tcnt0_power_on, i_temp1 ;//Rd,Rr // Move Between Registers // Rd←Rr
댓글 0
조회수 1,901등록된 댓글이 없습니다.