; LCD Display Demo.asm ; Include the header file for our target chip #include "p16f676.inc" ; First line, declare that we want a 16F676 PICC ; and that our numbers will be in Hexadecimal ; unless otherwise noted LIST P=16f676, R=HEX ; Tell the programmer what options we want to use ; In this case: ; _WDT_OFF -- Watchdog Timer Off ; _INTRC_OSC_NOCLKOUT -- Internal Oscillator ; _CP_OFF -- Code Protect Off ; _MCLRE_OFF -- disable reset pin, so we can use it for I/O __CONFIG _WDT_OFF & _INTRC_OSC_NOCLKOUT & _CP_OFF & _MCLRE_OFF ; Variable Declarations ; Here we assign memory locations for our variables cblock 0x20 command delay1 delay2 counter1 counter2 out_char endc ; Uses PORTA<4> for RS, PORTA<5> for E, PORTC<4:7> for 4-bit data bus ; consult HD44780 data sheet for more information ; or http://www.myke.com/lcd.htm for details #define RS PORTA, 4 #define E PORTA, 5 #define DATAPORT PORTC sdelay macro ; delays for 3*256 cycles = 153.6us local d0 movlw h'50' movwf delay1 d0: decfsz delay1,f goto d0 endm Estrobe macro bsf E nop nop nop bcf E endm ; First column is always for labels. Anything in the first ; column will be interpreted by the assembler as a label org 0 goto Start Start clrf DATAPORT ; Initialize Data Port clrw ; Clear W register bsf STATUS,RP0 ; Select Register Bank 1 movwf TRISC ; Set C to all outputs movlw b'000001' movwf TRISA ; set A to all outputs movlw b'00000001' movwf ANSEL ; turn on only analog input 0 bcf ADCON1,ADCS2 ; set ADCS<2:0> = 001 -> bcf ADCON1,ADCS1 ; Sample Time 8*Tosc bsf ADCON1,ADCS0 ; from Data Sheet bcf STATUS,RP0 ; select Register Bank 0 movlw b'11100011' ; set A/D input channel 0 andwf ADCON0, f bcf ADCON0, ADFM ; set shift left bcf ADCON0, VCFG ; set reference voltage = Vdd bsf ADCON0, ADON ; turn on A/D converter call ResetDisplay loop bsf ADCON0, GO ; acquire a sample wait_for_sample btfsc ADCON0, NOT_DONE goto wait_for_sample ; call ClearDisplay movlw b'10000000' call SendCommand movlw d'16' movwf counter2 movf ADRESH, W movwf counter1 swapf counter1,f movlw h'0f' andwf counter1,f movf counter1,w subwf counter2,f movf counter1,f ; update zero flag btfsc STATUS,Z goto BarGraph_Done BarGraph_Loop: movlw b'00111010' call DisplayChar decfsz counter1,f goto BarGraph_Loop BarGraph_Done: movf counter2,f ; update zero flag btfsc STATUS,Z goto BarGraph2_Done BarGraph2_Loop: movlw b'00010000' call DisplayChar decfsz counter2,f goto BarGraph2_Loop BarGraph2_Done: ; call HexToASCII ; call DisplayChar ; swapf out_char,f ; movf out_char,w ; andlw h'0f' ; call HexToASCII ; call DisplayChar ; call sdelay goto loop HexToASCII sublw d'9' ; subtract 10 from w btfsc STATUS, C ; if /borrow is clear goto ascii_1 ; n < 10 sublw h'40' ; make A-F return ascii_1 sublw h'39' ; make 0-9 return DisplayChar ; Displays character in w bsf RS call SendCommand bcf RS return ClearDisplay: ; Clear the LCD display ; R/S = 0, R/W = 0, DATA1=b'0000', DATA2=b'0001' bcf RS movlw b'00000001' call SendCommand movlw d'100' call delay return SendCommand: ; sends a one-byte command in w to LCD ; assumes RS already set correctly, E cleared movwf command swapf command,f movf command,w movwf DATAPORT Estrobe swapf command,f movf command,w movwf DATAPORT Estrobe sdelay return ResetDisplay: ; Initializes LCD bcf E bcf RS movlw d'20' ; wait 15.4msec call delay movlw 0x3 ; movwf DATAPORT ; send 0x3 out Estrobe movlw d'6' call delay ; wait 5msec Estrobe ; send another 0x3 out sdelay ; wait ~160us Estrobe ; send another 0x3 out sdelay ; wait ~160us movlw 0x28 ; 4 line interface, 2 line display call SendCommand movlw 0x10 ; turn off display call SendCommand call ClearDisplay movlw 0x06 ; set cursor autoincrement call SendCommand movlw b'00001100' ; turn on display call SendCommand return delay ; delay for 2+770*w cycles ; at 20MHz that's about 0.154msec*w movwf delay1 clrf delay2 d1: decfsz delay2,f goto d1 decfsz delay1,f goto d1 return END ; End of program