MCP2210 Library — MCP3204 SPI ADC

During the past few weeks, I have shown many examples (see 1, 2, 3, 4) of using the open source MCP2210 Library with SPI devices under Linux. In this post, I will conclude this series with one more example: interfacing MCP3204 with MCP2210. With this example, I will have covered all the devices included on the evaluation board, which represents most of the scenarios you will run into. Other SPI devices can be controlled similarly using the methods illustrated in this series.

The code below shows how to read the channel 0 analog-digital converter values from MCP3204.

void TestMCP3204(hid_device* handle) {
    ChipSettingsDef chipDef;

    //set GPIO pins to be CS
    chipDef = GetChipSettings(handle);

    for (int i = 0; i < 9; i++) {
        chipDef.GP[i].PinDesignation = GP_PIN_DESIGNATION_CS;
        chipDef.GP[i].GPIODirection = GPIO_DIRECTION_OUTPUT;
        chipDef.GP[i].GPIOOutput = 1;
    }
    int r = SetChipSettings(handle, chipDef);

    //configure SPI
    SPITransferSettingsDef def;
    def = GetSPITransferSettings(handle);

    //chip select is GP1
    def.ActiveChipSelectValue = 0xfffd;
    def.IdleChipSelectValue = 0xffff;
    def.BitRate = 50000l;
    def.BytesPerSPITransfer =3;

    r = SetSPITransferSettings(handle, def);

    if (r != 0) {
        printf("Errror setting SPI parameters.\n");
        return;
    }
    
    byte spiCmdBuffer[4];

    //query ch0
    spiCmdBuffer[0] = 0x06; //00000110B (start, single ended, ch2)
    spiCmdBuffer[1] = 0x00; //(ch1 ch0)
    
    SPIDataTransferStatusDef def1 = SPISendReceive(handle, spiCmdBuffer, 3);       
    unsigned int val = ((def1.DataReceived[1] & 0xF) <<8) | def1.DataReceived[2];   
    
    printf("%3.2f\n", val/4096.0*2.5*2); //volts
}

While similar to the code you have seen previously, there are a few places that require special attention.

First, there seems to be a maximum bit-rate that the device can support. While the minimum bit-rate is clearly stated in the datasheet (due to the sample/hold capacitance), there doesn’t seem to be any mentioning of the maximum bit-rate. But since the maximum throughput of MCP3204 is at around 100ksps and it takes 12 clock cycles for the analog-digital conversion to complete, there is clearly a theoretical maximum speed under which the chip can communicate with the SPI bus. When SPITransferSettingsDef.BitRate is set as 6000000 (the value we had been using in other examples), there seems to be a large scaling error in the converted results (for instance, a 3V voltage would be returned as 2.5V). This is presumably due to the fact that the SPI clock is too fast for the sample and hold capacitor to charge fully before the measurement is taken place. In any event, when we relax the SPI clock speed to 50000, this error disappears.

Another potential pitfall is that the control bits for MCP3204 are 4 bits long and for easy interpretation of the ADC results, these bits must be padded with leading 0’s. For instance, the control bits for reading single ended result from ADC channel 0 is 1000 (which represents single ended, ch2, ch1 and ch0). In order for the returned data to end at B0, the command byte needs to be padded to 8 bits and two bytes are needed to represent the command (see code snippet below). As you can see, the 4-bit command is actually divided into two bytes.

    spiCmdBuffer[0] = 0x06; //00000110B (start, single ended, ch2)
    spiCmdBuffer[1] = 0x00; //(ch1 ch0)

This way, the last four bits in the first returned byte would be B11-D8 and the second returned byte would be B7-B0. Finally, the converted data is assembled back as:

    unsigned int val = ((def1.DataReceived[1] & 0xF) <<8) | def1.DataReceived[2];   

You can find my other example using the links below:

Be Sociable, Share!

3 Comments

  1. Hari says:

    Hi Kenny,

    That was awesome work. You made my life a lot easier by developing this library.
    I was able to access the individual GP and toggle the outputs.
    Now, I have a IR range finder connected to a MCP3201 which is interfaced with the MCP2210 on the MISO pin. I am not quite sure about how to read the converted digital value from that pin.
    Is there any interface or a function to read the data sent from the MCP3201 to MCP2210 on the MISO pin?
    Forgive me for my ignorance since I am relatively new to this field.

  2. lee says:

    when i tried your code, it gives me error: unknown type name “hid device”

Leave a Reply to Hari