;**************************************************************************************** ;* PIC-micro project Date: 07.12.09 * ;* * ;* FILE: Regulator+LCD.asm 2x16-Characters Name: GC * ;* Two-Wire LCD * ;* Device: PIC16F690 Text in RAM * ;* +ADC +BinDec-Converter * ;* * ;* Limits on ADC-value controls Output RC0 * ;* Uses Two-Wire LCD interface (RA4 + RA5) * ;* ADC-value is displayed as 2 digit decimal * ;* * ;**************************************************************************************** ; H'' D'' B'' A'' ; Registers og constants are defined here: INDF equ H'00' ; Indirect Register (Uses content of FSR) 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 PORTB equ H'06' ; Input/output-register B TRISB equ H'06' ; Bank-1, input/output configuration B PORTC equ H'07' ; Input/output-register C TRISC equ H'07' ; Bank-1, input/output configuration C INTCON equ H'0B' ; Interupt Control register (Enable-bits/Flags) PIR2 equ H'0D' ; Bank-0, EE-prom interuptflag EEIF = PIR2,4 EEDAT equ H'0C' ; Bank-2, EE-Prom data-register R/W EEADR equ H'0D' ; Bank-2, EE-Prom address-register EECON1 equ H'0C' ; Bank-3, EE-Prom Control register EECON2 equ H'0D' ; Bank-3, CM1CON0 equ H'19' ; Bank-2, Comparator control register CM2CON0 equ H'1A' ; Bank-2, Comparator control register CM2CON1 equ H'1B' ; Bank-2, Comparator control register ANSEL equ H'1E' ; Bank-2, Analog input select register ANSELH equ H'1F' ; Bank-2, Analog input select register ADRESH equ H'1E' ; Bank-0, ADC result format ADCON0 equ H'1F' ; Bank-0, ADC Conditions and control ADCON1 equ H'1F' ; Bank-1, ADC Clock control (A/D conversion Clock) ; RAM-registers used by routines: Ux equ H'20' ; Ux? (A/D Converter) Ref_1 equ H'21' ; Low_? Ref_2 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 #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 #define D_C PORTA,5 ; RA5: Clock-input for Two-wire LCD #define Out_1 PORTC,0 ; RC0 #define Out_2 PORTC,1 ; RC1 #define SW1 PORTA,3 ; RA3, Switch input list p=16F690 org H'00' ; Start of code goto Init ; Reset Vector Located at 0x0000 nop ; nop ; nop ; nop ; (ISR Vector Located at 0x0004) ;*************************************** Chip setup *************************************** Init ; PORT Setup: ; Inputs and outputs are selected bsf STATUS,5 ; Bank-1 PORT_A movlw B'11001111' ; RA0 is ADC-input movwf TRISA ; RA5 and RA4 are digital outputs ; RA2 and RA1 are digital inputs (Tristate) PORT_B ; All pins remain inputs - not used PORT_C clrf TRISC ; PORTC= Outputs bcf STATUS,5 ; Bank-0 ; Unused comperators are switched off: bsf STATUS,6 ; Bank-2 clrf CM1CON0 ; Disable comparator 1, !!! IMPORTANT !!! clrf CM2CON0 ; Disable comparator 2, PORTC: General purpos I/O bcf STATUS,6 ; Bank-0 ; ADC Setup: ; Conversion clock: bsf STATUS,5 ; Bank-1 movlw B'00010000' ; Bit<6:4> = 001 => ADC-Clock= Fosc/8 movwf ADCON1 ; bcf STATUS,5 ; Bank-0 ; Analog / Digital input: bsf STATUS,6 ; Bank-2 movlw B'00000001' ; Makes AN0 analog input for ADC and - movwf ANSEL ; ANS<7:1> are digital inputs clrf ANSELH ; Asosiated pins are digital inputs (ANS<11:8>) bcf STATUS,6 ; Bank-0 ; ADC Output, Vref and input channel select 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 Setup: ; movlw D'21' ; Set Reference temperature (Used by Deg_C) movwf Deg_Ref ; Offset-value: 21deg. movlw D'41' ; Ref_1 : Low limit movwf Ref_1 ; ( 20deg.) movlw D'51' ; Ref_2 : High limit movwf Ref_2 ; ( 30deg.) ; Reset PORT's ; Outputs are reset: clrf PORTA ; PORTA Outputs are cleared (LED's off) clrf PORTC ; PORTC Outputs are cleared ;cccccccccccccccccccccccccc Characters used by Txt_#X Routines ccccccccccccccccccccccccc Txt#1 movlw A'R' ; R ASCII-Code ! Display-Characters are loaded into RAM. movwf H'30' ; <= (Text starts at 30h) movlw A'e' ; e movwf H'31' movlw A'g' ; g movwf H'32' movlw A'u' ; u movwf H'33' movlw A'l' ; l movwf 34 movlw A'a' ; a movwf 35 movlw A't' ; t movwf 36 movlw A'o' ; o movwf 37 movlw A'r' ; r movwf 38 movlw A'+' ; + movwf 39 movlw A'L' ; L movwf 3A movlw A'C' ; C movwf 3B movlw A'D' ; D movwf 3C movlw A'*' ; * <- Star: ends read-out (Se: Txt_Out routine) movwf 3D Txt#2 movlw A'T' ; T <= (Text starts at 3Eh) movwf 3E movlw A'e' ; e movwf 3F movlw A'm' ; m movwf 40 movlw A'p' ; p movwf 41 movlw A':' ; : movwf 42 movlw A'*' ; * <- Star: ends read-out (Se: Txt_Out routine) movwf 43 goto start ;*********************************** Subroutines *********************************** ;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 ; Sends prepared data to display-buffer (6 bits), 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 forward one more step 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' ; Position must be in W. Command-mode (Bit7 must be set) movwf Tmp_1 ; Save a copy in Tmp_1 call Wr_Cmd return ; Writes text-string to Display-unit. Trailing * ends read-out. Txt_Out movwf FSR ; Set text-pointer for indirect addressing Next_C movf INDF,w ; Get Character - call Wr_Ch ; Write Character to Display-unit incf FSR,f ; Move pointer to next character movf INDF,w ; Get next character - movwf Tmp_1 ; save a copy sublw A'*' ; Test for last character = * btfss STATUS,2 ; Z=1 ? goto Next_C ; No! Continue return Txt_#1 movlw H'00' ; Text-1 start-position on display call Dis_Pos movlw H'30' ; Address where Txt#1 is Located call Txt_Out return Txt_#2 movlw H'40' ; Text-2 start-position on display call Dis_Pos movlw H'3E' ; Address where Txt#2 is Located call Txt_Out return ;ddddddddddddddddddddddddddddddd Data-handeling routines dddddddddddddddddddddddddddddddd ; 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 ; Write ADC-value as 3 decimal characters to display @ 40h DisADC Call Ux? movf Ux,w ; Save a copy of Ux in Nr movwf Nr call BinDec movlw H'40' ; Writes 3 Decimal digits @ 40h call Dis_Pos ; -> 40h (Start of line 2) movf x100,w call Wr_Ch movf x10,w call Wr_Ch movf x1,w call Wr_Ch return 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 (End of Display-line 2) call Dis_Pos ; movf x10,w call Wr_Ch movf x1,w call Wr_Ch movlw H'DF' ; = HEX-Value for degree character 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 (Near the end of Display-line 2) movlw A'-' call Wr_Ch movlw A'-' call Wr_Ch movlw H'DF' ; = HEX-Value for degree character call Wr_Ch movlw A'C' ; C: for Celcius call Wr_Ch return ; This routine calculates the 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 ;IIIIIIIIIIIIIIIIIIIIIIIIIIIIII Input Outpt & ADC Routines IIIIIIIIIIIIIIIIIIIIIIIIIIII ; 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 (ADC Sample & Hold Setup-time) bsf ADCON0,1 ; GO, Start A/D Conversion loop1 btfsc ADCON0,1 ; Done ? (Bit1: A/D Start and Busy test-bit) goto loop1 ; No, try again (Conversion still in progress) movf ADRESH,w ; Yes, movwf Ux ; Store result in Ux bcf ADCON0,0 ; Turn off A/D Converter return ; Go back to Main program ; Checks if Ux is below Ref_1 value Low_? movf Ux,w ; Get Ux to W subwf Ref_1,w ; Subtract Ux from Ref_1 btfss STATUS,0 ; Ux < Ref_1 ? return ; No, Go back to Main program bcf Out_1 ; Yes, Switch off RC0. return ; Go back to Main program ; Checks if Ux exceeds Ref_2 value High_? movf Ref_2,w ; Get Ref_2 to W subwf Ux,w ; Subtract Ref2 from Ux btfss STATUS,0 ; Ux > Ref_2 ? (C-bit=1) return ; No, Go back to Main program bsf Out_1 ; Yes, Switch on RC0. return ; Go back to Main program Reg_Out call Ux? call Low_? call High_? return Switch btfsc SW1 ; Is SW1= ON? (Input low ?) return ; No, proceed bsf Out_2 ; Yes, turn on DS2 lp_k btfss SW1 ; SW1 still ON? goto lp_k ; Yes, check again! bcf Out_2 ; No, turn off DS2 return ; Proceed ;************************************* Main program ************************************* start call Dis_Ini ; Display-unit setup call Cur_Hom ; Cursor home (00) call Txt_#1 ; Write Text_1 call Txt_#2 ; Write Text_2 New call Reg_Out ; Read ADC and set Output accordingly call DisTemp ; Displays temperature call Switch ; Is SW1 activated ? goto New ; New measurement end ; Program ends here ;*********************************** Programming a Device ******************************* ; Select: ; ; 1.Configure Select Device... 16f690 ; 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) ;******************************** Display Connections: **************************** ; Colour Pin Nr. Function ; BK 1 - ; BN 2 + ; RD 3 Contrast ; OR 4 RS ; YE 5 R/W (GND=>W) ; GN 6 E ; BL 7 D4 ; PU 8 D5 ; GR 9 D6 ; HW 10 D7 ; Temperature sensor: 10k NTC in series vith 10k trim (temp. adjust).