Tutorial 4.1 - requires Main Board, LCD Board and Joystick Board.
This program uses the LCD module to give a hexadecimal display of the values of the X and Y resistors in the joystick, and an indication if the buttons are pressed or not. It uses the LCD subroutines from the previous tutorial, and subroutines written to read the joystick.
;Joystick routines with LCD display
;Nigel Goodwin 2002
LIST p=16F628 ;tell assembler what chip we are using
include "P16F628.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
templcd ;temp store for 4 bit mode
templcd2
HiX ;result for X pot
LoX
HiY ;result for Y pot
LoY
Flags
endc
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
JOY_PORT Equ PORTB
JOY_TRIS Equ TRISB
PotX Equ 0x06 ;input assignments for joystick
PotY Equ 0x03
SW1 Equ 0x07
SW2 Equ 0x02
SW1_Flag Equ 0x01 ;flags used for key presses
SW2_Flag Equ 0x02
org 0x0000
goto Start
;TABLES - moved to start of program memory to avoid paging problems,
;a table must not cross a 256 byte boundary.
HEX_Table ADDWF PCL , f
RETLW 0x30
RETLW 0x31
RETLW 0x32
RETLW 0x33
RETLW 0x34
RETLW 0x35
RETLW 0x36
RETLW 0x37
RETLW 0x38
RETLW 0x39
RETLW 0x41
RETLW 0x42
RETLW 0x43
RETLW 0x44
RETLW 0x45
RETLW 0x46
Xtext addwf PCL, f
retlw 'J'
retlw 'o'
retlw 'y'
retlw '-'
retlw 'X'
retlw ' '
retlw 0x00
Ytext addwf PCL, f
retlw 'J'
retlw 'o'
retlw 'y'
retlw '-'
retlw 'Y'
retlw ' '
retlw 0x00
presstext addwf PCL, f
retlw 'C'
retlw 'l'
retlw 'o'
retlw 's'
retlw 'e'
retlw 0x00
nopresstext addwf PCL, f
retlw 'O'
retlw 'p'
retlw 'e'
retlw 'n'
retlw ' '
retlw 0x00
;end of tables
Start movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
clrf PORTB
bcf Flags, SW1_Flag ;clear button pressed flags
bcf Flags, SW2_Flag
SetPorts bsf STATUS, RP0 ;select bank 1
movlw 0x00 ;make all LCD pins outputs
movwf LCD_TRIS
movlw 0xff ;make all joystick pins inputs
movwf JOY_TRIS
bcf STATUS, RP0 ;select bank 0
call JOY_Init ;discharge timing capacitors
call Delay100 ;wait for LCD to settle
call LCD_Init ;setup LCD module
Main
call ReadX ;read X joystick
call ReadY ;read Y joystick
call ReadSW ;read switches
call LCD_Line1 ;set to first line
call XString ;display Joy-X string
movf HiX, w ;display high byte
call LCD_HEX
movf LoX, w ;display low byte
call LCD_HEX
movlw ' '
call LCD_Char
call DisplaySW1
call LCD_Line2 ;set to second line
call YString ;display Joy-Y string
movf HiY, w ;display high byte
call LCD_HEX
movf LoY, w ;display low byte
call LCD_HEX
movlw ' '
call LCD_Char
call DisplaySW2
goto Main ;loop for ever
;Subroutines and text tables
DisplaySW1 btfsc Flags, SW1_Flag
goto Press_Str
btfss Flags, SW1_Flag
goto NoPress_Str
retlw 0x00
DisplaySW2 btfsc Flags, SW2_Flag
goto Press_Str
btfss Flags, SW2_Flag
goto NoPress_Str
retlw 0x00
XString clrf count ;set counter register to zero
Mess1 movf count, w ;put counter value in W
call Xtext ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess1
YString clrf count ;set counter register to zero
Mess2 movf count, w ;put counter value in W
call Ytext ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess2
Press_Str clrf count ;set counter register to zero
Mess3 movf count, w ;put counter value in W
call presstext ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess3
NoPress_Str clrf count ;set counter register to zero
Mess4 movf count, w ;put counter value in W
call nopresstext ;get a character from the text table
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess4
;LCD routines
;Initialise LCD
LCD_Init movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30 ;convert numbers to ASCII values
LCD_Char movwf templcd ;display character in W register
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set block cursor on
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set block cursor off
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
LCD_HEX movwf tmp1 ;display W as hexadecimal byte
swapf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
movf tmp1, w
andlw 0x0f
call HEX_Table
call LCD_Char
retlw 0x00
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00
;end of LCD routines
;joystick routines
JOY_Init ;setup joystick port
bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotX ;make PotX an output
bcf JOY_PORT, PotX ;discharge capacitor
bcf JOY_TRIS, PotY ;make PotY an output
bcf JOY_PORT, PotY ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadX
clrf HiX ;reset counter registers
clrf LoX
bsf STATUS, RP0 ;select bank 1
bsf JOY_TRIS, PotX ;make PotX an input
bcf STATUS, RP0 ;select bank 0
x1
btfsc JOY_PORT, PotX ;keep going until input high
goto EndX
incfsz LoX,f
goto x1
incfsz HiX,f
goto x1
EndX bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotX ;make PotX an output
bcf JOY_PORT, PotX ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadY
clrf HiY ;reset counter registers
clrf LoY
call Delay5
bsf STATUS, RP0 ;select bank 1
bsf JOY_TRIS, PotY ;make PotY an input
bcf STATUS, RP0 ;select bank 0
y1
btfsc JOY_PORT, PotY ;keep going until input high
goto EndY
incfsz LoY,f
goto y1
incfsz HiY,f
goto y1
EndY bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotY ;make PotY an output
bcf JOY_PORT, PotY ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadSW btfss JOY_PORT, SW1
call Sw1On
btfss JOY_PORT, SW2
call Sw2On
btfsc JOY_PORT, SW1
call Sw1Off
btfsc JOY_PORT, SW2
call Sw2Off
retlw 0x00
Sw1On bsf Flags, SW1_Flag
retlw 0x00
Sw2On bsf Flags, SW2_Flag
retlw 0x00
Sw1Off bcf Flags, SW1_Flag
retlw 0x00
Sw2Off bcf Flags, SW2_Flag
retlw 0x00
;end of joystick routines
;Delay routines
Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
;end of Delay routines
end
Tutorial 4.2 - requires Main Board, LCD Board and Joystick Board.
This second program is very similar to the previous one, except it uses a different method of counting the time taken to charge the capacitor. Whereas the first example used a simple software counter, this one uses a hardware timer for the lower byte, and an interrupt driven routine for the upper byte. This has the major advantage of being more accurate, giving 1uS resolution.
;Joystick routines with LCD display
;Nigel Goodwin 2002
LIST p=16F628 ;tell assembler what chip we are using
include "P16F628.inc" ;include the defaults for the chip
ERRORLEVEL 0, -302 ;suppress bank selection messages
__config 0x3D18 ;sets the configuration settings (oscillator type etc.)
cblock 0x20 ;start of general purpose registers
count ;used in looping routines
count1 ;used in delay routine
counta ;used in delay routine
countb ;used in delay routine
tmp1 ;temporary storage
tmp2
templcd ;temp store for 4 bit mode
templcd2
HiX ;result for X pot
LoX
HiY ;result for Y pot
LoY
Timer_H
Flags
endc
LCD_PORT Equ PORTA
LCD_TRIS Equ TRISA
LCD_RS Equ 0x04 ;LCD handshake lines
LCD_RW Equ 0x06
LCD_E Equ 0x07
JOY_PORT Equ PORTB
JOY_TRIS Equ TRISB
PotX Equ 0x06 ;input assignments for joystick
PotY Equ 0x03
SW1 Equ 0x07
SW2 Equ 0x02
SW1_Flag Equ 0x01 ;flags used for key presses
SW2_Flag Equ 0x02
org 0x0000
goto Start
ORG 0x0004
BCF INTCON, T0IF
INCF Timer_H, f
RETFIE
Start movlw 0x07
movwf CMCON ;turn comparators off (make it like a 16F84)
Initialise clrf count
clrf PORTA
clrf PORTB
bcf Flags, SW1_Flag ;clear button pressed flags
bcf Flags, SW2_Flag
SetPorts bsf STATUS, RP0 ;select bank 1
movlw 0x00 ;make all LCD pins outputs
movwf LCD_TRIS
movlw 0xff ;make all joystick pins inputs
movwf JOY_TRIS
MOVLW 0x88 ;assign prescaler to watchdog
MOVWF OPTION_REG
bcf STATUS, RP0 ;select bank 0
CLRF INTCON
BSF INTCON , T0IE ;enable timer interrupts
call JOY_Init ;discharge timing capacitors
call Delay100 ;wait for LCD to settle
call LCD_Init ;setup LCD module
Main
call ReadX ;read X joystick
call ReadY ;read Y joystick
call ReadSW ;read switches
call LCD_Line1 ;set to first line
call XString ;display Joy-X string
movf HiX, w ;display high byte
call LCD_HEX
movf LoX, w ;display low byte
call LCD_HEX
movlw ' '
call LCD_Char
call DisplaySW1
call LCD_Line2 ;set to second line
call YString ;display Joy-Y string
movf HiY, w ;display high byte
call LCD_HEX
movf LoY, w ;display low byte
call LCD_HEX
movlw ' '
call LCD_Char
call DisplaySW2
goto Main ;loop for ever
;Subroutines and text tables
DisplaySW1 btfsc Flags, SW1_Flag
goto Press_Str
btfss Flags, SW1_Flag
goto NoPress_Str
retlw 0x00
DisplaySW2 btfsc Flags, SW2_Flag
goto Press_Str
btfss Flags, SW2_Flag
goto NoPress_Str
retlw 0x00
XString clrf count ;set counter register to zero
Mess1 movf count, w ;put counter value in W
bsf PCLATH, 1
call Xtext ;get a character from the text table
bcf PCLATH, 1
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess1
YString clrf count ;set counter register to zero
Mess2 movf count, w ;put counter value in W
bsf PCLATH, 1
call Ytext ;get a character from the text table
bcf PCLATH, 1
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess2
Press_Str clrf count ;set counter register to zero
Mess3 movf count, w ;put counter value in W
bsf PCLATH, 1
call presstext ;get a character from the text table
bcf PCLATH, 1
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess3
NoPress_Str clrf count ;set counter register to zero
Mess4 movf count, w ;put counter value in W
bsf PCLATH, 1
call nopresstext ;get a character from the text table
bcf PCLATH, 1
xorlw 0x00 ;is it a zero?
btfsc STATUS, Z
retlw 0x00 ;return when finished
call LCD_Char
incf count, f
goto Mess4
;LCD routines
;Initialise LCD
LCD_Init movlw 0x20 ;Set 4 bit mode
call LCD_Cmd
movlw 0x28 ;Set display shift
call LCD_Cmd
movlw 0x06 ;Set display character mode
call LCD_Cmd
movlw 0x0d ;Set display on/off and cursor command
call LCD_Cmd
call LCD_Clr ;clear display
retlw 0x00
; command set routine
LCD_Cmd movwf templcd
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bcf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_CharD addlw 0x30 ;convert numbers to ASCII values
LCD_Char movwf templcd ;display character in W register
swapf templcd, w ;send upper nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
movf templcd, w ;send lower nibble
andlw 0x0f ;clear upper 4 bits of W
movwf LCD_PORT
bsf LCD_PORT, LCD_RS ;RS line to 1
call Pulse_e ;Pulse the E line high
call Delay5
retlw 0x00
LCD_Line1 movlw 0x80 ;move to 1st row, first column
call LCD_Cmd
retlw 0x00
LCD_Line2 movlw 0xc0 ;move to 2nd row, first column
call LCD_Cmd
retlw 0x00
LCD_CurOn movlw 0x0d ;Set block cursor on
call LCD_Cmd
retlw 0x00
LCD_CurOff movlw 0x0c ;Set block cursor off
call LCD_Cmd
retlw 0x00
LCD_Clr movlw 0x01 ;Clear display
call LCD_Cmd
retlw 0x00
LCD_HEX movwf tmp1 ;display W as hexadecimal byte
swapf tmp1, w
andlw 0x0f
bsf PCLATH, 1
call HEX_Table
bcf PCLATH, 1
call LCD_Char
movf tmp1, w
andlw 0x0f
bsf PCLATH, 1
call HEX_Table
bcf PCLATH, 1
call LCD_Char
retlw 0x00
Pulse_e bsf LCD_PORT, LCD_E
nop
bcf LCD_PORT, LCD_E
retlw 0x00
;end of LCD routines
;joystick routines
JOY_Init ;setup joystick port
bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotX ;make PotX an output
bcf JOY_PORT, PotX ;discharge capacitor
bcf JOY_TRIS, PotY ;make PotY an output
bcf JOY_PORT, PotY ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadX clrf Timer_H ;clear timer hi byte
bsf STATUS, RP0 ;select bank 1
bsf JOY_TRIS, PotX ;make PotX an input
bcf STATUS, RP0 ;select bank 0
clrf TMR0
bcf INTCON, T0IF ;start timer
bsf INTCON, GIE ;start interrupts
btfss JOY_PORT, PotX
goto $-1 ;loop until input high
clrw
iorwf TMR0, f ;stop timer (for 3 cycles)
movf TMR0, W
movwf LoX ;and read immediately
movf Timer_H, W
movwf HiX
bcf INTCON, GIE ;turn off interrupts
btfsc INTCON, GIE
goto $-2
bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotX ;make PotX an output
bcf JOY_PORT, PotX ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadY clrf Timer_H ;clear timer hi byte
bsf STATUS, RP0 ;select bank 1
bsf JOY_TRIS, PotY ;make PotY an input
bcf STATUS, RP0 ;select bank 0
clrf TMR0
bcf INTCON, T0IF ;start timer
bsf INTCON, GIE ;start interrupts
btfss JOY_PORT, PotY
goto $-1 ;loop until input high
clrw
iorwf TMR0, f ;stop timer (for 3 cycles)
movf TMR0, W
movwf LoY ;and read immediately
movf Timer_H, W
movwf HiY
bcf INTCON, GIE ;turn off interrupts
btfsc INTCON, GIE
goto $-2
bsf STATUS, RP0 ;select bank 1
bcf JOY_TRIS, PotY ;make PotY an output
bcf JOY_PORT, PotY ;discharge capacitor
bcf STATUS, RP0 ;select bank 0
retlw 0x00
ReadSW btfss JOY_PORT, SW1
call Sw1On
btfss JOY_PORT, SW2
call Sw2On
btfsc JOY_PORT, SW1
call Sw1Off
btfsc JOY_PORT, SW2
call Sw2Off
retlw 0x00
Sw1On bsf Flags, SW1_Flag
retlw 0x00
Sw2On bsf Flags, SW2_Flag
retlw 0x00
Sw1Off bcf Flags, SW1_Flag
retlw 0x00
Sw2Off bcf Flags, SW2_Flag
retlw 0x00
;end of joystick routines
;Delay routines
Delay255 movlw 0xff ;delay 255 mS
goto d0
Delay100 movlw d'100' ;delay 100mS
goto d0
Delay50 movlw d'50' ;delay 50mS
goto d0
Delay20 movlw d'20' ;delay 20mS
goto d0
Delay5 movlw 0x05 ;delay 5.000 ms (4 MHz clock)
d0 movwf count1
d1 movlw 0xC7 ;delay 1mS
movwf counta
movlw 0x01
movwf countb
Delay_0
decfsz counta, f
goto $+2
decfsz countb, f
goto Delay_0
decfsz count1 ,f
goto d1
retlw 0x00
;end of Delay routines
ORG 0x0200
;TABLES - moved to avoid paging problems,
;a table must not cross a 256 byte boundary.
HEX_Table ADDWF PCL , f
RETLW 0x30
RETLW 0x31
RETLW 0x32
RETLW 0x33
RETLW 0x34
RETLW 0x35
RETLW 0x36
RETLW 0x37
RETLW 0x38
RETLW 0x39
RETLW 0x41
RETLW 0x42
RETLW 0x43
RETLW 0x44
RETLW 0x45
RETLW 0x46
Xtext addwf PCL, f
retlw 'J'
retlw 'o'
retlw 'y'
retlw '-'
retlw 'X'
retlw ' '
retlw 0x00
Ytext addwf PCL, f
retlw 'J'
retlw 'o'
retlw 'y'
retlw '-'
retlw 'Y'
retlw ' '
retlw 0x00
presstext addwf PCL, f
retlw 'C'
retlw 'l'
retlw 'o'
retlw 's'
retlw 'e'
retlw 0x00
nopresstext addwf PCL, f
retlw 'O'
retlw 'p'
retlw 'e'
retlw 'n'
retlw ' '
retlw 0x00
;end of tables
end
The first change in this program is the main program start address, previously we started as immediately after the reset vector (0x0000) as possible, but the interrupt vector is located at 0x0004 so we need to skip over this with a 'goto Start' command. The small interrupt routine itself is located an 0x0004 and simply increments the high byte counter every time the hardware low byte counter overflows. The other two lines in the interrupt routine re-enable interrupts (they are cancelled automatically when called) and the return from the routine, this time using 'retfie' (Return From Interrupt) rather than 'retlw
Problems with Microcontroller Projects? You may face many Problems, but do not worry we are ready to solve your Problems. All you need to do is just leave your Comments. We will assure you that you will find a solution to your project along with future tips. On Request we will Mail you the Codes for Registered Members of this site only, at free service...Follow Me.
Subscribe to:
Post Comments (Atom)
Recent Comments
Popular Projects
-
Construction of microcontroller based Touchscreen Mobile Phone with Password protected features. Touch Screen GLCD based Digital Devices C...
-
The first project I am posting in this blog is a microcontroller project that communicates with a Siemens M55 mobile phone through the seria...
-
In this project we have used two types of different R.F Module like 433Mhz and 315Mhz interface into Pic16f877a,HT640 for R.F Encoder,HT64...
-
Click below links to get the project: Design with microcontrollers:Final year ECE projects ATmega644 JTAG Debugger Ultrasonic Hapti...
-
Introduction A digital thermometer is a good choice of project for beginners who just stepped in to the world of microcontrollers because it...
-
Automation today has increased the speed of living. This project in which radio frequency is used to automatically control the door locks a...
-
After finishing the serial LCD project , it is time to do some cool projects using PIC12F683. Now we can have a nice LCD display with PIC1...
-
Introduction Tachometer is a device that gives you the information about the rotational speed of any shaft or disc. It usually measures the...
-
The project is a GSM SMS Controller without using any GSM modem. This is using the BTSerial1 module which wirelessly connects to a Bluetoot...
-
Introduction Heart rate measurement indicates the soundness of the human cardiovascular system. This project demonstrates a technique to mea...
No comments:
Post a Comment