MCP2210 Library
After a couple of weeks’ coding and testing, I finally finished the initial version of the MCP2210 C++ library for Linux. This library utilizes functions from Signal 11‘s HID API (hidraw) to communicate over the USB HID interface.
You can get the latest source from here, or you can pull directly from github using the command below:
git clone git://github.com/kerrydwong/MCP2210-Library.git
This library exposes all the functionalities specified in the device datasheet.
The following code snippet shows how to generate a rectangular wave on the GP0 pin by rapidly toggling it on and off:
#include "mcp2210.h"
int main(int argc, char** argv) {
int r = 0;
hid_device *handle;
/**
* initializing the MCP2210 device.
*/
handle = InitMCP2210();
/**
* Configure GPIO0 direction to output
*/
GPPinDef def = GetGPIOPinDirection(handle);
def.GP[0].GPIODirection = GPIO_DIRECTION_OUTPUT;
r = SetGPIOPinDirection(handle, def);
///< Generate a rectangular wave by toggling GP0.
while (1) {
def.GP[0].GPIOOutput = 1-def.GP[0].GPIOOutput;
r = SetGPIOPinVal(handle, def);
}
/**
* release the handle
*/
ReleaseMCP2210(handle);
return 0;
}
You should see a rectangular wave at GP0 (Pin 5) with a frequency of roughly 160 Hz.
The function calls are pretty straight forward. Most “Set” functions take the current device handle and the input data definition (e.g. SPITransferSettingsDef, GPPinDef, etc.) and returns a status code. A typical “Get” function call takes the current device handle and returns the corresponding data definition.
All SPI data transfer is handled via a single function call SPIDataTransfer, the function definition is shown below:
SPIDataTransferStatusDef SPIDataTransfer(hid_device *handle, byte* data, int length);
Basically, you supply the beginning address of the data to be transferred and the length of the data and when the call returns, the SPIDataTransferStatusDef contains the result along with the call status.
struct SPIDataTransferStatusDef {
/**
* Number of bytes received
*/
unsigned int NumberOfBytesReceived;
/**
* SPI transfer engine status
* 0x10: SPI transfer finished, no data to send
* 0x20: SPI transfer started, no data to receive
* 0x30: SPI data accepted, command completed successfully
*
*/
unsigned int SPIEngineStatus;
/**
* The buffer contains received data.
* Actual amount of data is determined by NumberOfBytesReceived.
*/
unsigned char DataReceived[60];
/**
* The error code returned
*/
int ErrorCode;
};
For more detailed information, you can take a look at the header file (mcp2210.h) or the doxygen generated documentation located under the doc directory.
The project was created using Netbeans 7.2 and was compiled under Ubuntu 12.04 (64 bit). To compile the code, make sure that you have the build essentials installed and also you will need libudev.
sudo apt-get install libudev0
Note, the process must have write access to the USB device under Linux. This means that either you will need to use sudo to run your code or you will need to setup rules to allow read/write access to the device using instructions provided on signal11. I have provided a UDEV rule file (99-hid.rules), and you may need to add it to the /etc/udev/rules.d directory.
I will provide more sample code in the coming weeks. Please drop me a line if you run into any issues.

Hello,
thank You for great job. Today I tried my MCP2210 with your library and test program, but no GPIO output activity I observed. With MCP2210 Utility under winXP it works fine. Are you sure, that all initialization procedures have been done in your test program? When i tried to read manufacturer i got empty string, the same fake activity I observed when I read some char from eeprom.
Thanks in advance.
Pavel
Hi Pavel,
Yes, I had tested the provided code using multiple chips. One thing I forgot to mention is that you will need to follow signall11′s directions to change device permissions on Linux, otherwise you will need to use sudo to run your code.
Yes, without root access to the devices, you will not be able to manipulate the settings.
Could you let me know if you are able to get it working by using sudo?
One more thing, if you are still having problems, could you tell me what is the returned status code? I just added a note in the blog posting above about the permissions. Thanks.
I’ve been working on getting the MCP2210 to run with Java on a Mac. I’m using the javahidapi based on signal11′s work. It was really nice to come across your code for linux and use it as a model.
Unfortunately, I’ve been having a difficult time getting SPI transfers to work reliably. After writing something like:
42 03 00 00 13 40 00
Part of the time, I get back this:
42 00 00 20
Meaning the write happened but nothing was read back. Part of the time I get this:
42 f8
Meaning the command was received but there was a SPI data transfer in progress. Also, part of the time I get this:
42 00 03 10 00 00 00
Meaning it finished and read correctly. The thing is, I think I have the connection configured synchronously so this sort of thing shouldn’t happen.
Anyway, I know this is a different environment but I thought I would just take a shot at describing it and see if this sounds like a problem you solved.
Hi Russel,
I have not run into the problem you described. The SPI clock needs to be issued until the results are received. Did you try this? If you continue issuing the SPI transfer command you should see the engine status comes back as 0×10 eventually.
Anyway, I am putting together a tutorial using MCP2210 SPI and should appear on this blog in the coming days.
Hi Kerry,
I’ve got this working. In my particular case, the SPI results are read out during the second byte of a SPI transfer so sending out more clock cycles will not help. It turns out, if you receieve a 0×20 in byte 3, you need to initiate another SPI transfer but set the number of bytes (specified in byte 1) to zero. I got that from Microchip support and it seems to work well.
In the case of an F8 in byte 1, you need to start the whole SPI transfer over as if it never happened. I placed a 25ms sleep before retrying a SPI transfer and this seems to minimize the number of re-trys.
Thanks for looking over my question and giving me your thoughts on it.
Hi Russel,
Yep, that’s the exactly approach you would need. The SPI command needs to be issued continuously until all the data has been received as indicated by the engine status as I mentioned previously. I have found that the number of bytes field does not need to be 0 though (at least from my testing), it seems that that field is not used the subsequent SPI calls are made when retrieving the result.
Hi Kerry,
Thank you for your work it was a great help.
But there’s something not really clear about how the MCP2210 handles the data size and transmission size:
If I configure the SPI to send 2 bytes per transmission and I want to send let’s say 4 bytes.
Will the MCP trigger 2 transmissions or only one and give up on the remaining data ?
So far it seems the data sent are truncated (not sent) when bigger than a transmission size.
Is it actually how it works ? The only point of the message size is, in case it’s smaller than the transmission size, to allow the master keeping the CS and the clock active until the transmission is done ?
Any information on this would be greatly appreciated !
Yes, as you observed the buffer size needs to match the length of the data you are sending. As you concluded, if the buffer length is larger then the size of the data, 0′s will be clocked in as the buffer is initialized to 0 with the maximum length.
Hi Kerry,
How should one handle the toggling of GPIO’s after SPI has been configured with one GPIO dedicated to CS for the downstream device (tilt sensor)?
The tilt sensor will be periodically queried for its data, but GPIO changes will be sporadic. The issue is that the GPIO Levels are all set
in two bytes in command 0×30, datasheet p.49, but what does one put for the CS? 0×00?
Thanks! Great work, btw!
Hi Vic,
Thanks for your comments. The way MCP2210 works is that once you have designated a pin as CS, it will automatically select/deselect when you issue SPI command. You can see this in my example here (http://www.kerrywong.com/2012/10/22/mcp2210-library-mcp3204-spi-adc/)
….
//chip select is GP1
def.ActiveChipSelectValue = 0xfffd;
def.IdleChipSelectValue = 0xffff;
….
Hi Kerry,
Once configured for CS, GPIO pins function extremely well for their intended purpose of serving SPI slaves. However, standalone GPIO control for individual pins seems not to work! I first read GET levels, assert a pin level, write SET levels, and read back GET levels for final confirmation and comparison. However, the MCP2210 never responds correctly, even if I configure the device with Microchip’s own utility. Is this chip not intended for general purpose GPIO’s, but specifically for SPI slaves or alternate functions? Microchip documentation points in that direction, and their demo kit seems to fit that model also, since they SPI slave an EEPROM, Temp Sensor, IO Expansion, and A/D.
Thank you, and best regards,
Vic
Hi Vic,
Could you give the example in this post a try? I used it to toggle GPIO0 and it worked fine. Did you try configure each individual pins separately? If you could post your code I can give it a try when I get back tonight.
Kerry, In your example you are toogling the GPIO0, but you are keeping track of the status of the GPIO.
When you do: def.GP[0].GPIOOutput = 1-def.GP[0].GPIOOutput; , def.GP[0].GPIOOutput is in the memory of your computer, not in the output register of the MCP2210.
I think Vic is trying to use the GPIO as both input and output at the same time. If you set the levels of the GPIO, there is no need to read them back (you just set the level yourself). If the GPIO is defined as input, then setting levels have no meaning since the level is forced by an external voltage.
So if the pin is Output, you can set the levels (to GND or VCC) but you probably wont be able to read the voltage (I should check the datasheet to see if it returns the flipflop value for the output bit).
If the pin is Input, there is no way of setting the voltage.
I wonder if the MCP2210 supports Open Colector output.
Best Regards
Can I have all this information, with the operating system windows, xp, 7 ..?
Since Signal11′s hidapi works in either Linux or Windows, technically speaking this library can be recompiled to work under Windows as well. But I have not tried it myself.