Swordfish Program - MCP3001 (External ADC)

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.


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

Forum Activity

  • No posts to display.

Member Access