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;

 | Site Tutorial Index |
|  | 16F PIC Examples |
|  | 18F PIC Examples |
| |  | 7 Segment Displays |
| |  | 7 Segment Displays |
| |  | RS232 and UART |
| |  | Code Snippets |
|  | Handy Tips |