Example of how to use the LTC1865 2-Channel SPI 16-bit ADC.

Dependencies:   mbed

Despite much effort I was unable to achieve adequate internal ADC performance on my LPC1768. I had read a lot of material from the mbed community and other sources and tried various solutions, none of which met my requirement for fast ADC sampling and input processing (so, for instance, ruling out averaging over many ADC input values).

I searched for an external ADC meeting the following criteria: - 2 channels - 16-bit resolution - Fast SPI serial I/O - Single 5V supply - Input resolution 0 to 5V - Low cost - DIP or SO package

The LTC1865 fits the bill!

Here is the datasheet: http://cds.linear.com/docs/en/datasheet/18645fb.pdf

The example code shows how to read the ADC in single-ended mode (i.e. each channel reads 0 to 5V).

Please note that my style is 'old hat', as I come from an iRMX and PL/M background of 30 years ago, but it works!

Import programLTC1865_adc

Example of how to use the LTC1865 2-Channel SPI 16-bit ADC.

Committer:
ChrisMabey
Date:
Wed Nov 09 17:40:41 2016 +0000
Revision:
0:778d41341161
Example of how to use the LTC1865 2-Channel SPI 16-bit ADC.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ChrisMabey 0:778d41341161 1 /***************************************************************************************/
ChrisMabey 0:778d41341161 2 /* */
ChrisMabey 0:778d41341161 3 /* Program: LTC1865_ADC_Example */
ChrisMabey 0:778d41341161 4 /* Author: Chris Mabey */
ChrisMabey 0:778d41341161 5 /* Date: November 2016 */
ChrisMabey 0:778d41341161 6 /* Target Platform: mbed */
ChrisMabey 0:778d41341161 7 /* Description: External LTC1865 16-bit ADC example */
ChrisMabey 0:778d41341161 8 /* Version: 1v0 */
ChrisMabey 0:778d41341161 9 /* */
ChrisMabey 0:778d41341161 10 /* Notes: After struggling with the internal LPC1768 ADC noise I decided to use an */
ChrisMabey 0:778d41341161 11 /* external ADC. My requirements were 2 channels at 16-bit resolution, single */
ChrisMabey 0:778d41341161 12 /* 5V supply, input range 0 to 5V (Vcc), high sample rate and using a fast SPI */
ChrisMabey 0:778d41341161 13 /* clock frequency. */
ChrisMabey 0:778d41341161 14 /* I'm very happy with the LTC1855 and as I've received help from the mbed */
ChrisMabey 0:778d41341161 15 /* community thought I'd share an example that may be of help to others. */
ChrisMabey 0:778d41341161 16 /* */
ChrisMabey 0:778d41341161 17 /* LTC1865 Datasheet: http://cds.linear.com/docs/en/datasheet/18645fb.pdf */
ChrisMabey 0:778d41341161 18 /* */
ChrisMabey 0:778d41341161 19 /* Please don't criticise my coding style, it's 'old school' from when I worked */
ChrisMabey 0:778d41341161 20 /* with Intel iRMX and the PL/M language 30 or so years ago! */
ChrisMabey 0:778d41341161 21 /* */
ChrisMabey 0:778d41341161 22 /***************************************************************************************/
ChrisMabey 0:778d41341161 23
ChrisMabey 0:778d41341161 24 #include "mbed.h"
ChrisMabey 0:778d41341161 25
ChrisMabey 0:778d41341161 26 /* ADC (SPI) */
ChrisMabey 0:778d41341161 27 /* ========= */
ChrisMabey 0:778d41341161 28 #define SPI_MOSI_PIN p5 /* SPI Bus Master Out/Slave In */
ChrisMabey 0:778d41341161 29 #define SPI_MISO_PIN p6 /* SPI Bus Master In/Slave Out */
ChrisMabey 0:778d41341161 30 #define SPI_SCK_PIN p7 /* SPI Bus Master Clock */
ChrisMabey 0:778d41341161 31 #define SPI_CS_ADC_PIN p8 /* SPI ADC Slave Select */
ChrisMabey 0:778d41341161 32
ChrisMabey 0:778d41341161 33 /* The LTC1864 ADC has two input channels */
ChrisMabey 0:778d41341161 34 #define ADC_CHANNEL_0 0
ChrisMabey 0:778d41341161 35 #define ADC_CHANNEL_1 1
ChrisMabey 0:778d41341161 36
ChrisMabey 0:778d41341161 37 /* The LTC1864 conversion cycle begins with the rising edge of CONV. */
ChrisMabey 0:778d41341161 38 /* After a period equal to tCONV, the conversion is finished. */
ChrisMabey 0:778d41341161 39 /* The maximum conversion time is 3.2uS, so wait for 4uS as wait_us() */
ChrisMabey 0:778d41341161 40 /* accepts an integer value. */
ChrisMabey 0:778d41341161 41 #define ADC_CONVERSION_TIME 4
ChrisMabey 0:778d41341161 42
ChrisMabey 0:778d41341161 43 #define LOW 0
ChrisMabey 0:778d41341161 44 #define HIGH 1
ChrisMabey 0:778d41341161 45
ChrisMabey 0:778d41341161 46
ChrisMabey 0:778d41341161 47 /**********************************************************/
ChrisMabey 0:778d41341161 48 /* */
ChrisMabey 0:778d41341161 49 /* MBED I/O Ports */
ChrisMabey 0:778d41341161 50 /* */
ChrisMabey 0:778d41341161 51 /**********************************************************/
ChrisMabey 0:778d41341161 52 DigitalOut ADCcsPin(SPI_CS_ADC_PIN);
ChrisMabey 0:778d41341161 53 SPI spi(SPI_MOSI_PIN, SPI_MISO_PIN, SPI_SCK_PIN);
ChrisMabey 0:778d41341161 54
ChrisMabey 0:778d41341161 55
ChrisMabey 0:778d41341161 56 /* Holds the last ADC conversion channel */
ChrisMabey 0:778d41341161 57 unsigned char previousADCchannel;
ChrisMabey 0:778d41341161 58
ChrisMabey 0:778d41341161 59
ChrisMabey 0:778d41341161 60 /***********************************************************/
ChrisMabey 0:778d41341161 61 /* */
ChrisMabey 0:778d41341161 62 /* Read_External_ADC */
ChrisMabey 0:778d41341161 63 /* */
ChrisMabey 0:778d41341161 64 /* Function: Read the latest value from the specified */
ChrisMabey 0:778d41341161 65 /* channel of the external LTC1865 ADC. */
ChrisMabey 0:778d41341161 66 /* */
ChrisMabey 0:778d41341161 67 /* Performance: Takes around 15.5uS to execute */
ChrisMabey 0:778d41341161 68 /* using 20MHz SPI clock without dummy read for */
ChrisMabey 0:778d41341161 69 /* switching channels (measured on NUCLEO-L476RG)*/
ChrisMabey 0:778d41341161 70 /* */
ChrisMabey 0:778d41341161 71 /* Input Parameters: */
ChrisMabey 0:778d41341161 72 /* unsigned char: the ADC channel (ADC_LP_CHANNEL or */
ChrisMabey 0:778d41341161 73 /* ADC_GP_CHANNEL) */
ChrisMabey 0:778d41341161 74 /* */
ChrisMabey 0:778d41341161 75 /* Output Parameters: */
ChrisMabey 0:778d41341161 76 /* unsigned int: the ADC value (range 0 to 65535) */
ChrisMabey 0:778d41341161 77 /* */
ChrisMabey 0:778d41341161 78 /***********************************************************/
ChrisMabey 0:778d41341161 79 unsigned int Read_External_ADC(unsigned char channel)
ChrisMabey 0:778d41341161 80 {
ChrisMabey 0:778d41341161 81 unsigned int adcVal;
ChrisMabey 0:778d41341161 82
ChrisMabey 0:778d41341161 83 /* If changing channel a dummy read is required as the */
ChrisMabey 0:778d41341161 84 /* two bits of the input word (SDI) assign the MUX */
ChrisMabey 0:778d41341161 85 /* configuration for the next requested conversion. */
ChrisMabey 0:778d41341161 86 /* ---- */
ChrisMabey 0:778d41341161 87 if (channel != previousADCchannel)
ChrisMabey 0:778d41341161 88 {
ChrisMabey 0:778d41341161 89 /* The LTC1865 conversion cycle begins with the rising edge of CONV */
ChrisMabey 0:778d41341161 90 ADCcsPin = HIGH;
ChrisMabey 0:778d41341161 91
ChrisMabey 0:778d41341161 92 /* Wait for the conversion to complete */
ChrisMabey 0:778d41341161 93 wait_us(ADC_CONVERSION_TIME); /* Note: Blocks interrupts! */
ChrisMabey 0:778d41341161 94
ChrisMabey 0:778d41341161 95 /* Enable the Serial Data Out to allow the data to be shifted out by taking CONV low */
ChrisMabey 0:778d41341161 96 ADCcsPin = LOW;
ChrisMabey 0:778d41341161 97
ChrisMabey 0:778d41341161 98 /* Send command and read previous selected ADC channel value, whilst */
ChrisMabey 0:778d41341161 99 /* telling the ADC the next conversion is for the new channel */
ChrisMabey 0:778d41341161 100 adcVal = spi.write(0x8000 | (((unsigned int)channel) << 14)); /* Transmit the Mode (Single-ended MUX Mode), */
ChrisMabey 0:778d41341161 101 /* the channel and receive the sixteen bit result */
ChrisMabey 0:778d41341161 102
ChrisMabey 0:778d41341161 103 /* Save the new ADC channel */
ChrisMabey 0:778d41341161 104 previousADCchannel = channel;
ChrisMabey 0:778d41341161 105 }
ChrisMabey 0:778d41341161 106 /* endif */
ChrisMabey 0:778d41341161 107
ChrisMabey 0:778d41341161 108 /* The LTC1865 conversion cycle begins with the rising edge of CONV */
ChrisMabey 0:778d41341161 109 ADCcsPin = HIGH;
ChrisMabey 0:778d41341161 110
ChrisMabey 0:778d41341161 111 /* Wait for the conversion to complete */
ChrisMabey 0:778d41341161 112 wait_us(ADC_CONVERSION_TIME);
ChrisMabey 0:778d41341161 113
ChrisMabey 0:778d41341161 114 /* Enable the Serial Data Out to allow the data to be shifted out by taking CONV low */
ChrisMabey 0:778d41341161 115 ADCcsPin = LOW;
ChrisMabey 0:778d41341161 116
ChrisMabey 0:778d41341161 117 /* Send command and read previous selected ADC channel value, whilst */
ChrisMabey 0:778d41341161 118 /* telling the ADC the next conversion is for the same channel */
ChrisMabey 0:778d41341161 119 adcVal = spi.write(0x8000 | (((unsigned int)channel) << 14)); /* Transmit the Mode (Single-ended MUX Mode), */
ChrisMabey 0:778d41341161 120 /* the channel and receive the sixteen bit result */
ChrisMabey 0:778d41341161 121
ChrisMabey 0:778d41341161 122 return(adcVal); /* Return the 16-bit ADC value */
ChrisMabey 0:778d41341161 123 }
ChrisMabey 0:778d41341161 124
ChrisMabey 0:778d41341161 125
ChrisMabey 0:778d41341161 126 int main()
ChrisMabey 0:778d41341161 127 {
ChrisMabey 0:778d41341161 128 /**********************************************************/
ChrisMabey 0:778d41341161 129 /* */
ChrisMabey 0:778d41341161 130 /* Initialise the SPI interface to the external ADC */
ChrisMabey 0:778d41341161 131 /* */
ChrisMabey 0:778d41341161 132 /**********************************************************/
ChrisMabey 0:778d41341161 133 spi.format(16,1); /* 16-bit data, Mode 1 */
ChrisMabey 0:778d41341161 134 spi.frequency(20000000); /* 20MHz clock rate */
ChrisMabey 0:778d41341161 135
ChrisMabey 0:778d41341161 136 ADCcsPin = LOW; /* Deselect the ADC by setting chip select low */
ChrisMabey 0:778d41341161 137
ChrisMabey 0:778d41341161 138 /* Perform a dummy read to initialise the ADC conversion channel to ADC_CHANNEL_0 */
ChrisMabey 0:778d41341161 139 Read_External_ADC(ADC_CHANNEL_0);
ChrisMabey 0:778d41341161 140
ChrisMabey 0:778d41341161 141 printf("\n\rLTC1865 External ADC Example\n\r");
ChrisMabey 0:778d41341161 142
ChrisMabey 0:778d41341161 143 while(1)
ChrisMabey 0:778d41341161 144 {
ChrisMabey 0:778d41341161 145 printf("Channel 0 = %5u ", Read_External_ADC(ADC_CHANNEL_0));
ChrisMabey 0:778d41341161 146
ChrisMabey 0:778d41341161 147 wait(0.5f); /* 0.5s */
ChrisMabey 0:778d41341161 148
ChrisMabey 0:778d41341161 149 printf("Channel 1 = %5u\n\r", Read_External_ADC(ADC_CHANNEL_1));
ChrisMabey 0:778d41341161 150 }
ChrisMabey 0:778d41341161 151 /* end while */
ChrisMabey 0:778d41341161 152 }
ChrisMabey 0:778d41341161 153