I've attached a module and test program to control the microchip MCP342x range of ADCs. I've found these are very useful providing very stable readings and as they have an internal programmable gain they can direct read thermocouples.
Hope the code is of some use. Please feel free to let me have any constructive comments as to how the code could be improved
Best Regards
Peter
Module
Code: Select all
Module MCP342x
{
*****************************************************************************
* Name : MCP342x.BAS *
* Author : Peter Mather *
* Notice : Copyright (c) Peter Mather *
* : All Rights Reserved *
* Date : 12/06/2011 *
* Version : 1.0 *
* Notes : *
* : *
*****************************************************************************
}
{
Routines to control a Microchip MCP3421, MCP3422, MCP3424 i2c ADC
All use is in single shot mode and the start conversion routine is non-blocking
reading the value waits on completion by the ADC and is blocking until the conversion is complete
The MCP342x have an internal voltage reference and the results are not related to Vdd
Therefore it is possible to also return absolute signed voltage measurements
The MCP342x work perfectly for direct thermocouple measurement with gain set to 8 and 16 or 18 bit resolution
}
Include "I2C.bas"
Include "usart.bas"
Include "convert.bas"
Const MCP_Address(8) As Byte = (%11010000,%11010010,%11010100,%11010110,%11011000,%11011010,%11011100,%11011110) //valid addresses for MCP342x
Const ADC_mask As Byte = %10011111
Const Gain_mask As Byte = %11111100
Const Resolution_mask As Byte = %11110011
Public Const Bits18 As Byte = %00001100
Public Const Bits16 As Byte = %00001000
Public Const Bits14 As Byte = %00000100
Public Const Bits12 As Byte = %00000000
Const StartBit As Byte = %10000000
Dim ConfigByte(8) As Byte
{
Select the ADC in the stored config for chip, valid values are 0-3 NB for 3421 bits are ignored, for 3422 only lsb is used
}
Public Sub SelectADC(ByVal chip As Byte, ByVal ADC As Byte)
ADC = (ADC And $03) << 5
ConfigByte(chip) = (ConfigByte(chip) And ADC_mask) Or ADC
End Sub
{
Select the gain in the stored config for chip, valid values are 1, 2, 4, 8
}
Public Sub SetGain(ByVal chip As Byte, ByVal Gain As Byte)
Dim gainbits As Byte
gain=gain And $0F
gainbits=255
While gain <> 0
gainbits=gainbits+1
gain=gain >> 1
Wend
ConfigByte(chip) = (ConfigByte(chip) And Gain_mask) Or gainbits
End Sub
{
Select the resolution in the stored config for chip, valid values are Bits12, Bits14, Bits16, Bits18
}
Public Sub SetResolution(ByVal chip As Byte, ByVal Resolution As Byte)
Resolution = Resolution And (Not Resolution_mask) //check it isn't an invalid number
ConfigByte(chip) = (ConfigByte(chip) And Resolution_mask) Or Resolution
End Sub
{
Start a one shot conversion on chip specified using stored config parameters
}
Public Sub StartConversion(ByVal Chip As Byte)
ConfigByte(chip)=ConfigByte(chip) Or StartBit
I2C.Start
I2C.WriteByte(MCP_Address(chip))
I2C.WriteByte(ConfigByte(chip))
I2C.Acknowledge(I2C_NOT_ACKNOWLEDGE)
I2C.Stop
End Sub
{
Start a one shot conversion on chip specified
Select the ADC in the stored config for chip, valid values are 0-3 NB for 3421 bits are ignored, for 3422 only lsb is used
Select the resolution in the stored config for chip, valid values are Bits12, Bits14, Bits16, Bits18
Select the gain in the stored config for chip, valid values are 1, 2, 4, 8
}
Public Sub StartConversion(ByVal Chip As Byte, ByVal ADC As Byte, ByVal resolution As Byte, ByVal gain As Byte)
SelectADC(chip,ADC)
SetGain(chip,gain)
SetResolution(chip,resolution)
ConfigByte(chip)=ConfigByte(chip) Or StartBit
I2C.Start
I2C.WriteByte(MCP_Address(chip))
I2C.WriteByte(ConfigByte(chip))
I2C.Acknowledge(I2C_NOT_ACKNOWLEDGE)
I2C.Stop
End Sub
{
Wait for the conversion to complete on the chip specified and return the value as a 32bit signed integer
}
Public Function ReadVal(ByVal Chip As Byte) As LongInt
Structure TWord
LSB As Byte
MSB As Byte
HSB As Byte
sign As Byte
End Structure
Dim value As Tword , donestatus As Byte, resolution As Byte
Repeat
I2C.Start
I2C.WriteByte(MCP_Address(chip) + 1)
value.HSB= I2C.ReadByte
I2C.Acknowledge(I2C_ACKNOWLEDGE)
value.MSB = I2C.ReadByte
I2C.Acknowledge(I2C_ACKNOWLEDGE)
value.LSB = I2C.ReadByte
I2C.Acknowledge(I2C_ACKNOWLEDGE)
donestatus = I2C.ReadByte And StartBit
I2C.Acknowledge(I2C_NOT_ACKNOWLEDGE)
I2C.Stop
Until donestatus=0
resolution= (Not Resolution_mask) And ConfigByte(chip)
If resolution = Bits18 Then
If value.HSB<128 Then
value.sign=0
Else
value.sign=255
EndIf
Else
value.LSB=value.MSB
value.MSB=value.HSB
If value.MSB<128 Then
value.sign=0
value.HSB=0
Else
value.sign=255
value.HSB=255
EndIf
EndIf
ReadVal=value
End Function
{
Wait for the conversion to complete on the chip specified and return the voltage measured as a floating point value
}
Public Function ReadVolts(ByVal Chip As Byte) As Float
Dim vcalc As Float
Dim resolution,gain As Byte
vcalc = Float(ReadVal(chip))
resolution= (Not Resolution_mask) And ConfigByte(chip)
gain= ConfigByte(chip) And (Not Gain_mask)
Select resolution
Case Bits18
vcalc=vcalc / 131072.0
Case Bits16
vcalc=vcalc /32768.0
Case Bits14
vcalc=vcalc /8192.0
Case Bits12
vcalc=vcalc /2048.0
End Select
Select gain
Case 0
vcalc=vcalc *2.048
Case 1
vcalc=vcalc * 1.024
Case 2
vcalc=vcalc * 0.512
Case 3
vcalc=vcalc * 0.256
End Select
ReadVolts=vcalc
End Function
{
Initialisation of config bytes
}
ConfigByte(0)=0
ConfigByte(1)=0
ConfigByte(2)=0
ConfigByte(3)=0
ConfigByte(4)=0
ConfigByte(5)=0
ConfigByte(6)=0
ConfigByte(7)=0
End Module
Code: Select all
{
*****************************************************************************
* Name : MCPtest.BAS *
* Author : Peter Mather *
* Notice : Copyright (c) Peter Mather *
* : All Rights Reserved *
* Date : 12/06/2011 *
* Version : 1.1 *
* Notes : *
* : *
*****************************************************************************
}
// if device and clock are omitted, then the compiler defaults to
// 18F452 @ 20MHz - they are just used here for clarity...
Device = 18F4520
Clock = 20
Include "usart.bas"
Include "convert.bas"
Include "mcp342x.bas"
Include "i2c.bas"
SetBaudrate(br19200)
DelayMS (100)
I2C.Initialize
DelayMS(100)
// program start...
USART.SetBaudrate(br19200)
USART.Write("MCPTest V1.1",13,10)
// output the result
While true
MCP342x.SetResolution(0,Bits16)
MCP342x.SetGain(0,8)
MCP342x.SelectADC(0,2)
MCP342x.StartConversion(0)
USART.Write("Value 16 bit = ", DecToStr(MCP342x.ReadVal(0)), 13, 10)
MCP342x.StartConversion(0,2,Bits12,4)
USART.Write("Value 12 bit = ", DecToStr(MCP342x.ReadVal(0)), 13, 10)
MCP342x.StartConversion(0,2,Bits18,8)
USART.Write("Volts = ", FloatToStr(MCP342x.ReadVolts(0),6), 13, 10)
DelayMS(1000)
Wend