External ADC – MCP3021


I’ve used the AD converter several times in my articles, but you could be in situation, when you need more ADCs, or you have not enough IO ports. In these situations an external AD converter is suitable choice. I tested MCP3021, cheap and simple ADC worked on I2C bus. More inside…

 MCP3021 description (from official website)

The MCP3021 is a successive approximation A/D converter with 10-bit resolution. Available in the SOT-23 package, this device provides one, single-ended input with very low power consumption. The MCP3021 provides a low maximum conversion current and standby current of 250 µA and 1 µA respectively. Low current consumption combined with the small SOT-23 package make this device ideal for battery powered and remote data acquisition applications. Communication to the MCP3021 is performed using a 2-wire I2C compatible interface. Standard (100 kHz) and Fast (400 kHz) I2C™ modes are available with the device. An on-chip conversion clock enables independent timing for the I2C™ clock and the conversion clock. The device is also addressable allowing up to eight devices on a single 2-wire bus. The MCP3021 runs on a single supply voltage that operates over a broad range of 2.7 V to 5.5 V



ADC usage with DPA

You can use my previous I2C project as a base for new one and change it for new device in this way:

// Handle peripheral command
// PNUM = 2 = ADC MCP3021
if ( _PNUM == PNUM_USER + 2 )
    if ( _PCMD == 0 )
        // Check data length
        if ( _DpaDataLength != 0 )
            DpaApiReturnPeripheralError( ERROR_DATA_LEN );
        adc_result =  MCP3021_Read_ADC();
        _DpaMessage.Response.PData[0] = adc_result.high8;
        _DpaMessage.Response.PData[1] = adc_result.low8;
        _DpaDataLength = 2;
        goto DpaHandleReturnTRUE;
    // unknown command?
    DpaApiReturnPeripheralError( ERROR_PCMD ); 

when adc_result is defined as:

static uns16 adc_result;

There is also new function for ADC read:

uns16 MCP3021_Read_ADC(void)
    uns16 ret_data = 0;
    ret_data.high8 = i2c_read(ACK);
    ret_data.low8 = i2c_read(NO_ACK);

Be carefull, when you are purchasing this converter. There are more variants, but there is difference between address only. Following table shows, which address you have to use for specific variant:

MCP3021_adressAddress format is 0b1001A2A1A0R/W.

I bought MCP3021A1T-E/OT, so I used 0b10010010 address for write operation.


I have node with NADR 1, so in my case DPA packet will be:

MCP3021_dpaand response:

MCP3021_dparesponseYou can see, response data: 0x0B and 0x3B. Just, use only four LSB from first byte and six MSB from second byte, so we have 0000 1011 0011 1011 (BIN) which is 10 1100 1110 (BIN) which is 718 (DEC).

From calculation voltage = (718/1024)*VDD, where VDD is in my case 3V, the input voltage is 2.1V. And this is correct 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.