Ahoj,
mám trochu trable s přerušením od pinů portu B při změně. Nejsem si jistý, jestli to mám špatně napsané, nebo jestli je to špatně přeložené, každopádně to nefunguje.
Část kódu, který chci použiít ve svém programu přikládám (je to jen obsluha přerušení a vypsání na LCD + deklarace a nastavení). Mělo by to v přerušení načítat impulsy z kvadraturního enkodéru a vypsat výsledek na displej:
[code]Define CONF_WORD = 0x3f72
Define CLOCK_FREQUENCY = 12
Define LCD_BITS = 4
Define LCD_DREG = PORTD
Define LCD_DBIT = 4
Define LCD_RSREG = PORTC
Define LCD_RSBIT = 0
Define LCD_EREG = PORTC
Define LCD_EBIT = 2
Define LCD_RWREG = PORTC
Define LCD_RWBIT = 1
Define LCD_COMMANDUS = 5000
Define LCD_DATAUS = 100
Define LCD_INITMS = 100
'Define LCD_READ_BUSY_FLAG = 1
OPTION_REG.7 = 1
TRISD = 0x00
AllDigital
Symbol ra_a = PORTB.5
Symbol ra_b = PORTB.2
Dim ra_a_last As Bit
Dim ra_b_last As Bit
Dim ra_cw As Bit
Dim ra_enc As Word
ra_enc = 7100
ra_a_last = ra_a
ra_b_last = ra_b
INTCON.GIE = 1 'enable all un-masked interrupts
INTCON.RBIE = 1 'enable RB0/INT interrupts
Lcdinit
loop:
Lcdcmdout LcdClear
Lcdout “X”, #ra_enc
WaitMs 500
Goto loop
End
On Interrupt 'Rutina preruseni
If PORTB.5 <> ra_a_last Then
If PORTB.5 = PORTB.2 Then
ra_enc = ra_enc - 1
ra_cw = 0
Else
ra_enc = ra_enc + 1
ra_cw = 1
Endif
Endif
ra_a_last = PORTB.5
ra_b_last = PORTB.2
INTCON.RBIF = 0
Resume [/code]
Přeložené (a vlastně celé psané) je to v PIC Simulator IDE:
; Compiled with: PIC Simulator IDE v6.86
; Microcontroller model: PIC16F877A
; Clock frequency: 12.0 MHz
;
; The address of 'ra_a' (bit) (global) is 0x6,5
; The address of 'ra_b' (bit) (global) is 0x6,2
; The address of 'ra_a_last' (bit) (global) is 0x2C,0
; The address of 'ra_b_last' (bit) (global) is 0x2C,1
; The address of 'ra_cw' (bit) (global) is 0x2C,2
; The address of 'ra_enc' (word) (global) is 0x2D
ra_enc EQU 0x2D
; Begin
R0L EQU 0x20
R0H EQU 0x21
R1L EQU 0x22
R1H EQU 0x23
R2L EQU 0x24
R2H EQU 0x25
R3L EQU 0x26
R3H EQU 0x27
R4L EQU 0x28
R4H EQU 0x29
R5L EQU 0x2A
R5H EQU 0x2B
W_TEMP EQU 0x7F
STATUS_TEMP EQU 0x7E
ORG 0x0000
BCF PCLATH,3
BCF PCLATH,4
GOTO L0002
ORG 0x0004
MOVWF W_TEMP
SWAPF STATUS,W
CLRF STATUS
MOVWF STATUS_TEMP
CALL L0003
SWAPF STATUS_TEMP,W
MOVWF STATUS
SWAPF W_TEMP,F
SWAPF W_TEMP,W
RETFIE
; Begin of program
L0002:
; 1: Define CONF_WORD = 0x3f72
; 2: Define CLOCK_FREQUENCY = 12
; 3:
; 4: Define LCD_BITS = 4
; 5: Define LCD_DREG = PORTD
; 6: Define LCD_DBIT = 4
; 7: Define LCD_RSREG = PORTC
; 8: Define LCD_RSBIT = 0
; 9: Define LCD_EREG = PORTC
; 10: Define LCD_EBIT = 2
; 11: Define LCD_RWREG = PORTC
; 12: Define LCD_RWBIT = 1
; 13: Define LCD_COMMANDUS = 5000
; 14: Define LCD_DATAUS = 100
; 15: Define LCD_INITMS = 100
; 16: 'Define LCD_READ_BUSY_FLAG = 1
; 17:
; 18: OPTION_REG.7 = 1
BSF STATUS,RP0
BSF 0x01,7
; 19:
; 20: TRISD = 0x00
CLRF 0x08
; 21:
; 22: AllDigital
MOVLW 0x06
MOVWF 0x1F
MOVLW 0x07
MOVWF 0x1C
BCF STATUS,RP0
; 23:
; 24: Symbol ra_a = PORTB.5
; 25: Symbol ra_b = PORTB.2
; 26:
; 27: Dim ra_a_last As Bit
; 28: Dim ra_b_last As Bit
; 29:
; 30: Dim ra_cw As Bit
; 31:
; 32: Dim ra_enc As Word
; 33: ra_enc = 7100
MOVLW 0xBC
MOVWF 0x2D
MOVLW 0x1B
MOVWF 0x2E
; 34:
; 35:
; 36: ra_a_last = ra_a
BTFSC 0x06,5
BSF 0x2C,0
BTFSS 0x06,5
BCF 0x2C,0
; 37: ra_b_last = ra_b
BTFSC 0x06,2
BSF 0x2C,1
BTFSS 0x06,2
BCF 0x2C,1
; 38:
; 39: INTCON.GIE = 1 'enable all un-masked interrupts
BSF 0x0B,7
; 40: INTCON.RBIE = 1 'enable RB0/INT interrupts
BSF 0x0B,3
; 41:
; 42: Lcdinit
BCF 0x07,2
BCF 0x07,0
BCF 0x07,1
BSF STATUS,RP0
BCF 0x07,2
BCF 0x07,0
BCF 0x07,1
MOVLW 0x0F
ANDWF 0x08,F
BCF STATUS,RP0
MOVLW 0x64
MOVWF R0L
MOVLW 0x00
MOVWF R0H
CALL W001
MOVLW 0x33
CALL LC02
MOVLW 0x33
CALL LC02
MOVLW 0x33
CALL LC02
MOVLW 0x22
CALL LC02
MOVLW 0x28
CALL LC02
MOVLW 0x0C
CALL LC02
MOVLW 0x01
CALL LC02
; 43:
; 44: loop:
L0001:
; 45:
; 46: Lcdcmdout LcdClear
MOVLW 0x01
CALL LC02
; 47: Lcdout "X", #ra_enc
MOVLW 0x58
CALL LC01
MOVF 0x2D,W
MOVWF R2L
MOVF 0x2E,W
MOVWF R2H
CALL LC21
; 48: WaitMs 500
MOVLW 0xF4
MOVWF R0L
MOVLW 0x01
MOVWF R0H
CALL W001
; 49:
; 50: Goto loop
GOTO L0001
; 51:
; 52: End
L0004: GOTO L0004
; 53:
; 54: On Interrupt 'Rutina preruseni
L0003:
; 55:
; 56: If PORTB.5 <> ra_a_last Then
CLRW
BTFSC 0x06,5
ADDLW 0x01
BTFSC 0x2C,0
SUBLW 0x01
BTFSC STATUS,Z
GOTO L0005
; 57: If PORTB.5 = PORTB.2 Then
CLRW
BTFSC 0x06,5
ADDLW 0x01
BTFSC 0x06,2
SUBLW 0x01
BTFSS STATUS,Z
GOTO L0006
; 58: ra_enc = ra_enc - 1
MOVLW 0x01
SUBWF 0x2D,W
MOVWF 0x2D
MOVLW 0x00
BTFSS STATUS,C
ADDLW 0x01
SUBWF 0x2E,W
MOVWF 0x2E
; 59: ra_cw = 0
BCF 0x2C,2
; 60: Else
GOTO L0007
L0006:
; 61: ra_enc = ra_enc + 1
MOVF 0x2D,W
ADDLW 0x01
MOVWF 0x2D
MOVF 0x2E,W
BTFSC STATUS,C
ADDLW 0x01
ADDLW 0x00
MOVWF 0x2E
; 62: ra_cw = 1
BSF 0x2C,2
; 63:
; 64: Endif
L0007:
; 65: Endif
L0005:
; 66:
; 67: ra_a_last = PORTB.5
BTFSC 0x06,5
BSF 0x2C,0
BTFSS 0x06,5
BCF 0x2C,0
; 68: ra_b_last = PORTB.2
BTFSC 0x06,2
BSF 0x2C,1
BTFSS 0x06,2
BCF 0x2C,1
; 69:
; 70: INTCON.RBIF = 0
BCF 0x0B,0
; 71:
; 72: Resume
RETURN
; End of program
L0008: GOTO L0008
; Division Routine
D001: MOVLW 0x10
MOVWF R3L
CLRF R2H
CLRF R2L
D002: RLF R0H,W
RLF R2L,F
RLF R2H,F
MOVF R1L,W
SUBWF R2L,F
MOVF R1H,W
BTFSS STATUS,C
INCFSZ R1H,W
SUBWF R2H,F
BTFSC STATUS,C
GOTO D003
MOVF R1L,W
ADDWF R2L,F
MOVF R1H,W
BTFSC STATUS,C
INCFSZ R1H,W
ADDWF R2H,F
BCF STATUS,C
D003: RLF R0L,F
RLF R0H,F
DECFSZ R3L,F
GOTO D002
MOVF R0L,W
RETURN
; Waitms Routine
W001: MOVF R0L,F
BTFSC STATUS,Z
GOTO W002
CALL W003
DECF R0L,F
NOP
NOP
NOP
NOP
NOP
GOTO W001
W002: MOVF R0H,F
BTFSC STATUS,Z
RETURN
CALL W003
DECF R0H,F
DECF R0L,F
GOTO W001
W003: MOVLW 0x0C
MOVWF R2H
W004: DECFSZ R2H,F
GOTO W004
NOP
NOP
MOVLW 0x3A
MOVWF R1L
W005: DECFSZ R1L,F
GOTO W006
CALL W007
CALL W007
NOP
NOP
RETURN
W006: CALL W007
GOTO W005
W007: MOVLW 0x0D
MOVWF R2L
W008: DECFSZ R2L,F
GOTO W008
NOP
RETURN
; Waitus Routine - Byte Argument
X001: MOVLW 0x04
SUBWF R4L,F
BTFSS STATUS,C
RETURN
GOTO X002
X002: MOVLW 0x02
SUBWF R4L,F
BTFSS STATUS,C
RETURN
GOTO X002
; Waitus Routine - Word Argument
Y001: MOVLW 0x06
SUBWF R4L,F
CLRW
BTFSS STATUS,C
ADDLW 0x01
SUBWF R4H,F
BTFSS STATUS,C
RETURN
GOTO Y002
Y002: MOVLW 0x04
SUBWF R4L,F
CLRW
BTFSS STATUS,C
ADDLW 0x01
SUBWF R4H,F
NOP
NOP
BTFSS STATUS,C
RETURN
GOTO Y002
; Lcdout Routine
LC01: MOVWF R4L
BSF 0x07,0
BCF 0x07,1
MOVLW 0x0F
ANDWF 0x08,F
MOVF R4L,W
ANDLW 0xF0
IORWF 0x08,F
CALL LCX1
SWAPF R4L,F
MOVLW 0x0F
ANDWF 0x08,F
MOVF R4L,W
ANDLW 0xF0
IORWF 0x08,F
CALL LCX1
MOVLW 0x64
MOVWF R4L
CALL X001
RETURN
LCX1: BSF 0x07,2
NOP
NOP
NOP
BCF 0x07,2
NOP
NOP
NOP
RETURN
; Lcdcmdout Routine
LC02: MOVWF R4L
BCF 0x07,0
BCF 0x07,1
MOVLW 0x0F
ANDWF 0x08,F
MOVF R4L,W
ANDLW 0xF0
IORWF 0x08,F
CALL LCX1
SWAPF R4L,F
MOVLW 0x0F
ANDWF 0x08,F
MOVF R4L,W
ANDLW 0xF0
IORWF 0x08,F
CALL LCX1
MOVLW 0x88
MOVWF R4L
MOVLW 0x13
MOVWF R4H
CALL Y001
RETURN
; Lcdout Decimal Conversion Routine
LC21: BSF R3H,7
MOVLW 0x27
MOVWF R1H
MOVLW 0x10
CALL LC22
MOVLW 0x03
MOVWF R1H
MOVLW 0xE8
CALL LC22
CLRF R1H
MOVLW 0x64
CALL LC22
CLRF R1H
MOVLW 0x0A
CALL LC22
MOVF R2L,W
GOTO LC23
LC22: MOVWF R1L
MOVF R2H,W
MOVWF R0H
MOVF R2L,W
MOVWF R0L
CALL D001
MOVF R0L,W
BTFSS STATUS,Z
BCF R3H,7
BTFSC R3H,7
RETURN
LC23: ADDLW 0x30
CALL LC01
RETURN
; Configuration word settings
ORG 0x2007
DW 0x3F72
; End of listing
END
Vím, že to není ideální, ale jako věčnému začátečníkovi vyhovuje možnost rovnou to odsimulovat… A v Basicu se mi píše dobře, nic jiného neznám…
Netušil by někdo, co v tom mám za botu? Můžu ukroutit osičku enkodéru a ani se to nehne. Zkoušel jsem to všelijak trápit, ale výsledkem bylo, že se buď nic nedělo, nebo že přerušení uvízlo ve smyčce…
Moc díky, i za nakopnutí správným směrem.
Martin
administrator: přejmenováno z "Přerušení od RB4-7 na 16F877A"