×
单片机 > 单片机程序设计 > 详情

pic16f874步进电机程序

发布时间:2020-05-16 发布时间:
|

pIC16f874步进电机程序

    list    p=16f874 
    include  


; --==*[ CONSTANTS ]*==--

#define        COMMAND_2    ’B’ 
#define        COMMAND_3    ’C’ 
#define        COMMAND_4    ’D’ 


; --==*[ VARIABLES ]*==-- 
cmdNum        equ    0x20            ; command number. 0xFF for invalid command 
recByte        equ    0x21            ; received byte 

motorL        equ    0x22            ; motor data - low byte 
motorH        equ    0x23            ; motor data - high byte 

byteCnt        equ    0x24            ; internal counter for byte counting during reception 

tickL        equ    0x25            ; ticks: low byte 
tickH        equ    0x26            ; ticks: high byte 
result1L    equ    0x27            ; result: this one is needed for storage of ticks 
result1H    equ    0x28 

winkelL        equ    0x29            ; winkel: tick counter without overflow check etc. 
winkelH        equ    0x30 

quad        equ    0x31            ; quadrature signal, for direction storage 
oldb        equ    0x32            ; old value of PORTB 
newb        equ    0x33            ; new value of PORTB 

tmr0o0        equ    0x34            ; tmr0 overflow counter 0 
tmr0o1        equ    0x35            ; tmr0 overflow counter 1 

wtemp1        equ    0x60            ; storage for the W register (rbif) 
wtemp2        equ    0x61            ; storage for the W register (CCp2if) 
wteMP3        equ    0x62            ; storage for the W register (rcif) 
wtemp4        equ    0x63            ; storage for the W register (usart error routines) 


    org    0x00                ; --==*[ RESET VECTOR ]*==-- 
    b    main 

    org    0x04                ; --==*[ INT VECTOR ]*==-- 
    b    int_handler 

    org    0x05                ; --==*[ MAIN PROGRAM ]*==-- 
main: 
    ; --==*[ VARIABLES - initialize ]*==-- 
    MOVlw    0xFF 
    MOVwf    cmdNum 
    clrf    motorL 
    clrf    motorH 
    clrf    tickL 
    clrf    tickH 
    clrf    result1L 
    clrf    result1H 
    clrf    winkelL 
    clrf    winkelH 
    clrf    quad 
    clrf    oldb 
    clrf    newb 
    clrf    tmr0o0 
    clrf    tmr0o1 

    ; --==*[ PORTS - setup port B ]*==-- 
    clrf    PORTB 
    bsf    STATUS, RP0            ; PIN 4 and 5 as input (photo-interrupter signals) 
    MOVlw    b’00110000’            ; pin 1 has to be an output (direction signal) 
    MOVwf    TRISB                ; all other pins are outputs, too (default) 
    bcf    STATUS, RP0 

    ; --==*[ PORTS - setup port C ]*==-- 
    clrf    PORTC 
    bsf    STATUS, RP0 
    MOVlw    b’11111011’            ; pin 2 as output (PWM signal) 
    MOVwf    TRISC                ; pins 6 and 7 have to be inputs (default) 
    bcf    STATUS, RP0            ; all other pins are inputs, too  (default) 

    ; --==*[ CCP1 - setup PWM Module ]*==-- 
    bsf    STATUS, RP0 
    MOVlw    d’249’                ; pwm period (calculated with formula) 
    MOVwf    PR2 
    bcf    STATUS, RP0            ; duty cycle = 0 
    clrf    CCPR1L                ; CCPR1L is upper 8 (bit: 9...2) bits of duty cycle 
    MOVlw    b’00000101’            ; enable timer2 (bit: 2) and set prescale of 1:4 (bit: 0-1) 
    MOVwf    T2CON                ; timer2 is important for pwm operation! 
    MOVlw    b’00001111’            ; select pwm mode for ccp1 module (bit: 0-3) 
    MOVwf    CCP1CON                ; and reset lower two bits of duty cycle (bit: 4-5) 

    ; --==*[ USART - setup ]*==-- 
    bsf    STATUS, RP0 
    MOVlw    0x40                ; configure baud generator register (calculated with formula) 
    MOVwf    SPBRG                ; with: 9600 baud, no parity, 8 data bits, no handshake 
    MOVlw    b’00100100’            ; enable trasmit (bit: 5) and high speed baud rate (bit: 2) 
    MOVwf    TXSTA 
    bcf    STATUS, RP0 
    MOVlw    b’10010000’            ; enable serial port (bit: 7) and continuous reception (bit: 4) 
    MOVwf    RCSTA 
    clrw                    ; w = 0 
    MOVwf    RCREG                ; reset UART receiver and fifo 
    MOVwf    RCREG                ; so we CAN avoid receive/framing/overrun errors at the beginning 
    MOVwf    RCREG 
    MOVwf    TXREG                ; just in case:     the txif flag is now valid (=1; avoids infinite loops in sendByte) 

    ; --==*[ TIMER 0 - setup ]*==-- 
    bsf    STATUS, RP0            ; this is tricky; prescaler has to be assigned to the WDT, 
                        ; in case you want to achieve 1:1 prescale 
    bcf    OPTION_REG, PS0            ; first, set prescaler to 1:2 
    bcf    OPTION_REG, PS1 
    bcf    OPTION_REG, PS2 
    bsf    OPTION_REG, PSA            ; then, assign prescaler to wdt; now we have a 1:1 prescale for timer0 :-) 
    bcf    OPTION_REG, T0SE 
    bcf    OPTION_REG, T0CS 
    bcf    STATUS, RP0 

    ; --==*[ INTERRUPTS - setup ]*==-- 
    bsf    STATUS, RP0 
    clrf    PIE1 
    bsf    PIE1, RCIE            ; enable "receive byte" interrupt 
    bcf    STATUS, RP0 
    clrf    INTCON                ; reset all interrupt flags 
    bsf    INTCON, RBIE            ; enable "interrupt on change" interrupt 
    bsf    INTCON, T0IE            ; enable "timer0 overflow" interrupt 
    bsf    INTCON, PEIE            ; enable peripheral interrupts 
    bsf    INTCON, GIE            ; enable global interrupts 

    ; --==*[ MAIN LOOP ]*==-- 
loop: 
    b        loop 


; --==*[ sendByte - ROUTINE ]*==-- 
sendByte:                    ; send byte (which is stored in W) 
sendByte_l0:                    ; wait until new data arrived in txreg 
    btfss    PIR1, TXIF            ; (inDICated via transmit interrupt flag bit: txif) 
    b        sendByte_l0 
sendByte_l1: 
    MOVwf    TXREG                ; send new data 
    return 


; --==*[ INTERRUPT HANDLING ROUTINE ]*==-- 
int_handler: 
    btfsc    RCSTA, OERR            ; overflow error occured, handle it 
    b    err_Overflow 
    btfsc    RCSTA, FERR            ; framing error occured, handle it 
    b    err_Frame 
    btfsc    PIR1, RCIF            ; receive interrupt: rcif 
    b    int_USART_receive 
    btfsc    INTCON, RBIF            ; pin interrupt: rbif 
    b    int_RB_change 
    btfsc    INTCON, T0IF            ; tmr0 interrupt: t0if 
    b    int_timer0_reset 
    retfie 

int_RB_change: 
    incf    tickL, 1            ; increment ticks (low byte) 
    btfsc    STATUS, Z 
    incf    tickH, 1            ; increment ticks on overflow (high byte) 
    incf    winkelL, 1            ; same as tick, but will not be reset (eichungswert) 
    btfsc    STATUS, Z 
    incf    winkelH, 1 
    MOVwf    wtemp1                ; save W 
    MOVfw    PORTB 
    MOVwf    newb                ; newb = PORTB 
    MOVlw    b’00110000’            ; and mask 
    andwf    oldb, 1                ; reset all bits except 4 and 5 
    andwf    newb, 1                ; reset all bits except 4 and 5 
    clrf    quad                ; reset quad value 
    clrw                    ; oldb == 00 ? 
    subwf    oldb, W 
    bz    o00 
    MOVlw    b’00010000’            ; oldb == 01 ? 
    subwf    oldb, W 
    bz    o01 
    MOVlw    b’00100000’            ; oldb == 10 ? 
    subwf    oldb, W 
    bz    o10 
    b    o11                ; else, oldb == 11 
o00: 
    MOVlw    b’00010000’            ; newb == 01 ? 
    subwf    newb, W 
    bnz    quit 
    bsf    quad, 7                ; left 
    b    quit 
o01: 
    MOVlw    b’00110000’            ; newb == 11 ? 
    subwf    newb, W 
    bnz    quit 
    bsf    quad, 7                ; left 
    b    quit 
o10: 
    clrw                    ; newb == 00 ? 
    subwf    newb, W 
    bnz    quit 
    bsf    quad, 7                ; left 
    b    quit 
o11: 
    MOVlw    b’00100000’            ; newb == 10 ? 
    subwf    newb, W 
    bnz    quit 
    bsf    quad, 7                ; left 
quit: 
    MOVfw    PORTB 
    MOVwf    oldb                ; oldb = PORTB 
    MOVfw    wtemp1                ; restore W 
    bcf    INTCON, RBIF            ; reset interrupt (important) 
    retfie 


int_timer0_reset: 
    btfsc    tmr0o0, 7            ; wait 128 overflows 
    goto    a1 
    incf    tmr0o0, 1 
    goto    a0 
a1: 
    btfsc    tmr0o1, 6            ; wait 64 overflows 
    goto    a4 
    incf    tmr0o1, 1 
    goto    a0 
a4: 
    btfsc    PORTB, 7            ; a short hack, so we can measure the impulses 
    goto    next1                ; of timer0 with an oscillograph 
    bsf    PORTB, 7            ; signal is on bit 7 of portb 
    goto    mainl 
next1: 
    bcf    PORTB, 7 
mainl: 
    MOVwf    wtemp2                ; save W 
    MOVfw    tickL                ; store ticks in result1 
    MOVwf    result1L 
    MOVfw    tickH 
    MOVwf    result1H 

    MOVfw    quad                ; and blend the direction bit on MSB of result1 
    iorwf    result1H, 1 

    clrf    tickH                ; clear tick counter 
    clrf    tickL 
    clrf    tmr0o0                ; clear timer0 overflow counters 
    clrf    tmr0o1 
    MOVfw    wtemp2                ; restore W 
a0: 
    bcf    INTCON, T0IF            ; reset interrupt (important) 
    retfie 


int_USART_receive: 
    MOVwf    wtemp3                ; save W 
    MOVlw    COMMAND_3            ; command3 active ? 
    subwf    cmdNum, W 
    bz    getData_command3        ; yes, handle it 
    MOVfw    RCREG                ; store received byte 
    clrf    RCREG                ; it’s a good idea to flush the buffer 
    clrf    RCREG                ; after receiving a byte, so it’s 
    clrf    RCREG                ; forced that we have a new byte in the buffer in the next step 
    MOVwf    recByte 
    MOVlw    COMMAND_2            ; -execute command2 ? 
    subwf    recByte, W 
    bz    command2            ;  yes, do it 
    MOVlw    COMMAND_3            ; -execute command3 ? 
    subwf    recByte, W 
    bz    command3            ;  yes, do it 
    MOVlw    COMMAND_4            ; -execute command4 ? 
    subwf    recByte, W 
    bz    command4            ;  yes, do it 

commandUnknown:                    ; else, received byte is unknown 
    bsf    PORTB, 0            ; show error on LEDs 
    MOVfw    wtemp3                ; restore W 
    retfie 

; --==*[ COMMAND EXEC - transmit motor data in debug mode ]*==-- 
command2: 
    MOVfw    result1H 
    call    sendByte 
    MOVfw    result1L 
    call    sendByte 
    MOVfw    winkelH 
    call    sendByte 
    MOVfw    winkelL 
    call    sendByte 
    MOVfw    wtemp3                ; restore W 
    retfie 

; --==*[ COMMAND INIT - setup for receive motor data (part 1/2) ]*==-- 
command3:                    ; command3 
    MOVlw    COMMAND_3 
    MOVwf    cmdNum                ; cmdNum contains now the current command value 
    MOVlw    .2 
    MOVwf    byteCnt                ; we want exactly 2 bytes from the pc 
    MOVfw    wtemp3                ; restore W 
    retfie 

; --==*[ COMMAND EXEC - receive motor data (part 2/2) ]*==-- 
getData_command3: 
    decf    byteCnt, 1            ; handle byte counter 
    bz    c3_b2                ; if byte counter is 0 then it is the 2nd byte 
    MOVfw    RCREG                ; else, 1st byte receive 
    MOVwf    motorL                ; store in motorL 
    b    outhere                ; and exit 
c3_b2: 
    MOVfw    RCREG                ; 2nd byte receive 
    MOVwf    motorH                ; store in motorH 
    MOVlw    0xFF                ; reset cmdNum to undefined value (0xFF) 
    MOVwf    cmdNum 
                        ; reconfigure PWM 
    MOVfw    motorH 
    MOVwf    CCPR1L                ; store high byte (8; bits 9 - 2) 
    bcf    CCP1CON, CCP1Y 
    btfsc    motorL, 0            ; store low byte (2; bits 0) 
    bsf    CCP1CON, CCP1Y 
    bcf    CCP1CON, CCP1X 
    btfsc    motorL, 1            ; store low byte (2; bits 1) 
    bsf    CCP1CON, CCP1X 
    btfss    motorL, 2            ; motorL<2> bit is significant for motor direction 
    b    turn_left 
    bsf    PORTB, 1            ; turn motor right 
    b    outhere 
turn_left: 
    bcf    PORTB, 1            ; turn motor left 
outhere: 
    MOVfw    wtemp3                ; restore W 
    retfie 


; --==*[ COMMAND EXEC - transmit motor data ]*==-- 
command4: 
    MOVfw    result1H            ; transmit high byte 
    call    sendByte 
    MOVfw    result1L            ; transmit low byte 
    call    sendByte 
    MOVfw    wtemp3                ; restore W 
    retfie 


; --==*[ ERROR HANDLING - for the serial communication ]*==-- 
err_Overflow:                    ; handle overflow error 
    MOVwf    wtemp4                ; save W 
    bsf    PORTB, 7            ; show error on leds (10) 
    bcf    PORTB, 6 
    bcf    RCSTA, CREN            ; dISAble continuous reception 
    MOVf    RCREG, W            ; flush receive fifo buffer (3 bytes deep) 
    MOVf    RCREG, W 
    MOVf    RCREG, W 
    bsf    RCSTA, CREN            ; reenable continuous reception 
    MOVfw    wtemp4                ; restore W 
    retfie 
err_Frame:                    ; handle frame error 
    MOVwf    wtemp4                ; save W 
    bcf    PORTB, 7            ; show error on leds (01) 
    bsf    PORTB, 6 
    MOVf    RCREG, W            ; flush receive fifo buffer (3 bytes deep) 
    MOVf    RCREG, W 
    MOVf    RCREG, W 
    MOVfw    wtemp4                ; restore W 
    retfie 


    end 




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32单片机的复用端口初始化的步骤及方法