;**************************************************************************************** ;* PIC16F684 project Date: 15.07.08 * ;* Rev. 22.03.10 * ;* FILE: Two-wire LCD.asm 2x16-Characters Name: GC * ;* * ;* +ADC +BinDec-Converter * ;* * ;* * ;* Uses Two-Wire LCD interface * ;* * ;* ADC-value is displayed as 2 digit decimal (Temperatur:) * ;* * ;**************************************************************************************** ; H'' D'' B'' A'' ; Registers and constants are defined here: INDF equ H'00' ; Indirect Register (Uses content of FSR) PCL equ H'02' ; Program Counter Low byte address STATUS equ H'03' ; Status-register FSR equ H'04' ; Indirect Data Memory Address Pointer PORTA equ H'05' ; Input/output-register A TRISA equ H'05' ; Bank-1, input/output configuration A PORTC equ H'07' ; Input/output-register C TRISC equ H'07' ; Bank-1, input/output configuration C PIR1 equ H'0C' ; EE-prom interuptflag EEIF = PIR1,7 ANSEL equ H'11' ; Bank-1, Analog select register (A/D conversion Clock) CMCON0 equ H'19' ; Comparator control register EEDAT equ H'1A' ; Bank-1, EE-Prom data-register EEADR equ H'1B' ; Bank-1, EE-Prom address-register EECON1 equ H'1C' ; Bank-1, EECON2 equ H'1D' ; Bank-1, ADRESH equ H'1E' ; ADC result ADRESL equ H'1E' ; Bank-1, ADC result ADCON0 equ H'1F' ; ADC Control register ADCON1 equ H'1F' ; Bank-1, ADC Control register ; RAM-registers used by routines: Ux equ H'20' ; Ux? (A/D Converter) Low_ equ H'21' ; Low_? High_ equ H'22' ; High_? Dly_1 equ H'23' ; Delay Dly_2 equ H'24' ; Delay2 Tmp_1 equ H'25' ; Wr_Ch, Wr_Cmd, TxtOut, Dis_Pos Tmp_2 equ H'26' ; Wr_Ch, Wr_Cmd, D_Tx Tmp_3 equ H'27' ; D_Tx, Clr_Buf (Number of Buffer-bits) Deg_Ref equ H'28' ; Deg_C (Offset to subtract from ADC-value) Nr equ H'29' ; BinDec x100 equ H'2A' ; BinDec x10 equ H'2B' ; BinDec x1 equ H'2C' ; BinDec Txt_Loc equ H'2F' ; Txt_Out (Start location of Text) Set by Txt_#1 and Txt_#2 ; Definitions used: #define Max_ D'121' ; Maximum for Temperature-display #define Min_ D'20' ; Minimum for Temperature-display #define D_D PORTA,4 ; RA4: Data-input for Two-wire LCD-interface #define D_C PORTA,5 ; RA5: Clock-input for Two-wire LCD-interfacs list p=16F684 org H'05' ; Start location of code (05) ;*************************************** Chip setup *************************************** ;Bank-1 bsf STATUS,5 ; Switch to bank-1 for setup ;PORTA movlw B'11001111' ; RA0 is ADC-input movwf TRISA ; RA5 and RA4 are digital outputs ; RA2 and RA1 are digital inputs (Tristate) ;PORTC clrf TRISC ; PORTC= Outputs (TRISC<5:0>= 000000) ; Bit5=RS, Bit4=Strobe, Bit<3:0>=Data (Nibble) ;ADC-In movlw B'00000001' ; RA0: ADC-Input, All other pins = digital I/O movwf ANSEL ; movlw B'00010000' ; Bit<6:4> A/D Clock=Fosc/8 movwf ADCON1 ; ;Bank-0 bcf STATUS,5 ; Switch back to bank-0 ;Comperators off movlw H'07' ; CM<2:0>=111 => !!! IMPORTANT !!! movwf CMCON0 ; Disable comparator, General purpose I/O ;ADC-Out movlw B'00000000' ; Bit7=0: 0-------, Makes A/D Result Left justified (8 Bits used) ; Bit6=0: -0------, Vref for A/D =VDD movwf ADCON0 ; Bit<4:2> ---000--, Channel 0 selected: RA0/AN0= ADC-input ; Bit1: ------1-, A/D start and Busy test bit ; Bit0=1: -------1, Turns on A/D Converter ;Ref. movlw D'25' ; Low_ : Temperature Low limit movwf Low_ ; movlw D'27' ; High_ : Temperature High limit movwf High_ ; movlw D'21' ; Set Reference temperature (Used by Deg_C) movwf Deg_Ref ; Offset-value clrf PORTA ; PORTA Outputs are cleared clrf PORTC ; PORTC Outputs are cleared goto Start ;************************************ Subroutines *********************************** ; NB! Text can also be written in EEPROM-Buffer using the ASCII-Field (View -> EEPROM -> ) ; and can be programed here directly. ; Characters used by Txt-Routines are loaded into EE-prom EE_Ld bsf STATUS,5 ; Switch to Bank-1 bsf EECON1,2 ; Write enable of EE-Prom movlw H'00' ; Startaddress In EE-Prom movwf EEADR Txt_1 movlw A'T' ; ASCII-Code ! Display-Characters are loaded into EE-Prom. call EE_In movlw A'w' ; call EE_In movlw A'o' ; call EE_In movlw A'-' ; call EE_In movlw A'W' ; call EE_In movlw A'i' ; call EE_In movlw A'r' ; call EE_In movlw A'e' ; call EE_In movlw A' ' ; call EE_In movlw A'L' ; call EE_In movlw A'C' ; call EE_In movlw A'D' ; call EE_In movlw A'*' ; * <- Star: ends read-out (Se: Txt_Out) call EE_In movlw A' ' ; call EE_In movlw A' ' ; call EE_In movlw A' ' ; call EE_In movlw A' ' ; call EE_In Txt_2 movlw A'T' call EE_In movlw A'e' call EE_In movlw A'm' call EE_In movlw A'p' call EE_In movlw A'e' call EE_In movlw A'r' call EE_In movlw A'a' call EE_In movlw A't' call EE_In movlw A'u' call EE_In movlw A'r' call EE_In movlw A':' call EE_In movlw A'*' call EE_In bcf EECON1,2 ; Disable EE-Write bcf STATUS,5 ; Switch back to Bank-0 return EE_In movwf EEDAT ; Character in W-register is stored EEDAT-register movlw H'55' ; Unlock write EE-Prom sequense movwf EECON2 ; - movlw H'AA' ; - movwf EECON2 ; - bsf EECON1,1 ; Start the write bcf STATUS,5 ; Switch to Bank-0 where PIR1 is WR_Lp btfss PIR1,7 ; Wait here until Write is complete goto WR_Lp bcf PIR1,7 ; Clear EEIF (Bit7: Write EE-Prom interuptflag) bsf STATUS,5 ; Switch back to Bank-1 incf EEADR,f ; Point to next character return ;WWWWWWWWWWWWWWWW Routines for writing and controling the Two-wire display WWWWWWWWWWWWWW ; Short delays used by: Delay2, Ux?, Strobe, Various Display-routines Delay movwf Dly_1 ; Store W in Dly_1 (23H) lp_d decfsz Dly_1,f ; goto lp_d ; return ; Long delays used by: Various Display-routines Delay2 movwf Dly_2 ; Store W in Dly_2 (24H) movlw H'00' lp_d2 call Delay ; Dly_2 * 772uS decfsz Dly_2,f goto lp_d2 return ; Writes a command to the Display-unit Wr_Cmd movwf Tmp_1 ; Save a copy swapf Tmp_1,w ; High nibble first andlw H'0F' ; Preparation of Enable-bit addlw H'20' ; Command-mode (RS=0) movwf Tmp_2 ; Modified copy to Working registe call D_Tx ; Send first part Wr_Cmd2 movf Tmp_1,w ; Get data for second part andlw H'0F' ; Preparation of Enable-bit addlw H'20' ; Command-mode (RS=0) movwf Tmp_2 ; Modified copy to Working register call D_Tx ; Send second part movlw H'05' ; Wait (50 uS) call Delay return ; Writes a character to the Display-unit Wr_Ch movwf Tmp_1 ; Save a copy swapf Tmp_1,w ; High nibble first andlw H'0F' ; Preparation of Enable-bit addlw H'30' ; Charactermode (RS=1) movwf Tmp_2 ; Modified copy to Working registe call D_Tx ; Send first part movf Tmp_1,w ; Get data for second part andlw H'0F' ; Preparation of Enable-bit addlw H'30' ; Charactermode (RS=1) movwf Tmp_2 ; Modified copy to Working register call D_Tx ; Send second part movlw H'05' ; Wait (50 uS) call Delay return ; Loads prepared data (6 bits) into serial-interface display-buffer, used by: Wr_Ch D_Tx call Clr_Buf ; Clear the Display-buffer movlw H'06' ; Number of buffered bits movwf Tmp_3 ; H_L_? btfsc Tmp_2,5 ; IF: Most significant bit is not low goto D_H ; THEN: Go to D_H D_L bcf D_D ; ELSE: Set display data-line Low goto D_X ; Go - transmit current bit D_H bsf D_D ; Set display data-line High D_X call D_Ck ; Clock data into display-buffer rlf Tmp_2,f ; Rotate left for next bit decfsz Tmp_3,f ; All done ? goto H_L_? ; Get status of next bit bcf D_D ; Set display data-line low call D_Ck ; Clock Data one more step forward E_P bsf D_D ; Pulse E-line to transfer data to display-unit (målt: 15us) movlw H'03' call Delay bcf D_D return ; Generates a clock-pulse to Two-wire LCD. Used by: D_Tx D_Ck bcf D_C ; Set Display_Clock-line low movlw H'03' ; call Delay ; Wait (x9 uS) bsf D_C ; Set Display_Clock-line high movlw H'06' ; Wait (x9 uS) call Delay bcf D_C ; Set Display_Clock-line low movlw H'03' ; Wait (x9 uS) call Delay return ; Clears buffer for Two-wire LCD Clr_Buf bcf D_D ; Set Display Data-line low, movlw H'08' ; All 8 bits are cleared movwf Tmp_3 CB_lp call D_Ck decfsz Tmp_3,f goto CB_lp return ;IIIIIIIIIIIIIIIIIIIIII Routines for initialising and Display set-up IIIIIIIIIIIIIIIIIIII ; Setup-routine for Display-unit. Dis_Ini call Clr_Buf ; Clear display-buffer movlw H'43' ; Delay after power on (50mS) call Delay2 ; Display "wakes up" movlw B'0010' ; 4-bit mode 0,0,1,DL movwf Tmp_1 call Wr_Cmd2 ; NB! Only the first 4 bits is needed to select 4-bit mode movlw H'06' ; Wait (4,6mS) call Delay2 Fnc_Set movlw B'00101000' ; Switch display to 4-bit mode, 2 display-lines in use call Wr_Cmd ; 4-bit mode 0,0,1,DL N,F,-,- movlw H'10' ; Wait (50uS) call Delay Disp_On movlw B'00001100' ; Turning ON the Display 1,D,C,B, (1=ON, 0=OFF) call Wr_Cmd ; D: Display ON, C: Cursor OFF, B: Blink OFF movlw H'10' ; Wait (50uS) call Delay Ent_Mod movlw B'00000110' ; Entry mode call Wr_Cmd ; 0,1,I/D,S I/D: Increment/Decrement, S: Shift display movlw H'10' ; Wait (50 uS) call Delay return Dis_Off movlw B'00001000' ; Blanks Display! RS=0 & Data=0 1,D,C,B, (1=ON, 0=OFF) call Wr_Cmd ; D: Display OFF, C: Cursor OFF, B: Blink OFF movlw H'10' ; Wait (50uS) call Delay return Dis_Clr movlw B'00000001' ; Display is cleared, cursor home at start (00) call Wr_Cmd ; RS=0 & Data=0 movlw H'06' ; Wait (4,6mS) call Delay2 return Cur_Hom movlw B'00000010' ; Cursor home at start (00), text remains on display call Wr_Cmd ; RS=0 & Data=0 movlw H'06' ; Wait (4,6mS) call Delay2 return ;wwwwwwwwwwwwwwwwwwwwwwwwwwwwww Text-handeling routines wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ; Value in W holds cursor position for text start on display-unit Dis_Pos addlw H'80' ; W holds the position. Command-mode (Bit7 must be set) movwf Tmp_1 ; Save a copy in Tmp_1 call Wr_Cmd return ; Writes text-string i EE-Prom to Display-unit. Trailing * ends read-out. Txt_Out movf Txt_Loc,w ; Get text location address in EE-Prom bsf STATUS,5 ; Switch to Bank-1 to read EEPROM-data movwf EEADR ; Next_C bsf EECON1,0 ; Initiate Reading of a character in EE-Prom movf EEDAT,w ; Get the character sublw A'*' ; Test for last character = * btfsc STATUS,2 ; IF: Character = * (Z=1) goto Txt_End ; THEN: End read-out movf EEDAT,w ; Get EE-Data for display bcf STATUS,5 ; Bank-0 call Wr_Ch ; ELSE: Write Character to Display-unit bsf STATUS,5 ; Bank-1 incf EEADR,f ; Move pointer to next character goto Next_C ; Continue Txt_End bcf STATUS,5 ; Bank-0 return Txt_#1 movlw H'00' ; Text_1 start-position on display call Dis_Pos movlw H'00' ; Address in EE-Prom where Text_1 is Located movwf Txt_Loc call Txt_Out return Txt_#2 movlw H'40' ; Text_2 start-position on display call Dis_Pos movlw H'11' ; Address in EE-Prom where Text_2 is Located movwf Txt_Loc call Txt_Out return ;ddddddddddddddddddddddddddddddd Data-handeling routines dddddddddddddddddddddddddddddddd ; Reads ADC-value Ux? bsf ADCON0,0 ; Turn on A/D Converter movlw D'4' ; W contains delay-value for Dly_1 (23h) call Delay ; Delay bsf ADCON0,1 ; GO, Start A/D conversion Ux_lp btfsc ADCON0,1 ; Done ? (Bit1: A/D Start and Busy test-bit) goto Ux_lp ; No, try again movf ADRESH,w ; Yes, movwf Ux ; Store result in Ux bcf ADCON0,0 ; Turn off A/D Converter return ; Go back to Main program DisTemp ; Checks if Ux is below Min_ value Dis_L movf Ux,w ; Get Ux to W sublw Min_ ; Subtract Ux from Min_ (Min_ = D'21') btfss STATUS,0 ; IF: Ux < Min_ w C-bit=1 goto Dis_H ; THEN: Check if high limit is exeded goto Dis_E ; ELSE: Display -- for error ; Checks if Ux exceeds Max_ value Dis_H movlw Max_ ; Get Max_ to W subwf Ux,w ; Subtract Max_ from Ux (Max_ = D'121') btfss STATUS,0 ; IF: Ux > Max_ w C-bit=1 goto Dis_Tp ; THEN: Go display the temperature goto Dis_E ; ELSE: Display -- for error ; Displays temperature as 2 Decimal characters Dis_Tp call Deg_C ; Deg_C converts 8-bits to a 3-digit Decimal number. movlw H'4C' ; -> Position 4C (At the end of Display-line 2) call Dis_Pos ; movf x10,w call Wr_Ch movf x1,w call Wr_Ch movlw H'DF' ; DF= Degree character in ASCII table call Wr_Ch movlw A'C' ; C: for Celcius call Wr_Ch return Dis_E movlw H'4C' ; Displays -- , meaning ouside range from Min_ to Max_ call Dis_Pos ; -> Position 4C (End of Display-line 2) movlw A'-' call Wr_Ch movlw A'-' call Wr_Ch movlw H'DF' ; DF= Degree character call Wr_Ch movlw A'C' ; C: for Celcius call Wr_Ch return ; This routine calculates a binary value for temperature and convert it to decimal. Deg_C Call Ux? movf Deg_Ref,w ; Get Reference temperature (Deg_Ref=Offset-value) subwf Ux,w ; Subtract Deg_Ref from w Nr_Out movwf Nr call BinDec ; Convert it to decimal. return ; Converts one byte to a 3-digit Decimal number. BinDec clrf x100 ; Reset Registers. clrf x10 ; The value to convert must be in register: Nr clrf x1 ; Dig_3 movlw D'100' ; subwf Nr,w ; Subtract 100 from Nr btfss STATUS,0 ; goto Dig_2 ; movwf Nr ; Remainder in w to Nr W -> Nr incf x100,f ; Number of hundred's goto Dig_3 ; Dig_2 movlw D'10' ; subwf Nr,w ; Subtract 10 from Nr btfss STATUS,0 ; goto Dig_1 ; movwf Nr ; Remainder in w to Nr W -> Nr incf x10,f ; Number of ten's goto Dig_2 ; Dig_1 movf Nr,w ; movwf x1 ; Remainder goes in register: x1 Prep_N movf x100,w ; Preparing characters for display andlw H'0F' ; (Numbers starting with 3 Eks: D'5' => H'35') iorlw H'30' ; movwf x100 ; movf x10,w ; andlw H'0F' ; And w with 00001111 H'0F' iorlw H'30' ; Or w with 00110000 H'30' movwf x10 ; To make it a Number H'3X' movf x1,w ; andlw H'0F' ; iorlw H'30' ; movwf x1 ; return ;************************************* Main program ************************************* Start ; Make shure Text is in EE-Prom !!! call EE_Ld ; Writes text to EE-Prom ; Text can also be written in the ASCII field - ; in the EE-Prom window prior to programming. call Dis_Ini ; Display-unit setup call Txt_#1 ; Write Text_1 call Txt_#2 ; Write Text_2 New call Ux? ; Read ADC! call DisTemp ; Displays temperature goto New ; New measurement end ; Program ends here ;*********************************** Programming a Device ******************************* ; Select: ; ; 1.Configure Select Device... 16f684 ; 2.Configure Configuration Bits Clock: Internal-RC,- ; No Clock ; ; WatchDogTimer: Off ; Master Clear Enable: Internal ; Internal External Switch Over Mode: Disabled ; Monitor Clock Fail-safe: Disabled ; ; 3.Project Quickbuild *.asm ; 4.Programmer Select Programmer (PICkit 2) ; 5.Programmer Program Device (Or Yellow Icon) ; Temperature sensor: 10k NTC in series vith 10k trim (temp. adjust).