18F External ADC

Developed with the Swordfish compiler

    The MCP3001 is a high speed 10 Bit Analogue to Digital converter. It utilizes an SPI interface, and is very easy to interface with. The output of the MCP3001 is the "hard" part to take into account. Well that and the fact that I have made the following program accurate too 3 decimal places without the use of Floats.

    The output of the MCP3001 Would look something like this;

0011 1110 0100 0010 0111 1100 

The first two bits are blank - its the converting time.
The following 10 Bits is the ADC result, MSB first.
And The next 10 Bits are the ADC result LSB first.
The last two are always 00.

    With that said, lets move on. The hardware SPI could be used, I just wanted to experiment with the Software SPI (SSPI) for this example. There are 3 Bytes of information to receive all up, so I can place that into a couple of buffers to be analysed afterwards. Now the next issue is how to extract the 10 Bit result efficiently.

    To do this, I simply juggle the buffers bytes around a bit

Result.Byte1 = Buffer_1 >> 4
Result.Byte0 = (Buffer_2 >> 4) Or (Buffer_1 << 4)

    The above will put the 10 Bit result into the variable "Result". Now that we know what the 10 Bit result is, its time to calculate what the answer is in volts;

Result = Result * 5000 / 1023

    As I am not using Floats with this example, I'm using a scale of 1000 to ensure I don't "drop" the decimal places from my equation. Another point here is to always multiply before dividing - this will keep you results as accurate as possible. 1023 is the greatest value of a 10 Bit number, and 5 volts is the reference voltage. With that in mind, the math of the equation is fairly straight forward.

    Now to display the answer on the LCD.

LCD.WriteAt(1, 10, DecToStr(Digit(Result,4)),".",DecToStr(Digit(Result,3)))
LCD.WriteAt(1, 13, DecToStr(Digit(Result,2)),DecToStr(Digit(Result,1)))

    The modifier DecToStr turns the numerical values into ASCII codes to be displayed on the LCD. However the Digit command will extract the numerical value for each place in a number. Eg, Digit(123, 3) will return 1 and Digit(123, 1) will return 3. Remembering that the result had a factor of 1000, now I can build the answer, so that it appears to have 3 decimal places.

Note the PIC's power supply/oscillator are not shown

Click here to watch this circuit in action!

 

Device = 18F452
Clock = 20

#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3

#option SSPI_SCK = PORTC.3
#option SSPI_SDI = PORTC.4

Include "system.bas"
Include "SSPI.bas"    
Include "convert.bas"
Include "Utils.bas"       
Include "LCD.bas"

Dim Buffer_1 As Byte   
Dim Buffer_2 As Byte  
Dim Buffer_3 As Byte

Dim Result As LongInt
Dim Last_Result As LongInt
 
Dim CS As PORTC.2   

Sub ADC_Convert()

    CS = 0    
               
    Buffer_1 = SSPI.ReadByte
    Buffer_2 = SSPI.ReadByte
    Buffer_3 = SSPI.ReadByte
   
    Result.Byte1 = Buffer_1 >> 4
    Result.Byte0 = (Buffer_2 >> 4) Or (Buffer_1 << 4)
    
    CS = 1 

End Sub    


// Start Of Program...
SetAllDigital                           ' Make all pins digital

DelayMS(150)                            ' Allow LCD to start up
LCD.Cls                                 ' Clear the screen
TRISD.1 = 0  
SSPI.Initialize                         ' Initialize the software SPI
SSPI.SetClock(spiIdleLow)               ' Set the default clock state

High(CS)                                ' Make CS an output and set it high

LCD.WriteAt(1, 1, "Result = ")          ' This info only needs to be sent once

While True                              ' Create an infinite loop

        ADC_Convert                     ' Get the new ADC sample
        
        Result = Result * 5000 / 1023   ' Change the 10 Bit result to Volts
        
        If Last_Result <> Result Then   ' See if the data has changed
            LCD.WriteAt(1, 10, DecToStr(Digit(Result,4)),".",DecToStr(Digit(Result,3)))
            LCD.WriteAt(1, 13, DecToStr(Digit(Result,2)),DecToStr(Digit(Result,1)))
            Last_Result = Result        ' Display the new info, and update the last result
        EndIf        
               
Wend

Where you can get the components;

 Skip Navigation Links.

Collapse Site Tutorial IndexSite Tutorial Index
Expand 16F PIC Examples16F PIC Examples
Collapse 18F PIC Examples18F PIC Examples
LED's
Switches
Expand 7 Segment Displays7 Segment Displays
LCD's
Expand 7 Segment Displays7 Segment Displays
ADC
ADC (Another Example)
EEPROM's
DS1307
Expand RS232 and UARTRS232 and UART
DS18B20
External ADC
Hall Effect Sensor
Pulse Width Modulation (PWM)
Infrared UART
Swordfish Modules
Expand Code SnippetsCode Snippets
Expand Handy TipsHandy Tips