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 12:09, local time: 2024/11/17 06:15,
18.119.106.211:LOG IN
|
©2024 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://massmind.org/techref/microchip/ibuttonsearch.htm"> PIC code to search the iButton bus (untested)</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! |
.