by Michael Brown of Instant Net Solutions www.KillerPCs.net
Code:
;---------------------------------------------------------------------------------------------
; HEADER:
;---------------------------------------------------------------------------------------------
LIST P=16f84a
RADIX DEC
INCLUDE "p16f84a.inc"
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
; This program and the code/routines contained within are Copyright 2001,2003 by michael brown. It may
; not be used for commercial purposes without written consent from the Copyright holder (me). It
; is free for personal use as long as this Copyright message is kept intact. If commercial
; usage is desired, please contact michael brown via e-mail at n5qmg@amsat.org to make licensing
; arrangements. I'm not trying to be a greedy jerk, but I have to eat too. ;-)
;
; 73's de N5QMG
;---------------------------------------------------------------------------------------------
#define Clock_Freq 4000000
#include "wait.mac"
;---------------------------------------------------------------------------------------------
; EQUATES:
;---------------------------------------------------------------------------------------------
RS equ 0 ;LCD's pin 4 should be connected to PORTB.0
RW equ 1 ;LCD's pin 5 should be connected to PORTB.1
EN equ 2 ;LCD's pin 6 should be connected to PORTB.2
#define LCD_PORT PORTB ;LCD_PORT implies use of bits 4-7 for data lines to LCD
#define LCD_RS LCD_PORT, RS
#define LCD_RW LCD_PORT, RW
#define LCD_EN LCD_PORT, EN
#define LCD_DAT7 LCD_PORT, 7
#define LCD_DAT6 LCD_PORT, 6
#define LCD_DAT5 LCD_PORT, 5
#define LCD_DAT4 LCD_PORT, 4
#define YEL_LED PORTA, 0
#define RED_LED PORTA, 1
#define INTSCOPE PORTA, 2
#define MAIN_SCOPE PORTA, 3
#define ONE_WIRE PORTA, 4 ;Dallas 1-wire bus
MAX_DEVICES equ 4 ;Maximum number of 1-wire devices to find
STARTOFRAM equ 0x0C ;First Usable RAM Location for 16f84
ENDOFRAM equ 0x4F ;Last Usable RAM Location for 16f84
;
; General Purpose Temp Storage
;
cblock STARTOFRAM
OneWireByte
SOURCE
DEST
TEMP0
TEMP1
TEMP2
tempone
temptwo
;
; ISR Register Save Areas
;
;INT_FLAGS
;W_TEMP
;STATUS_TEMP
;FSR_TEMP
;
; ISR Loop Control
;
;LoopCntH
;LoopCntL
;
; Variables Relating to LCD Control
;
CursorRow ; Current Cursor Position
CursorCol
AbsAddr ; Absolute cursor position (start address of CursorRow + CursorCol)
SrcRowNum ; Source Row Number
DestRowNum ; Destination Row Number
SrcCharAddr ; DDRAM address in LCD
DestCharAddr ; DDRAM address in LCD
RowLoopCtr ; For Scrolling the screen
CharLoopCtr ; Same as above
LCD_Data
TEMPX
;
; Work areas
;
rombit_idx
bits
ctr_1wire
curr_discrep
last_discrep
done_flag
return_value
; One-Wire work area
work0 ; CRC (8 bits)
work1 ; Serial # (48 bits)
work2 ; "
work3 ; "
work4 ; "
work5 ; "
work6 ; "
work7 ; Family Code (8 bits)
;Sensor 0 Storage
ts00
ts01
ts02
ts03
ts04
ts05
ts06
ts07
;Sensor 1 Storage
ts10
ts11
ts12
ts13
ts14
ts15
ts16
ts17
;Sensor 2 Storage
ts20
ts21
ts22
ts23
ts24
ts25
ts26
ts27
;Sensor 3 Storage
ts30
ts31
ts32
ts33
ts34
ts35
ts36
ts37
endc
;---------------------------------------------------------------------------------------------
; START:
;---------------------------------------------------------------------------------------------
org 0x000
goto Start
org 0x004
; movwf W_TEMP ;Save everything
; swapf STATUS, W
; movwf STATUS_TEMP
; movfw FSR
; movwf FSR_TEMP
;
; Interrupt handler right here
;
; bsf INTSCOPE ;Mark start of interrupt routine
; bcf INTSCOPE ;Mark end of interrupt routine (for timing)
;
; Restore everything and return
;
;IntExit
; movfw FSR_TEMP
; movwf FSR
; swapf STATUS_TEMP, W
; movwf STATUS
; swapf W_TEMP, F
; swapf W_TEMP, W
retfie
;-------------------------------------------------------------
;Store_Bit -- take bit A (bits.1) and store into work0..work7
; at bit offset rombit_idx (1 relative)
; Entry:
; bits - contains 2 bits read from 1 wire bus bits.1 is the one to store
; rombit_idx - contains one relative bit offset from rom work area (work0..work7)
; of bit to store
; Exit:
; bits.1 -> work0..work7(rombit_idx)
;-------------------------------------------------------------
Store_Bit
call SetupFSR ;convert rombit_idx to something we can use
;Determine if we need to set a bit (1) or clear a bit (0)
movlw HIGH SetWorkBit
movwf PCLATH
rrf bits, W ;get bit.1 value right justified into W
andlw b'00000001' ;maintain sanity
addwf PCL, F ;quick test for 0 or 1
goto ClrWorkBit ;must be 0 (clr bit)
SetWorkBit ;must be 1 (set bit)
clrc
rlf TEMP2, W ;get bit position * 2 (0, 2, 4 .. 14)
addwf PCL, F ;bump PC, turn bit on then return
bsf INDF, 7
return
bsf INDF, 6
return
bsf INDF, 5
return
bsf INDF, 4
return
bsf INDF, 3
return
bsf INDF, 2
return
bsf INDF, 1
return
bsf INDF, 0
return
ClrWorkBit
movlw HIGH ClrWorkBit
movwf PCLATH
clrc
rlf TEMP2, W ;get bit position * 2 (0, 2, 4 .. 14)
addwf PCL, F ;bump PC and turn it off then return
bcf INDF, 7
return
bcf INDF, 6
return
bcf INDF, 5
return
bcf INDF, 4
return
bcf INDF, 3
return
bcf INDF, 2
return
bcf INDF, 1
return
bcf INDF, 0
return
;-------------------------------------------------------------
;GetWorkBit --
; at bit offset rombit_idx (1 relative)
; Entry:
; rombit_idx - contains one relative bit offset from rom work area (work0..work7)
; of bit to retrieve value of
; Exit:
; work0..work7(rombit_idx) -> W
;--------------------------------------------------------------
GetWorkBit
call SetupFSR ;point to the bit in question
movlw HIGH GetWorkBit
movwf PCLATH
clrc
rlf TEMP2, W ;get bit position * 2 into w
addwf TEMP2, W ;compute w = bit offset * 3 (0, 3, 6 ...)
addwf PCL, F ;bump PC to jump to appropriate test
;Bit 0
btfss INDF, 7 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 1
btfss INDF, 6 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 2
btfss INDF, 5 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 3
btfss INDF, 4 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 4
btfss INDF, 3 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 5
btfss INDF, 2 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 6
btfss INDF, 1 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;Bit 7
btfss INDF, 0 ;Is bit set(1)
retlw d'0' ; No, return 0
retlw d'1' ; Yes, return 1
;---------------------------------------------------------------------
;Lookup_TS -- Return address of start of 8 byte entry within TS table
; Entry:
; W contains slot number within TS table (0,1,2, or 3)
; Exit:
; W contains address of beginning of slot pointed to by W
;---------------------------------------------------------------------
Lookup_TS
andlw b'00000011'
addwf PCL, F
retlw ts00
retlw ts10
retlw ts20
retlw ts30
;---------------------------------------------------------------------------------------------
;
; lookup_row - Lookup ddram address of beginning of row for LCD
;
;---------------------------------------------------------------------------------------------
lookup_row addwf PCL, F ; bump PC by zero relative row number
retlw 0x00 ; start of row 0
retlw 0x40 ; row 1
retlw 0x14 ; row 2
retlw 0x54 ; row 3
;----------------------------------------------------------------------------------------
; SetupFSR -- Point FSR at byte within work area determined by rombit_idx
; Entry:
; rombit_idx contians bit number (one relative) we need to get to
; Exit:
; FSR - pointing at byte within work0..work7
; TEMP1 - zero relative byte offset (0,1,..7)
; TEMP2 - zero relative(0,1,..7) bit offset within byte
;----------------------------------------------------------------------------------------
SetupFSR ;Setup FSR, TEMP1(byte offset), and TEMP2(bit offset)
decf rombit_idx, W ;convert index to 0 relative
sublw d'63' ;form compliment of rombit_idw 0-63->63-0
movwf TEMP1 ; and temp byte offset area
andlw b'00000111' ;strip off byte offset leaving bit offset only
movwf TEMP2 ; and save into temp bit offset area
clrc ;right justify the byte offset in TEMP1
rrf TEMP1, F ; by right shifting
clrc ; and stripping 3 LSB's
rrf TEMP1, F
clrc
rrf TEMP1, F
;Get FSR pointing at appropriate byte in work area (work0, work1 ...)
movlw work0 ;Point FSR at beginning of work area
movwf FSR
movfw TEMP1 ;get byte offset (0 relative)
addwf FSR, F ; point FSR straight at it
return
;---------------------------------------------------------------------------------------------
;
; Main level code begins here
;
;---------------------------------------------------------------------------------------------
Start
bsf STATUS, RP0 ;Switch to Bank 1
movlw b'00000000' ;Define I/O on Port B (all outputs)
movwf TRISB & 0x07F
movlw b'00000' ;Define I/O on Port A (all outputs)
movwf TRISA & 0x07F
bcf STATUS, RP0 ;Back to Bank 0
clrf PORTA
clrf PORTB
Main
; Waste a couple of seconds between itterations
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
Wait 100 Millisecs, 0
call LCD_Init ;Initialize the LCD
movlw 'I' ;Display Init message
call LCD_Txt
movlw 'n'
call LCD_Txt
movlw 'i'
call LCD_Txt
movlw 't'
call LCD_Txt
movlw 'i'
call LCD_Txt
movlw 'a'
call LCD_Txt
movlw 'l'
call LCD_Txt
movlw 'i'
call LCD_Txt
movlw 'z'
call LCD_Txt
movlw 'e'
call LCD_Txt
movlw 'd'
call LCD_Txt
movlw ' ' ;Display Version
call LCD_Txt
movlw 'V'
call LCD_Txt
movlw 'e'
call LCD_Txt
movlw 'r'
call LCD_Txt
movlw '.'
call LCD_Txt
movlw ' '
call LCD_Txt
movlw '0'
call LCD_Txt
movlw '.'
call LCD_Txt
movlw '1'
call LCD_Txt
movlw 0x03 ;position to bottem row
movwf CursorRow
movlw 0x13 ;position to last column
movwf CursorCol
call Search_1Wire_init
_search_next
; movlw 'a'
; call LCD_Print
call Search_1Wire ;Initiate a search
; movlw 'b'
; call LCD_Print
btfss return_value, 0 ;See if we found anything
goto _search_done ;Nope, we are done
; movlw 'c'
; call LCD_Print
movlw work0 ;get address of work area
movwf SOURCE ;make it the source for block move
movlw HIGH Lookup_TS
movwf PCLATH
movfw ctr_1wire ;get device count
call Lookup_TS ;get address of its entry
movwf DEST ;set as destination for block move
call Block_Move ;copy the work area off to storage
call Print_Work_Area
incf ctr_1wire, F ;count the one just found
movlw MAX_DEVICES
xorwf ctr_1wire, W
btfss STATUS, Z ;is it 4 devices found yet
goto _search_next ; No, try for another
_search_done
; movlw 'X'
; call LCD_Print
goto Main
Print_Work_Area
movfw work0
call LCD_Hex
movlw ':'
call LCD_Print
movfw work1
call LCD_Hex
movfw work2
call LCD_Hex
movfw work3
call LCD_Hex
movfw work4
call LCD_Hex
movfw work5
call LCD_Hex
movfw work6
call LCD_Hex
movlw ':'
call LCD_Print
movfw work7
call LCD_Hex
movlw 0x13 ;position to last column so next byte starts on new line
movwf CursorCol
return
;-------------------------------------------------------------------
;
; Search the Dallas 1-Wire Bus
;
;-------------------------------------------------------------------
Search_1Wire_init
clrf ctr_1wire ;init device counter(effectively clears table)
clrf work0 ;clear the work area to zeros
clrf work1
clrf work2
clrf work3
clrf work4
clrf work5
clrf work6
clrf work7
clrf last_discrep ;init the bit position of last descrepancy
clrf done_flag ;set status to not done
return
Search_1Wire
clrf return_value ;set return flag to false
btfss done_flag,0 ;Are we done yet?
goto Do_reset ; No, start a search
clrf done_flag ; Yes, init this for next time???
goto Wrapup ; and get on out of here
Do_reset
call Reset_1wire
clrf rombit_idx ;set rom bit index to 1
incf rombit_idx, F
clrf curr_discrep ;set descrepancy marker to 0
movlw h'f0' ;send search rom
movwf OneWireByte
call Sendbyte_1wire ; command to devices
bsf MAIN_SCOPE
bcf MAIN_SCOPE
Get_2bits
call Readbit_1wire ;read bit a from bus and
movwf bits ; save it
clrc ;clear the carry flag
rlf bits, F ;shift bit A over to the left
call Readbit_1wire ;read bit B from bus and
iorwf bits, F ; save it
movlw HIGH lookup_1x
movwf PCLATH
movfw bits
lookup_1x
addwf PCL, F ;decode the bits read
goto bits_00 ;collision detected
goto bits_01 ;0 read
goto bits_10 ;1 read
goto bits_11 ;nobody there
bits_00 ;collision detected
;Does rombit_idx = last_discrep
; movlw '0'
; call LCD_Print
movfw rombit_idx
xorwf last_discrep, W
btfss STATUS, Z ;Does rombit_idx = last_discrep
goto _chknxt ; No, check other stuff
movlw b'10' ; Yes, pretend we read a 1
movwf bits
call Store_Bit ;Store a 1 into work area
goto ack_bus
_chknxt
movfw last_discrep ;get current bit position
subwf rombit_idx, W ;compare to last discrepancy position
;is rombit_idx > last_discrep
btfss STATUS, C
goto _chknx2 ; No,
movlw b'01' ; Yes, pretend we read a 0
movwf bits
call Store_Bit
;set discrepancy marker to rombit_idx
movfw rombit_idx
movwf curr_discrep
goto ack_bus
_chknx2
;does rombits(rombit_idx) = 0 ?
call GetWorkBit ;get bit located at work(rombit_idx)
movwf TEMP0 ; and save
movlw HIGH lookup_2x
movwf PCLATH
movfw TEMP0
lookup_2x
addwf PCL, F ;quik test for 0 or 1
goto _zero ; was 0
_one ; was 1
movlw b'10' ; Pretend we read a 1
movwf bits
goto ack_bus
_zero
movlw b'01' ; Pretend we read a 0
movwf bits
;set discrepancy marker to rombit_idx
movfw rombit_idx
movwf curr_discrep
goto ack_bus
bits_01 ;0 received
; movlw '1'
; call LCD_Print
goto _storit
bits_10 ;1 received
; movlw '2'
; call LCD_Print
_storit
call Store_Bit ;Save it into work area at rombit_idx offset
; Send rombit(rombit_idx) to 1-wire bus
ack_bus
; call GetWorkBit
clrc ;clear the carry flag and
rrf bits, W ; get bit A into W
call Sendbit_1wire ;send bit A to wire
; Increment rombit_idx
incf rombit_idx, F ;bump pointer to next location
; Is rombit_idx > 64?
movfw rombit_idx ;see if index > 64
sublw d'65' ; (i.e. = 65)
btfss STATUS, Z
goto Get_2bits ;if not, loop back for more
;set last discrepancy to descrepancy marker
movfw curr_discrep
movwf last_discrep
;is last discrepancy = 0?
btfsc STATUS, Z
incf done_flag, F ;yes, set done flag
movlw d'1' ;either way, set return value to true
movwf return_value
goto Wrapup
bits_11 ;nothing answered on the bus
movlw 'D'
call LCD_Print
movlw 'e'
call LCD_Print
movlw 'a'
call LCD_Print
movlw 'd'
call LCD_Print
movlw 'B'
call LCD_Print
movlw 'e'
call LCD_Print
movlw 'e'
call LCD_Print
movlw 'f'
call LCD_Print
clrf last_discrep
goto Wrapup
Wrapup
return
;---------------------------------------------------------------------
;Reset the one wire bus
;---------------------------------------------------------------------
Reset_1wire
bcf ONE_WIRE ;Pull it low
Wait 480 Microsecs, 0 ;Hold it till they are reset
bsf ONE_WIRE ;Let it idle back up
;
;*** suppose to check for ack from devices here, but why?? I'm leaving it out for now
;
Wait 500 Microsecs, 0
return
;---------------------------------------------------------------------
;Send bytes and bits on the one wire bus
; BYTE -- Send a byte from OneWireByte to the one wire bus
; bit -- Send bits, 1 to the one wire bus
;---------------------------------------------------------------------
Sendbyte_1wire
movlw d'8'
movwf TEMP0
; bsf MAIN_SCOPE
; bcf MAIN_SCOPE
_send_1w_lp
clrf TEMP1 ;Clear work area
bcf TEMP1, 0 ;Assume sending 0
clrc ;Fill new bits with 0
rrf OneWireByte, F ;Load CARRY with bit to send
btfsc STATUS, C ;See what we are sending
bsf TEMP1, 0 ; must be a 1
movfw TEMP1 ;Load up the bit and
call Sendbit_1wire ; send it out
decfsz TEMP0, F ;Is it 8 bits yet
goto _send_1w_lp ; not yet
return
Sendbit_1wire
movwf TEMP1
bcf ONE_WIRE ;Pull it low
btfsc TEMP1, 0
bsf ONE_WIRE ;end of low pulse if bit was a 1
Wait 58 Microsecs,0 ; (Tslot + Trec) - Tlow1
bsf ONE_WIRE ;end of low pulse if 0 (1 no change)
Wait 1 Microsecs,4 ; Trec
return
;---------------------------------------------------------------------
;Receive bytes and bits from the one wire bus
; BYTE -- Read a byte from the one wire and stick into OneWireByte
; bit -- Read a bit sticking it into bits, 1
;---------------------------------------------------------------------
Readbyte_1wire
movlw d'8'
movwf TEMP0
_read_1w_lp
call Readbit_1wire
movwf TEMP1 ;Save the bit read
clrc ;Assume bit is 0
btfsc TEMP1, 0 ;Check bit
setc ; its a 1
rrf OneWireByte, F ;Rotate bit into IO area
decfsz TEMP0, F ;Is it 8 bits yet
goto _read_1w_lp ; not yet
movfw OneWireByte ; yes, return with byte read in W
return ;
Readbit_1wire
bcf ONE_WIRE ;Pull it low and
nop
bsf ONE_WIRE ; release for a clock pulse
clrf TEMP1 ;Assume incomming bit is 0
Wait 12 Microsecs, 0 ;Give device time to respond
btfsc ONE_WIRE ;What are we receiving?
bsf TEMP1, 0 ; must be a 1
Wait 47 Microsecs, 0 ;Wait out the rest of the cycle
movfw TEMP1
return
;---------------------------------------------------------------------
;Block_Move -- Move 8 Bytes from SOURCE to DEST
; Entry:
; SOURCE should be pointing at place to move from
; DEST should be pointing at destination place to store block
; Exit:
; SOURCE ,DEST, TEMP0, TEMP1, FSR will be destroyed. However,
; the data will be moved ;-D
;---------------------------------------------------------------------
Block_Move
movlw d'8'
movwf TEMP0
_move_lp
movfw SOURCE ;Set up source pointer
movwf FSR
movfw INDF ;get the byte
movwf TEMP1 ; and save it
movfw DEST ;Set up destination pointer
movwf FSR
movfw TEMP1 ;pick up saved byte
movwf INDF ; and store it (now it is moved to destination)
incf SOURCE, F ;adjust pointers
incf DEST, F
decfsz TEMP0, F
goto _move_lp
return
;---------------------------------------------------------------------------------------------
;
; LCD_Print - Print a character to the LCD w/proper scrolling and wrapping
; Code is setup for a 4 * 20 LCD Display
;
;---------------------------------------------------------------------------------------------
LCD_Print
movwf TEMPX
incf CursorCol, F ;Bump the cursor
movfw CursorCol ;Load it
xorlw 0x14 ;Is it running off the right side of the screen
btfss STATUS, Z
goto noscroll ;No, go on and print it
; bsf MAIN_SCOPE
call scroll_scr ;Yes, scroll the display
clrf CursorCol ;Set cursor to beginning of line
; bcf MAIN_SCOPE
noscroll
movlw HIGH lookup_row
movwf PCLATH
movfw CursorRow ;Get current row into W
call lookup_row ;Convert to start address of row
addwf CursorCol, W ;Add in the column position
movwf AbsAddr ;Store absolute address
iorlw b'10000000' ; convert ABS Address to lcd command to set DDRAM address
call LCD_Cmd ;Set DDRAM address
movfw TEMPX ;Load the character received and
goto LCD_Txt ; display it
;---------------------------------------------------------------------------------------------
;
; scroll_scr - Scroll Screen by moving data up a line at a time and then
; filling the bottom row with blanks.
;
;---------------------------------------------------------------------------------------------
scroll_scr
movlw 0x03 ; Move three rows total 1->0, 2->1, 3->2
movwf RowLoopCtr ;
clrf DestRowNum ; Destination starts at row 0
movlw 0x01 ; Source row starts at row 1
movwf SrcRowNum
move_row
movlw HIGH lookup_row
movwf PCLATH
movf DestRowNum, W ; Get destination row number and
call lookup_row ; convert to a char address
movwf DestCharAddr ; and save it
movlw HIGH lookup_row
movwf PCLATH
movf SrcRowNum, W ; Get source row number and
call lookup_row ; convert to a char address
movwf SrcCharAddr ; and save it
movlw 0x14 ; twenty chars per line
movwf CharLoopCtr
move_chars
; read the source character
movf SrcCharAddr, W ; Load DDRAM address into W
; call LCD_ReadRam ; Fetch the character stored there
iorlw b'10000000' ;Turn on the high bit (Set DDRAM Address)
call LCD_Cmd ;Write the command to set the address
call LCD_In ;Read the DDRAM value at current position
movwf LCD_Data ; and save it
;if bottom row move a space to it while we are here
movf SrcRowNum,W ; See which row we are on
xorlw 0x03 ; Is it the bottom one
btfss STATUS, Z
goto wrtdest ; No, just write the destination location
;have to reposition the cursor since it insists on moving itself after a read
movf SrcCharAddr, W ; Load DDRAM address into W
iorlw b'10000000' ; make into a command to set address
call LCD_Cmd ; issue the command
movlw ' ' ; Load up a space character
call LCD_Txt ; and clear the character in the bottom row
;write to destination address
wrtdest
movf DestCharAddr, W ; Load Destination DDRAM address
iorlw b'10000000' ; make into a command to set address
call LCD_Cmd ; issue the command
movf LCD_Data, W ; Get the saved character
call LCD_Txt ; Write character to destination address
incf SrcCharAddr, F
incf DestCharAddr, F
decfsz CharLoopCtr, F
goto move_chars
row_done
incf DestRowNum, F ; Point to next row
incf SrcRowNum, F ; Same thing
decfsz RowLoopCtr, F ; Decrement loop counter and
goto move_row ; move next row
return
;---------------------------------------------------------------------------------------------
;
; LCD_ReadRam - Return character stored at LCD DDRAM Location
;
;---------------------------------------------------------------------------------------------
LCD_ReadRam
; movwf TEMP3 ;Save the address
iorlw b'10000000' ;Turn on the high bit (Set DDRAM Address)
call LCD_Cmd ;Write the command to set the address
call LCD_In ;Read the DDRAM value at current position
return
;---------------------------------------------------------------------------------------------
; LCD_Txt - Write ASCII byte in W to LCD
;
;---------------------------------------------------------------------------------------------
LCD_Txt
movwf TEMP1 ;Store w for LCD_Out
call LCD_BF ;Get the busy flag
andlw b'10000000'
btfss STATUS, Z ;Is busy flag set?
goto $ - 3 ; yes. Re-test busy flag.
bsf LCD_RS ;This is DATA.
goto LCD_Out ;Execute part of LCD_Cmd
;---------------------------------------------------------------------------------------------
; LCD_Cmd ROM: 12 words RAM: TEMP0, TEMP1
;---------------------------------------------------------------------------------------------
LCD_Cmd
movwf TEMP1 ;Store w
call LCD_BF ;Get the busy flag
andlw b'10000000'
btfss STATUS, Z ;Is busy flag set?
goto $ - 3 ; Yes. Re-test busy flag.
bcf LCD_RS ;This is a COMMAND.
LCD_Out bcf LCD_RW ;This is a WRITE.
movf TEMP1, w ;Restore w.
call LCD_Nbl ;Output the upper four bits of W.
swapf TEMP1, w ;Swap nybbles (and put result in W).
call LCD_Nbl ;Output the lower four bits of W.
return ;Done--Return.
;----------------------------------------------------------------------------------------------
;
; LCD_In - Return byte stored in CGRAM at currently addressed location (cursor position)
;
;----------------------------------------------------------------------------------------------
LCD_In
call LCD_BF ;Get the busy flag
andlw b'10000000'
btfss STATUS, Z ;Is busy flag set?
goto LCD_In ; Yes. Re-test busy flag.
bsf LCD_RS ;This is DATA operation.
bsf LCD_RW ;This is a READ.
bsf STATUS, RP0 ;Select Bank 1.
bsf TRISB & 0x07F, 4 ;Make ports input
bsf TRISB & 0x07F, 5
bsf TRISB & 0x07F, 6
bsf TRISB & 0x07F, 7
bcf STATUS, RP0 ;Bank 0 please
bsf LCD_EN ;Clock out the RS and RW bits.
movf LCD_PORT, w ;Get,
andlw b'11110000' ; mask, and
movwf TEMP0 ; store the upper nybble into a temp area
bcf LCD_EN ;Clock in the upper nybble
bsf LCD_EN ;Clock in the lower nybble
movf LCD_PORT, w ;Get and
andlw b'11110000' ; mask the lower nybble
bcf LCD_EN
swapf TEMP0, f ;Flip the temp area around backwards and
iorwf TEMP0, f ; OR in the lower nybble to the upper half of temp
swapf TEMP0, w ;Repair and load the byte into w.
return ;Done -- return.
;---------------------------------------------------------------------------------------------
;
; LCD_Hex - Take byte in W and LCD_Print it in HEX
;
;---------------------------------------------------------------------------------------------
LCD_Hex
movwf TEMP2 ;Store w
swapf TEMP2, w ;Get upper nybble of w
andlw b'00001111'
call LCD_Hex1 ;Convert upper nybble to ASCII
call LCD_Print ;Output ASCII on LCD display
movf TEMP2, w ;Get lower nybble of w
andlw b'00001111'
call LCD_Hex1 ;Conver lower nybble to ASCII
call LCD_Print ;Output ASCII on LCD display
return ;Done--return.
LCD_Hex1
addlw 0xF6 ;This routine converts a number in w to an
btfsc STATUS, C ;ASCII hex number. Result in w.
addlw 0x07
addlw 0x3A
return
;---------------------------------------------------------------------------------------------
;
; LCD_Nbl - Writes one nibble contained in upper half of W to LCD
;
;---------------------------------------------------------------------------------------------
LCD_Nbl
bsf STATUS, RP0 ;Make LCD_PORT.4-7 Outputs
bcf TRISB & 0x07F, 4
bcf TRISB & 0x07F, 5
bcf TRISB & 0x07F, 6
bcf TRISB & 0x07F, 7
bcf STATUS, RP0
bcf LCD_RW ;This is a WRITE command.
bsf LCD_EN ;Clock out RS and RW.
iorlw b'00001111' ;Write the upper four bits in W to the upper
andwf LCD_PORT, f ; four bits in LCD_PORT.
andlw b'11110000'
iorwf LCD_PORT, f
bcf LCD_EN ;Clock out the four data bits.
return ;Done--Return.
;---------------------------------------------------------------------------------------------
;
; LCD_BF - Do a busy flag read of the LCD returning in W': BF A6 A5 A4 A3 A2 A1 A0
;
;---------------------------------------------------------------------------------------------
LCD_BF
bcf LCD_RS ;This is a DATA operation.
bsf LCD_RW ;This is a READ command.
bsf STATUS, RP0 ;Select Bank 1.
bsf TRISB & 0x07F, 4 ;Make ports input
bsf TRISB & 0x07F, 5
bsf TRISB & 0x07F, 6
bsf TRISB & 0x07F, 7
bcf STATUS, RP0
bsf LCD_EN ;Clock out the RS and RW bits.
movf LCD_PORT, w ;Get,
andlw b'11110000' ; mask, and
movwf TEMP0 ; store the upper nybble into a temp area
bcf LCD_EN ;Bring enable pin low after getting data
bsf LCD_EN ;Clock in the lower nybble
movf LCD_PORT, w ;Get and
andlw b'11110000' ; mask the lower nybble
bcf LCD_EN
swapf TEMP0, f ;Flip the temp area around backwards and
iorwf TEMP0, f ; OR in the lower nybble to the upper half of temp
swapf TEMP0, w ;Repair and load the byte into w.
return ;Done -- return.
;---------------------------------------------------------------------------------------------
;
; LCD_Init - That pretty much says it all
;
;---------------------------------------------------------------------------------------------
LCD_Init
bcf LCD_RS ;The following will write to the HD44780's IR.
Wait 10 Millisecs, 0
;
;Grab display per recommended way by setting to eight bit mode 3 times
;
movlw b'00111000' ;Function set
call LCD_Nbl
Wait 50 Microsecs, 0 ;Wait 50us
movlw b'00111000' ;Function set
call LCD_Nbl
Wait 50 Microsecs, 0 ;Wait 50us
movlw b'00111000' ;Function set
call LCD_Nbl
Wait 50 Microsecs, 0 ;Wait 50us
;
;Now that we have its attention, set it to nibble mode and initialize
;
movlw b'00101000' ;Function Set -- 0 0 1 DL N F X X (nibble mode, 2lines, 5x7 font)
call LCD_Cmd
movlw b'00000001' ;Clear Display -- 0 0 0 0 0 0 0 1
call LCD_Cmd
Wait 1650 Microsecs, 0 ;Wait 1.65ms
movlw b'00000110' ;Entry Mode Set -- 0 0 0 0 0 1 ID S (increment, no shifting)
call LCD_Cmd
movlw b'00001100' ;Display Control -- 0 0 0 0 1 D C B (display on, no cursor, no blink)
call LCD_Cmd
return
#include "delay.asm"
end
+
Comments:
| file: /Techref/microchip/ibuttonsearch.htm, 44KB, , updated: 2013/1/11 13:09, local time: 2025/10/27 10:57,
216.73.216.188,10-3-157-36:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://ecomorder.com/techref/microchip/ibuttonsearch.htm"> PIC code to search the iButton bus (untested)</A> |
| Did you find what you needed? |
Welcome to ecomorder.com! |
|
The Backwoods Guide to Computer Lingo |
.