jakeselectronics
Member
I have a simple program... LCD, Keypad blah blah blah.
Im programming a pic to controll an ISD voice recorder chip.
I had it all working with no interrupts.
Comunication with the ISD chip via SPI no probs.
Now I want to put the keypad in an interrupt. Interrupt on PORTB change.
I've been trying for a few hours now and werid stuff keeps happening.
I get the right display at power-up on the LCD.
But nothin happens with my keypad when I press buttons.
Can anyone see anything obvious???
Im programming a pic to controll an ISD voice recorder chip.
I had it all working with no interrupts.
Comunication with the ISD chip via SPI no probs.
Now I want to put the keypad in an interrupt. Interrupt on PORTB change.
I've been trying for a few hours now and werid stuff keeps happening.
I get the right display at power-up on the LCD.
But nothin happens with my keypad when I press buttons.
Can anyone see anything obvious???
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; ISD 4002 Programmer ;
; Author: Jake Sutherland ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
list p=pic16f72
include "P16F72.INC"
__config _BOREN_OFF & _CP_OFF & _PWRTEN_ON & _WDTEN_OFF & _WDT_OFF & _XT_OSC
errorlevel -302 ;Eliminate bank warning
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; PIC16F72 Microcontroller ;
; ____ ____ ;
; MCLR -| - |- RB7 Keypad Column 1 I ;
; O ISD4002 SS RA0 -| |- RB6 Keypad Column 2 I ;
; O ISD4002 CLK RA1 -| |- RB5 Keypad Column 3 I ;
; O ISD4002 MOSI RA2 -| |- RB4 Keypad Column 4 I ;
; I ISD4002 MISO RA3 -| |- RB3 Keypad Row 1 O ;
; O LCD R/S RA4 -| |- RB2 Keypad Row 2 O ;
; O LCD E RA5 -| |- RB1 Keypad Row 3 O ;
; VSS -| |- RB0 Keypad Row 4 O ;
; OSC1 -| |- VDD ;
; OSC2 -| |- VSS ;
; O LCD bit 0 RC0 -| |- RC7 LCD bit 7 O ;
; O LCD bit 1 RC1 -| |- RC6 LCD bit 6 O ;
; O LCD bit 2 RC2 -| |- RC5 LCD bit 5 O ;
; O LCD bit 3 RC3 -|_________|- RC4 LCD bit 4 O ;
; ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set EQU vales and registers
CBLOCK 0x20
GPR1 ; Countdown Reg
GPR2 ; For storing command codes
GPR3 ; Countdown Reg
GPR4 ; Countdown Reg
DELAYGPR1
DELAYGPR2
ENDC
; PORTA bits
SS EQU 0
CLK EQU 1
MOSI EQU 2
MISO EQU 3
RS EQU 4
E EQU 5
; PORTB bits
COL1 EQU 7
COL2 EQU 6
COL3 EQU 5
COL4 EQU 4
ROW1 EQU 3
ROW2 EQU 2
ROW3 EQU 1
ROW4 EQU 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0x00 ; Program starts at 0x00
GOTO START
ORG 0x04 ; Interupt vector jumps here
GOTO ISR
; Interrupt Sevice Routine
ISR
BCF INTCON, GIE
; KEYPAD ROUTINES
; This routine scans the keypad for a button press
BCF PORTB,3
BTFSS PORTB, COL1 ; Scan COL 1
CALL BTN_POWERUP ;
BTFSS PORTB, COL2 ; Scan COL 2
CALL BTN_STOP ;
BTFSS PORTB, COL3 ; Scan COL 3
CALL BTN_STOPPOWERDOWN ;
BTFSS PORTB, COL4 ; Scan COL 4
CALL BTN_READADDRESS ;
BSF PORTB,3
BCF PORTB,2
BTFSS PORTB, COL1 ;
CALL BTN_PLAY ;
BTFSS PORTB, COL2 ;
CALL BTN_SETPLAY ;
BTFSS PORTB, COL3 ;
CALL BTN_SS ;
BTFSS PORTB, COL4 ;
CALL BTN_ADDRESSINC ;
BSF PORTB,2
BCF PORTB,1
BTFSS PORTB, COL1 ;
CALL BTN_RECORD ;
BTFSS PORTB, COL2 ;
CALL BTN_SETRECORD ;
BTFSS PORTB, COL3 ;
CALL BTN_CLK ;
BTFSS PORTB, COL4 ;
CALL BTN_ADDRESSDEC ;
BSF PORTB,1
BCF PORTB,0
BTFSS PORTB, COL1 ;
CALL BTN_MESSAGECUE ;
BTFSS PORTB, COL2 ;
CALL BTN_SETMESSAGECUE ;
BTFSS PORTB, COL3 ;
CALL BTN_MOSI ;
BTFSS PORTB, COL4 ;
GOTO $+1 ;
CALL DELAY_250mS
BCF INTCON, RBIF
RETFIE
MAIN_PROGRAM
CALL INITIALISE_LCD
CALL CLEAR_DISPLAY ; Clear Display
CALL MOVE_CURSOR_04 ; Move Cursor to Position 5 on Line 1
CALL TYPE_ISD4002 ; TYPE_ISD4002
CALL MOVE_CURSOR_43 ; Move Cursor to Position 4 on Line 2
CALL TYPE_PROGRAMMER ; TYPE_PROGRAMMER
here
BSF INTCON, GIE
BSF INTCON, PEIE
BSF INTCON, RBIE
BCF OPTION_REG, NOT_RBPU
BCF INTCON, RBIF
SLEEP
NOP
goto here
; MOVLW B'00000000' ; OPTION_REG OPTION REGISTER CONTROL BYTE
; ; <7> RBPU Enable week pull-ups
; ; <6> INTEDG Interrupt on falling edge of INT pin
; ; <5> Internal instruction cycle clock
; ; <4> Increment on low-to-high transistion on T0CKI pin
; ; <3> PSA Prescaler is assigned to the Timer0 module
; ; <2:0> PS2:PS0 Prescaler set to 1:2
; MOVWF OPTION_REG
;
; MOVLW B'10001000' ; INTCON INTTERRUPT CONTROL BYTE
; ; <7> GIE Enable all interrupts
; ; <6> PEIE Disable all peripherl interrupts
; ; <5> T0IE Disable the TMR0 overflow interrupt
; ; <4> INTE Disable the INT external interrupt
; ; <3> RBIE Enable the RB port change interrupt
; ; <2> T0IF Interrupt FLAG BIT
; ; <1> INTF Interrupt FLAG BIT
; ; <0> RBIF Interrupt FLAG BIT
; MOVWF INTCON
CHARATER_TABLE ; This routine holds all the words needed for the LCD display
ADDWF PCL,F
;BAFGEDCx
RETLW A'I' ; 0
RETLW A'S' ; 1
RETLW A'D' ; 2
RETLW A' ' ; 3
RETLW A'4' ; 4
RETLW A'0' ; 5
RETLW A'0' ; 6
RETLW A'2' ; 7
RETLW A'P' ; 8
RETLW A'R' ; 9
RETLW A'O' ; 10
RETLW A'G' ; 11
RETLW A'R' ; 12
RETLW A'A' ; 13
RETLW A'M' ; 14
RETLW A'M' ; 15
RETLW A'E' ; 16
RETLW A'R' ; 17
RETURN
START
SETIO ; This rountine sets up the chips Inputs and Outputs
BCF STATUS,RP0 ; Bank 0
BCF STATUS,RP1 ; Bank 0
CLRF PORTA ; Initialize PORTA by clearing output data latches
CLRF PORTB ; Initialize PORTB by clearing output data latches
CLRF PORTC ; Initialize PORTC by clearing output data latches
BSF STATUS,RP0 ; Bank 1
BCF STATUS,RP1 ; Bank 1
MOVLW 0x06 ; Configure all pins
MOVWF ADCON1 ; as digital inputs
MOVLW B'00001000' ; Value used to initialize data direction
MOVWF TRISA ; Set RA<1:0> as outputs
; RA<3> as inputs
; RA<5:4> as outputs
; TRISA<7:6> are always
; read as ‘0’.
MOVLW B'11110000' ; Value used to initialize data direction
MOVWF TRISB ; Set RB<7:4> as outputs
; RB<3:0> as inputs
MOVLW B'00000000' ; Value used to initialize data direction
MOVWF TRISC ; Set RC<7:0> as outputs
BCF STATUS,RP0 ; Bank 0
BCF STATUS,RP1 ; Bank 0
GOTO MAIN_PROGRAM
; LCD ROUTINES
INITIALISE_LCD ; This routine initialises the LCD so that it is ready to display charaters
BSF PORTA, E ; Set E line
BCF PORTA, RS ; LCD in Command mode
CALL DELAY_1mS
MOVLW B'00111000' ; Command: 8-Bit Mode, 2 Line, 5x7 Dot Matrix
MOVWF PORTC ; Move Working Register to PORTC
CALL TOGGLE_E ; Enter
CALL DELAY_1mS
MOVLW B'00001100' ; Command: Display On, Cursor Underline Off, Blink Off
MOVWF PORTC ; Move Working Register to PORTC
CALL TOGGLE_E ; Enter
CALL DELAY_1mS
RETURN
TOGGLE_E ; This routine is called when a command/charater is ready to be entered into the LCD
BCF PORTA, E
CALL DELAY_1mS
BSF PORTA, E
RETURN
CLEAR_DISPLAY
BCF PORTA, RS ; LCD in Command mode
MOVLW B'00000001' ; Command: Clear Display
MOVWF PORTC ; Move Working Register to PORTC
CALL TOGGLE_E ; Enter
CALL DELAY_1mS
BSF PORTA, RS ; LCD in Character mode
RETURN
MOVE_CURSOR_04
BCF PORTA, RS ; LCD in Command mode
MOVLW B'10000100' ; Command: Clear Display
MOVWF PORTC ; Move Working Register to PORTC
CALL TOGGLE_E ; Enter
CALL DELAY_1mS
BSF PORTA, RS ; LCD in Character mode
RETURN
MOVE_CURSOR_43
BCF PORTA, RS ; LCD in Command mode
MOVLW B'11000011' ; Command: Clear Display
MOVWF PORTC ; Move Working Register to PORTC
CALL TOGGLE_E ; Enter
CALL DELAY_1mS
BSF PORTA, RS ; LCD in Character mode
RETURN
TYPE_ISD4002 ; Word for LCD (ISD4002)
MOVLW D'0' ; Table Line to start printing from
MOVWF GPR1 ; Move Working Register to General Purpose Register
MOVLW D'7' ; Table Line to finish printing at
MOVWF GPR3 ; Move Working Register to General Purpose Register
CALL TYPE_IT ; Call 'TYPE_IT' routine to display word on LCD (ISD4002)
RETURN
TYPE_PROGRAMMER ; Word for LCD (PROGRAMMER)
MOVLW D'8' ; Table Line to start printing from
MOVWF GPR1 ; Move Working Register to General Purpose Register
MOVLW D'17' ; Table Line to finish printing at
MOVWF GPR3 ; Move Working Register to General Purpose Register
CALL TYPE_IT ; Call 'TYPE_IT' routine to display word on LCD (ISD4002)
RETURN
TYPE_IT ; This routine is for displaying charaters on the LCD. This routine is called only after data has been stored in the 2 countdown registers
MOVF GPR1,W ; Move GPR1 to the Working Register. This number will be the line number of the table we will start printing from
CALL CHARATER_TABLE ; Call 'CHARATER_TABLE' to get charater
MOVWF PORTC ; Move Working Register (which will have the ascii character stored in it) to PORTC
CALL TOGGLE_E ; Enter into LCD
CALL DELAY_1mS ; Wait
MOVF GPR1,W ; Move GPR1 to the Working Register. This number will be the line number of the table we will start printing from
XORWF GPR3,W ; XOR the Table Line Number we are currently at with the finish Table Line Number we previously set (The 'XORWF' intruction affects the 'Zero' bit or the Status Register)
BTFSC STATUS, Z ; Test 'Zero' bit of Status Register
GOTO $+3 ; If the test returns a 'zero', the routine has been exectuted the right amount of times, The 'Zero' bit of the Status Register will be 1 if we have decreased to zero. So, we are done.
INCF GPR1 ; If the test does not return a 'zero', (meaning we have not reached the LAST Table Line Number we previously set), we do it again and print the next charater
GOTO TYPE_IT ; Do it again after INC insruction (the INCrement is so we print the NEXT charater in the table)
RETURN
; ISD4002 ChipCorder Commands
BTN_POWERUP ; This routine sends a Power Up command to the ISD4002
MOVLW 0x05 ; Move '5' into Working Register
MOVWF GPR1 ; Move Working Register to Countdown Register
MOVLW B'00100' ; Move 'Power Up code' into Working Register
GOTO ENTERCOMMAND
BTN_PLAY
MOVLW 0x05 ; Move '5' into Working Register
MOVWF GPR1 ; Move Working Register to Countdown Register
MOVLW B'11110' ; Move 'Power Up code' into Working Register
GOTO ENTERCOMMAND
BTN_RECORD
MOVLW 0x05 ; Move '5' into Working Register
MOVWF GPR1 ; Move Working Register to Countdown Register
MOVLW B'01101' ; Move 'Record code' into Working Register
GOTO ENTERCOMMAND
BTN_MESSAGECUE
SLEEP
BTN_STOP
MOVLW 0x05 ; Move '5' into Working Register
MOVWF GPR1 ; Move Working Register to Countdown Register
MOVLW B'01100' ; Move 'Stop' into Working Register
GOTO ENTERCOMMAND
BTN_SETPLAY
SLEEP
BTN_SETRECORD
SLEEP
BTN_SETMESSAGECUE
SLEEP
BTN_STOPPOWERDOWN
MOVLW 0x05 ; Move '5' into Working Register
MOVWF GPR1 ; Move Working Register to Countdown Register
MOVLW B'01000' ; Move 'Stop Power Down' into Working Register
GOTO ENTERCOMMAND
BTN_SS
BSF PORTA,SS ; Set Slave Select Line
BCF PORTA,SS ; Clear Slave Select Line
RETURN
BTN_CLK
BSF PORTA, CLK ; Set Clock Line
BCF PORTA, CLK ; Clear Clock Line
RETURN
BTN_MOSI
BTFSC PORTA, MOSI ;
GOTO $+3 ;
BSF PORTA, MOSI ; } This routine is simply to invert the MOSI Line
GOTO $+2 ;
BCF PORTA, MOSI ;
RETURN
BTN_READADDRESS
RETURN
BTN_ADDRESSINC
RETURN
BTN_ADDRESSDEC
RETURN
ENTERCOMMAND ; This routine is to clock the data into the ISD4002
MOVWF GPR2 ; Move Working Register to General Purpose Register
AGAIN BTFSS GPR2, 0 ; Test bit 1 of GPR
GOTO $+2 ; If Clear, goto here + 2
GOTO $+3 ; If Set, goto here + 3
BCF PORTA, MOSI ;
GOTO $+2 ;
BSF PORTA, MOSI ;
BSF PORTA, CLK ;
BCF PORTA, CLK ;
RRF GPR2 ;
DECF GPR1,F ; Decrease Count Reg, Put value back into Count Reg (The 'DECF' intruction affects the 'Zero' bit or the Status Register
BTFSC STATUS, Z ; Test 'Zero' bit of Status Register
GOTO $+2 ; If out Count Reg has reached Zero, the routine has been exectuted the right amount of times, The 'Zero' bit of the Status Register will be 1 if we have decreased to zero. So, we are done.
GOTO AGAIN ; Count Reg has not reached Zero, So we do it again
BSF PORTA,SS ;
BCF PORTA,SS ;
RETURN
; DELAY ROUTINES
; Actual delay = 0.001 seconds = 1000 cycles
DELAY_1mS
MOVLW 0xC6 ;
MOVWF DELAYGPR1 ;
MOVLW 0x01 ;
MOVWF DELAYGPR2 ;
DELAY_1mS_0 ;
DECFSZ DELAYGPR1, f ;
GOTO $+2 ;
DECFSZ DELAYGPR2, f ;
GOTO DELAY_1mS_0 ; 993 cycles
GOTO $+1 ;
NOP ; 3 cycles
RETURN ; 4 cycles (including call)
; Actual delay = 0.25 seconds = 250000 cycles
DELAY_250mS
MOVLW 0x4E ;
MOVWF DELAYGPR1 ;
MOVLW 0xC4 ;
MOVWF DELAYGPR2 ;
DELAY_250mS_0 ;
DECFSZ DELAYGPR1, f ;
GOTO $+2 ;
DECFSZ DELAYGPR2, f ;
GOTO DELAY_250mS_0 ; 249993 cycles
GOTO $+1 ;
NOP ; 3 cycles
RETURN ; 4 cycles (including call)
STOP GOTO STOP
END