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

📄 stmd.asm

📁 mega48 microsteeeper基于mega48 步进马达细分程序
💻 ASM
📖 第 1 页 / 共 3 页
字号:
                ; -----001  ; 001 = no prescaler, internal clock
                ; -----100  ; 011 = 1:64 prescaler, internal clock
                ; -----100  ; 110 = 1:256 prescaler, internal clock
                ; -----101  ; 111 = 1:1024 prescaler, internal clock
    sts TCCR2B, temp1
    
    clr temp1               ; clear some registers
    sts TCNT2, temp1
    sts OCR2A, temp1
    sts OCR2B, temp1

    ; 8Mhz clock -> 125 ns instruction cycle
    ; 8 bit counter, 2^8 x 125 ns = 32 us
    ; with 1:1014 prescaler: 1024 x 32 us = 32.768 ms per rollover
    ; for 3 s delay: 3 s / 32.768 ms = 91.55 rollovers per 3 s
    ; -- calculate error for 92 rollovers: 92 * 32.768 ms = 3.015 s
    .equ tim2_idlerolls_target = 92
    ldi tim2_idlerolls, 0

; enable/disable timer/counter2 interrupts
    ldi temp1,  0b00000001
                ; xxxxx---  ; reserved
                ; -----0--  ; 0 = timer/counter2 Output Compare B Match interrupt disabled
                ; ------0-  ; 0 = timer/counter2 Output Compare A Match interrupt disabled
                ; -------0  ; 0 = timer/counter2 Overflow interrupt disabled
    sts TIMSK2, temp1

; ************************************************************************
; configure external interrupts
    ldi temp1, 0b00000010
               ; xxxx----   ; reserved
               ; ----00--   ; 00 = low level on INT1 generates interrupt request
               ; ------10   ; 10 = falling edge on INT0 generates interrupt request
    sts EICRA, temp1

    ldi temp1, 0b00000000
               ; xxxxxx--   ; reserved
               ; ------0-   ; 0 = INT1 disabled
               ; -------0   ; 0 = INT0 disabled
    out EIMSK, temp1


; ************************************************************************
; configure watchdog timer
    
    wdr                     ; hit the dog

    lds temp1, WDTCSR       ; start timed sequence to set up WDTCSR
    ori temp1, (1<<WDCE) | (1<<WDE)
    sts WDTCSR, temp1


    ldi temp1, 0b01000000
               ; 0-------   ; 0 = watchdog interrupt flag clear (WDIF)
               ; -1------   ; 1 = watchdog interrupt enabled (WDIE)
               ; --0--000   ; 0--000 = 16 ms timeout (watchdog prescaler bits)
               ; --1--001   ; 1--001 = 8 sec timeout (watchdog prescaler bits)
               ; ---0----   ; watchdog change enable (WDCE)
               ; ----0---   ; 0 = Watchdog system reset disabled (WDE)
    sts WDTCSR, temp1

; ************************************************************************
; initialize mode of stepping based on DIP switches
    in  temp1,  PINC
    andi temp1, 0b00000111  ; mask off the bits that don't pertain to stepping mode
    
    cpi temp1,  0b111  		; full-step mode with both phases on?  
    brne next1 
    rcall init_full_both
    
next1:
    cpi temp1,  0b110       ; full-step mode with one phase on?
    brne next2
    rcall init_full_wave

next2:    
    cpi temp1,  0b101       ; half-step mode?
    brne next3
    rcall init_half

next3:    
    cpi temp1,  0b100       ; quarter step mode?
    brne next4
    rcall init_quarter

next4:    
    cpi temp1,  0b011       ; sixth step mode?
    brne next5
    rcall init_sixth

next5:    
    cpi temp1,  0b010       ; eighth step mode?
    brne next6
    rcall init_eighth

next6:    
    cpi temp1,  0b001       ; tenth step mode?
    brne next7
    rcall init_tenth

next7:    
    cpi temp1,  0b000       ; twelfth or sixteenth step mode?
    brne next8
    rcall init_twelfth      
;    rcall init_sixteenth

next8:    
    sei         ; enable interrupts after everything is configured


; ************************************************************************      
Loop:   ; loop here forever waiting for step interruputs
    wdr
    rcall    enable_check       ; drive enabled?
    wdr                         ; hit the dog 
    rcall    LED_check          ; time to toggle LED?
    wdr                         ; hit the dog
    rcall    test_mode_check    ; test mode?
    wdr                         ; hit the dog
    rcall    idle_cur_red_check ; check to see if idle current reduction should be turned on
    rjmp     Loop

; ************************************************************************
; ***** Subroutines ******************************************************
; ************************************************************************

; ************************************************************************
LED_check:      ; check timer/counter0 rollovers to see if we should toggle the LED
    cpi  tim0_LEDrolls,  tim0_LEDrolls_target
    brsh toggle_led
    ret    
toggle_led:
    sbi pind, alive_LED ; toggle the pin
    clr tim0_LEDrolls   ; reset rollover counter
    ret

; ************************************************************************    
enable_check:   ; check to see if the drive is enabled *******************
                
; PD4 is the enable input from opto-isolator.  It is pulled high through 270R when disabled
; and goes low when 5v is applied to input of opto-isolator to enable the drive

; If drive is disabled, we want to disable external INT0.
                
; PC3 is an input with internal pullup enabled, DIP switch to gnd.
; When drive is disabled (PD4 high) and PC3 is low, we will let the motors freewheel
; by setting M pins low (PortB) and brake pin(s) (PD6) low.
                
; When drive is disabled (PD4 high) and PC3 is high, we will enable motor braking
; by taking brake pin(s) PD6 high.

    sbic PIND, enable_in    ; drive enabled?
    rjmp drive_disabled

    
drive_enabled:    
    cbi PORTD, brake_out    ; braking off
    sbi EIMSK, INT0         ; enable step interrupts
    ret

drive_disabled:
    cbi EIMSK, INT0         ; disable step interrupts
    sbis PINC, brake_in     ; 
    rjmp brake_on

freewheel:    
    clr temp1
    out PORTB, temp1        ; M pins all low so motor can freewheel
    cbi PORTD, brake_out    ; braking off
    ret

brake_on:    
    sbi PORTD, brake_out    ; braking on    
    ret

; ************************************************************************
test_mode_check: ; is test mode active?  Rotate motor, if yes
    sbic PINC, test_in      ; if it's clear, DIP switch is on so test mode is active
    rjmp test_disabled

    ldi temp1,  0b00000010  ; enable interrupt to periodically fire step signal
                ; --0-----  ; 0 = input capture interrupt disabled
                ; xx-xx---  ; reserved
                ; -----0--  ; 0 = timer/counter2 Output Compare B Match interrupt disabled
                ; ------0-  ; 0 = timer/counter2 Output Compare A Match interrupt disabled
                ; -------0  ; 0 = timer/counter2 Overflow interrupt disabled
    sts TIMSK1, temp1
    ret

test_disabled:    
    ldi temp1,  0b00000000  ; disable interrupt
                ; --0-----  ; 0 = input capture interrupt disabled
                ; xx-xx---  ; reserved
                ; -----0--  ; 0 = timer/counter2 Output Compare B Match interrupt disabled
                ; ------0-  ; 0 = timer/counter2 Output Compare A Match interrupt disabled
                ; -------0  ; 0 = timer/counter2 Overflow interrupt disabled
    sts TIMSK1, temp1
    
    ret

; ************************************************************************
idle_cur_red_check: ; is it time to reduce idle current?
    cpi  tim2_idlerolls, tim2_idlerolls_target
    brsh reduce_current
    ret
reduce_current:
    cli                 ; disable interrupts while we reduce current and stop timer2
    cbi portd, idle_red_out
    clr temp1           ; disable timer2 interrupts
    sts TIMSK2, temp1
    sei                 ; interrupts back on
    ret 

; ************************************************************************
fault_trap:  ; trap and log faults to EEPROM
    
    cli                 ; prevent new interrupts from getting us out of the trap
    
    ldi temp1, EE_PTR   ; EE_PTR contains the address of the next empty space in EEPROM
    rcall EEPROM_read
                            
    in  temp3, EEDR     ; store a copy of the address of the next empty space in EEPROM

    in  temp1, EEDR         ; address to write to
    mov temp2, fault_code   ; data to write
    rcall EEPROM_write
    
    inc temp3           ; calculate the new address of the next empty space in EEPROM
    breq infinite       ; test zero flag for rollover, meaning EEPROM is full

    ldi temp1, EE_PTR   ; address to write to
    mov temp2, temp3    ; data to write
    rcall EEPROM_write

infinite:
    cbi  portd, alive_LED   ; on to indicate fault
    rjmp infinite           ; spin forever...

; ************************************************************************
EEPROM_read:  ; read EEPROM
    
; Call: Address to read contained in temp1
    
    sbic    EECR, EEPE      ; wait for completion of previous write
    rjmp    EEPROM_read
    
    out     EEARL, temp1    ; setup low address byte
    ldi     temp1, 0        ; setup high address byte...
    out     EEARH, temp1    ; ...always zero as there are only 255 bytes on M48

    sbi     EECR, EERE      ; start the read by writing EERE

    ldi     temp1, 0
    out     EEARH, temp1    ; point back to location 0...
    out     EEARL, temp1    ; ...to minimize chance of corruption

    ret

; ************************************************************************
EEPROM_write:   ; write EEPROM
    
; Call: Address to write contained in temp1
;       Data to write contained in temp2    
    
    sbic    EECR, EEPE      ; wait for completion of previous write
    rjmp    EEPROM_write
    
    out     EEARL, temp1    ; setup low address byte
    ldi     temp1, 0        ; setup high address byte...
    out     EEARH, temp1    ; ...always zero as there are only 255 bytes on M48

    out     EEDR, temp2     ; setup data register
    
    sbi     EECR, EEMPE     ; set master write enable
    sbi     EECR, EEPE      ; set write enable
    
    ldi     temp1, 0
    out     EEARH, temp1    ; point back to location 0...
    out     EEARL, temp1    ; ...to minimize chance of corruption

    ret

⌨️ 快捷键说明

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