;**************************************************************************************** ;* PIC microproject Date: 10.11.07 * ;* * ;* FILE: Display-5 2x16-Characters Navn: GC * ;* * ;* Device: PIC16F684 Indirect Addressing * ;* +ADC +Knap +BinDec-Converter * ;* * ;* Limits on ADC-value controls LED D0 * ;* SW1 clears display and controls LED D1 * ;* ADC-value is displayed as ASCII-character and 3 digit decimal (BinDec) * ;* * ;**************************************************************************************** ; 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 CMCON0 equ H'19' ; Comparator control register ANSEL equ H'11' ; Bank-1, Analog select register (ADC conversion Clock) ADRESH equ H'1E' ; ADC result-high register ADRESL equ H'1E' ; Bank-1, ADC result-low register 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? (ADConverter) 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' ; Vr_Char, TxtOut, Dis_Pos Tmp_2 equ H'26' ; Tmp_3 equ H'27' ; Tmp_4 equ H'28' ; Nr equ H'29' ; BinDec x100 equ H'2A' ; BinDec, DisADC x10 equ H'2B' ; BinDec, DisADC x1 equ H'2C' ; BinDec, DisADC Text_1 equ H'30' ; Startlocation of Txt#1 list p=16F684 org H'05' ; Start of program (05) ;*************************************** Chip setup ************************************* Bank_1 bsf STATUS,5 ; Switch to Bank-1 for setup 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_C clrf TRISC ; PORTC= Outputs (TRISC<5:0>= 000000) ; Bit5=RS, Bit4=Strobe, Bit<3:0>=Data (Nibble) movlw B'00000001' ; RA0: ADC-Input, All other pins = digital I/O movwf ANSEL ; movlw B'00010000' ; Bit<6:4> ADC Clock=Fosc/8 movwf ADCON1 Bank_0 bcf STATUS,5 ; Switch back to Bank-0 ADC movlw H'07' ; CM<2:0>=111 => !!! IMPORTANT !!! movwf CMCON0 ; Disable comparator, General purpose I/O movlw B'00000000' ; Bit7=0: 0-------, Makes ADC Result Left justified (8 Bits used) ; Bit6=0: -0------, Vref for ADC =VDD movwf ADCON0 ; Bit<4:2> ---000--, Channel 0 selected: RA0/AN0= ADC-input ; Bit1: ------1-, ADC start and Busy test bit ; Bit0=1: -------1, Turns on AD-Converter movlw D'85' ; Ref_1 : Low limit movwf Ref_1 ; (85/255: ca.33%) movlw D'170' ; Ref_2 : High limit movwf Ref_2 ; (170/255: ca.66%) clrf PORTA ; PORTA Outputs are cleared (LED's off) clrf PORTC ; PORTC Outputs are cleared ; Text_1 Characters used by Txt#1 Routine movlw A'H' ; H ASCII-Code ! Display-Characters are loaded into RAM. movwf H'30' ; <= (Text starts at 30h) movlw A'T' ; T movwf H'31' movlw A'X' ; X movwf H'32' movlw A'-' ; - movwf H'33' movlw A'E' ; E movwf H'34' movlw A's' ; s movwf H'35' movlw A'b' ; b movwf H'36' movlw A'j' ; j movwf H'37' movlw A'e' ; e movwf H'38' movlw A'r' ; r movwf H'39' movlw A'g' ; g movwf H'3A' movlw A' ' ; movwf H'3B' movlw A'2' ; 2 movwf H'3C' movlw A'0' ; 0 movwf H'3D' movlw A'0' ; 0 movwf H'3E' movlw A'7' ; 7 movwf H'3F' movlw A'*' ; * Star: ends read-out (Se: Txt#1 subroutine) movwf H'40' goto start ;*********************************** Subroutines ************************************ ; Outputs: LED's are on PICkit-1 USB demo-board Led_0 movlw B'010000' ; Turns on D0 movwf PORTA ; return ; Led_1 movlw B'100000' ; Turns on D1 movwf PORTA ; return ; ; Signaling to Display-unit that Data is ready (4-bit) Strobe1 bsf PORTC,5 ; Set RS=1 for writing Characters to Display-unit Strobe movlw H'01' ; (Set RS=0 for writing commands to Display-unit) call Delay ; Wait (9 uS) bsf PORTC,4 ; Write PORTC-data to display movlw H'01' ; Wait (9 uS) call Delay bcf PORTC,4 movlw H'01' ; Wait (9 uS) call Delay return ; 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 ; decfsz Dly_2,f goto lp_d2 return ; Setup-routine for Display-unit. Dis_Ini movlw H'43' ; Delay after power on (50mS) call Delay2 ; Display "wakes up" bcf PORTC,5 ; RS=0, Command mode movlw B'0010' ; 4-bit mode movwf PORTC call Strobe movlw H'06' ; Wait (4,6mS) call Delay2 Fnc_Set movlw B'0010' ; Switch display to 4-bit mode movwf PORTC call Strobe movlw B'1000' ; 2 display-lines in use movwf PORTC call Strobe movlw H'10' ; Wait (50uS) call Delay Disp_On movlw B'0000' ; Turning ON the Display movwf PORTC call Strobe movlw B'1100' ; 1,D,C,B D: Display ON, C: Cursor OFF, B: Blink OFF, movwf PORTC ; (1=ON, 0=OFF) call Strobe movlw H'10' ; Wait (50uS) call Delay Ent_Mod movlw B'0000' ; Entry mode movwf PORTC call Strobe movlw B'0110' ; 0,1,I/D,S I/D: Increment/Decrement, S: Shift display movwf PORTC ; -> call Strobe movlw H'10' ; Wait (50 uS) call Delay return Dis_Off clrf PORTC ; Blanks Display! RS=0 & Data=0 call Strobe movlw B'1000' ; 1,D,C,B movwf PORTC ; D: Display OFF, C: Cursor OFF, B: Blink OFF, (1=ON, 0=OFF) call Strobe movlw H'10' ; Wait (50uS) call Delay return Dis_Clr clrf PORTC ; Display is cleared, cursor home at start (00) call Strobe ; RS=0 & Data=0 movlw B'0001' ; movwf PORTC call Strobe movlw H'06' ; Wait (4,6mS) call Delay2 return Cur_Hom clrf PORTC ; Cursor home at start (00), text remains on display call Strobe ; RS=0 & Data=0 movlw B'0010' ; movwf PORTC call Strobe movlw H'06' ; Wait (4,6mS) call Delay2 return ; Writes single characters to Display-unit Wr_Char movwf Tmp_1 ; save a copy swapf Tmp_1,w ; Swap high-nibble to low-nibble, movwf PORTC ; Send high-nibble first! call Strobe1 ; Set RS=1 (by using: Strobe1) for writing to display-unit movf Tmp_1,w ; Send low-nibble movwf PORTC call Strobe1 movlw H'10' ; Wait (50 uS) call Delay return ; Writes text-string to Display-unit. Trailing * ends read-out. Txt#1 movlw Text_1 ; Text starting address TxtOut movwf FSR ; Set text-pointer for indirect addressing Next_C movf INDF,w ; Get Character - call Wr_Char ; 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 ; Write ADC-value as ASCII caracter Dis_Ux movlw H'40' ; Set Display-pointer at 40h call Dis_Pos ; -> 40h (Left, on displayline 2) call Ux? call Wr_Char ; Write ADC-value as ASCII character @ 40h ! return ; Displays AD-Converter value in 3 digits Decimal characters DisADC call BinDec ; Converts 8-bits to 3-digit Decimal number for Display. movlw H'4D' ; Writes ADC in 3 digits Decimal characters @ 4Dh call Dis_Pos ; -> 4Dh (Right, on display-line 2) movf x100,w call Wr_Char movf x10,w call Wr_Char movf x1,w call Wr_Char Return ; Value in W holds cursor position for text start on display-unit Dis_Pos movwf Tmp_1 ; Save a copy in Temp_1 swapf Tmp_1,w ; High nibble first ! NB:Bit<3:0>on PORTC =Data Out movwf PORTC ; Bit5=RS, Bit4=Strobe, bcf PORTC,5 ; RS=0 for command mode bsf PORTC,3 ; ADD mode call Strobe ; Transfer data to display-unit movf Tmp_1,w movwf PORTC ; Low nibble next. bcf PORTC,5 ; RS=0 for command mode call Strobe ; Transfer data to display-unit movlw H'10' call Delay ; Wait 50us return ; Reads ADC-value Ux? bsf ADCON0,0 ; Turn on ADC Converter movlw D'4' ; W contains delay-value for Dly_1 (23h) call Delay ; Delay bsf ADCON0,1 ; GO, Start AD-Conversion loop1 btfsc ADCON0,1 ; Done ? (Bit1: ADC Start and Busy test-bit) goto loop1 ; No, try again movf ADRESH,w ; Yes, movwf Ux ; store result in Ux bcf ADCON0,0 ; Turn off AD-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 clrf PORTA ; Yes, Switch off LED D0. 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 call Led_0 ; Yes, Switch on LED D0. return ; Go back to Main program ; Checks if SW1 is pressed on PIC-Kit1 Knap btfsc PORTA,3 ; Is SW1= ON? (Input low) return ; No, proceed in Main program bsf PORTA,5 ; Yes, SW1 is ON, turn on LED D1 call Dis_Clr ; Display is cleared lp_k btfss PORTA,3 ; SW1 still ON? goto lp_k ; Yes, check again! bcf PORTA,5 ; No, SW1 is OFF, turn OFF Led1 call Txt#1 call Dis_Ux return ; Proceed in Main program ; Converts 8-bits to 3-digit Decimal number. BinDec clrf x100 ; Reset Registers. clrf x10 ; clrf x1 ; movf Ux,w ; Get Ux to W movwf Nr ; Save a copy in Nr W -> Nr 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 start with 3 Eks: 5 => H'35') iorlw H'30' ; movwf x100 ; movf x10,w ; andlw H'0F' ; And w with 00001111 iorlw H'30' ; Or w with 00110000 movwf x10 ; movf x1,w ; andlw H'0F' ; iorlw H'30' ; movwf x1 ; return ;************************************* Main program ************************************* start call Dis_Ini ; Display-unit setup call Txt#1 ; Write Text_1 New call Ux? ; Read ADC! call Low_? ; Ux < Ref_1 => LED D0 = OFF call High_? ; Ux > Ref_2 => LED D0 = ON call Knap ; KNAP activated => LED D1 = ON Clears Display call Dis_Ux ; Displays ADC-value as ASCII character call DisADC ; Displays ADC-value as 3 digit decimal number 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 1) ; 5.Programmer Program Device (Or Yellow Icon) ;********************************** Connections: ********************************** ; Colour DISPLAY J3 Pin No. 16F684 PICKit1 ; BK 1 - 14 GND. ; BN 2 + 13 +5_SWITCHED ; RD 3 Contrast - ; OR 4 RS 4 RC5 (Register Select) ; YE 5 R/W - (GND=>W) ; GN 6 E 5 RC4 (Strobe) ; BL 7 D4 10 RC0 (D4) ; PU 8 D5 11 RC1 (D5) ; GR 9 D6 12 RC2 (D6) ; HW 10 D7 6 RC3 (D7)