;************************************* ; Author : Mike Baird ; Program : Using ADC to convert LM35 Voltage into a Temperature in C ; Date : September 7th, 2009 ;************************************* List P=16F88 #include "P16F88.INC" __CONFIG _CONFIG1, _PWRTE_ON & _WDT_OFF & _INTRC_IO & _BODEN_OFF & _LVP_OFF & _CP_OFF & _MCLR_OFF __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF ;*** Cblock *** CBLOCK 0x20 ADCLOW ADCHIGH VoutLo VoutHi Ones ; Tens ; Hund ; Thou ; Thou TenK ; Count1 ; For delay! CountA ; CountB ; CountC ; not used TablePoint TempLCD TablePointer ENDC ;*** Defines *** LCD_PortA EQU PORTA LCD_Port EQU PORTB RS EQU 0x06 E EQU 0x07 ;*** Table Macro *** WriteText Macro Name,Length Local Loop CLRF TablePointer MOVLW Length MOVWF TablePoint Loop: MOVF TablePointer,W Call Name Call LCD_Char INCF TablePointer DECFSZ TablePoint GOTO Loop ENDM ;*** START OF RAM *** ORG 0x000 ; Start of program vector GOTO Start ; ORG 0x004 ; Interrupt vector ;*** ISR *** RETFIE ;*** Table *** Text1: ADDWF PCL dt "Temperature:" Text2: ADDWF PCL dt 0xDF,"C" ;*** Configuration *** Start CLRF PORTA ; PortA all low CLRF PORTB ; PortB all low BSF STATUS,RP0 ; Bank 1 MOVLW b'01100000' ; Make clock 4Mhz IORWF OSCCON MOVLW b'00000001' ; Bit 0 for ADC MOVWF TRISA ; MOVLW b'00000000' ; MOVWF TRISB ; PortB all output MOVLW b'00001001' ; Set RB7,analog input MOVWF ANSEL ; MOVLW b'10000000' ; MSB on the left (Top 6 bits of ADRESH = 0 ) MOVWF ADCON1 ; BCF STATUS,RP0 ; Bank 0 MOVLW b'11000001' MOVWF ADCON0 CALL LCD_Init CALL Delay100 ;*** WriteText Text1,.12 ; "Temperature:" MOVLW 5 Call LCD_Line2W ; " C " WriteText Text2,.2 Main: BSF ADCON0,GO ; Start Conversion BTFSC ADCON0,GO ; Wait for conversion to be complete GOTO $-1 ; BCF PIR1,ADIF Call ADCMOVE Call ToTemp Call Convert Call WriteTemp Call Delay2s GOTO Main WriteTemp: Call LCD_Line2 MOVF TenK,W ; Call LCD_CharD MOVF Thou,W ; Call LCD_CharD MOVLW '.' Call LCD_Char MOVF Hund,W ; Call LCD_CharD RETURN ADCMOVE: MOVF ADRESH,W ; MOVWF ADCHIGH ; BSF STATUS,RP0 ; Bank 1 MOVF ADRESL,W ; BCF STATUS,RP0 ; Bank 0 MOVWF ADCLOW ; RETURN ToTemp: CLRF VoutHi CLRF VoutLo ; x49 = x1 + x 16 + x 32 MOVF ADCLOW,W ; x 1 ADDWF VoutLo MOVF ADCHIGH,W ADDWF VoutHi RLF ADCLOW,F ; add x16 = x5 RLF ADCHIGH,F RLF ADCLOW,F RLF ADCHIGH,F RLF ADCLOW,F ; RLF ADCHIGH,F RLF ADCLOW,F RLF ADCHIGH,F MOVF ADCHIGH,W ADDWF VoutHi MOVF ADCLOW,W ADDWF VoutLo BTFSC STATUS,C INCF VoutHi RLF ADCLOW,F ; add x32 = x49 RLF ADCHIGH,F MOVF ADCHIGH,W ADDWF VoutHi MOVF ADCLOW,W ADDWF VoutLo BTFSC STATUS,C INCF VoutHi RETURN Convert: ; Takes number in NumH:NumL SWAPF VoutHi, w ; Returns decimal in IORLW B'11110000' ; TenK:Thou:Hund:Tens:Ones MOVWF Thou ADDWF Thou,f ADDLW 0XE2 MOVWF Hund ADDLW 0X32 MOVWF Ones MOVF VoutHi,w ANDLW 0X0F ADDWF Hund,f ADDWF Hund,f ADDWF Ones,f ADDLW 0XE9 MOVWF Tens ADDWF Tens,f ADDWF Tens,f SWAPF VoutLo,w ANDLW 0X0F ADDWF Tens,f ADDWF Ones,f RLF Tens,f RLF Ones,f COMF Ones,f RLF Ones,f MOVF VoutLo,w ANDLW 0X0F ADDWF Ones,f RLF Thou,f MOVLW 0X07 MOVWF TenK MOVLW 0X0A ; Ten Lb1: ; At this point, the original number is ADDWF Ones,f ; equal to DECF Tens,f ; TenK*10000+Thou*1000+Hund*100+Tens*10+Ones BTFSS 3,0 ; if those entities are regarded as two's GOTO Lb1 ; complement binary. To be precise, all of Lb2: ; them are negative except TenK. Now the number ADDWF Tens,f ; needs to be normalized, but this can all be DECF Hund,f ; done with simple byte arithmetic. BTFSS 3,0 GOTO Lb2 Lb3: ADDWF Hund,f DECF Thou,f BTFSS 3,0 GOTO Lb3 Lb4: ADDWF Thou,f DECF TenK,f BTFSS 3,0 GOTO Lb4 RETURN ;*** LCD routines *** LCD_Init MOVLW 0x20 ; Set to 4 bit mode CALL LCD_Cmd ; MOVLW 0x28 ; Set display shift to 1 CALL LCD_Cmd ; MOVLW 0x06 ; Set display move right after character sent CALL LCD_Cmd ; MOVLW 0x0C ; Set display on, don't underline cursor but flash it CALL LCD_Cmd ; CALL LCD_Clr ; Clear display RETURN LCD_Cmd MOVWF TempLCD ANDLW 0xF0 ; Clear upper 4 bits of W (Not to interfere with RS,RW and E) MOVWF LCD_Port BCF LCD_PortA,RS ; RS line to 0 BSF LCD_PortA,E ; Pulse the E line high NOP BCF LCD_PortA,E SWAPF TempLCD,W ; Send upper nibble ANDLW 0xF0 ; Clear upper 4 bits of W MOVWF LCD_Port BCF LCD_PortA,RS ; RS line to 0 BSF LCD_PortA,E ; Pulse the E line high NOP BCF LCD_PortA,E CALL Delay5 RETURN LCD_CharD ADDLW 0x30 ; Convert W to ASCII LCD_Char MOVWF TempLCD ; ANDLW 0xF0 ; Clear upper 4 bits of W MOVWF LCD_Port ; BSF LCD_PortA,RS ; RS line to 1 BSF LCD_PortA,E ; Pulse the E line high NOP BCF LCD_PortA,E SWAPF TempLCD,W ; Send upper nibble ANDLW 0xF0 ; Clear upper 4 bits of W MOVWF LCD_Port BSF LCD_PortA,RS ; RS line to 1 BSF LCD_PortA,E ; Pulse the E line high NOP BCF LCD_PortA,E CALL Delay5 RETURN LCD_Line1 MOVLW 0x80 ; Move to 1st row, first column CALL LCD_Cmd RETURN LCD_Line2 MOVLW 0xC0 ; Move to 2nd row, first column CALL LCD_Cmd RETURN LCD_Line1W ADDLW 0x80 ; Move to 1st row, column W CALL LCD_Cmd RETURN LCD_Line2W ADDLW 0xC0 ; Move to 2nd row, column W CALL LCD_Cmd RETURN LCD_Clr MOVLW 0x01 ; Clear display CALL LCD_Cmd RETURN ;*** Delay Routines *** Delay2s MOVLW .8 MOVWF CountC Delay2sLoop Call Delay255 DECFSZ CountC GOTO Delay2sLoop RETURN Delay255 MOVLW d'255' ; Delay 255 mS GOTO d0 Delay100 MOVLW d'100' ; Delay 100mS GOTO d0 Delay50 MOVLW d'50' ; Delay 50mS GOTO d0 Delay20 MOVLW d'20' ; Delay 20mS GOTO d0 Delay5 MOVLW d'5' ; Delay 5.000 ms (4 MHz clock) d0 MOVWF Count1 d1 MOVLW 0xC7 ; Delay 1mS MOVWF CountA MOVLW 0x01 MOVWF CountB Delay_0 DECFSZ CountA,F GOTO $+2 DECFSZ CountB,F GOTO Delay_0 DECFSZ Count1,F GOTO d1 RETURN ;******************** END ; That's all folks!