Monday, June 11, 2018

MCP2221 Tutorial - I2C Interfacing made easy

What is MCP2221?
MCP2221 is a USB to UART & I2C bridge integrated circuit from Microchip Technologies; I would highly recommend reading this tutorial first for further information on it.

How can the MCP2221 be beneficial to me?
Well, if you want to build a computer control and/or data acquisition unit via USB to an I2C slave device without the hustle of using a microcontroller or an Arduino, and less expensive than both of them, the MCP2221 is a good option, it acts as a master I2C device, and it can be programmed easily using its DLL from Microchip on Windows OS, or by configuring it as a USB-I2C dongle on Linux. Another advantage for the MCP2221 that it comes in a PDIP package, which makes it convenient for breadboard prototyping and testing.

What is I2C?
In brief, it is a low speed, master-slave serial communication protocol that uses two lines: data line, named SDA, and clock, named SCL. It is mainly used for sensors interfacing, low speed ADC/DAC or any similar integrated circuits. According to the I2C standard, the maximum speed is 3.2 Mbits/sec between a master and slave but the MCP2221 supports only up to 400 KHz bit rate.
For more C examples for the MCP2221, please visit this GitHub repository. 



Example Code:


#include <stdio.h>
#include "mcp2221_dll_um.h"

//Linking the MCP2221 library, only valid for Visual Studio
#pragma comment(lib, "mcp2221_dll_um_x86.lib")

#define I2cAddr7bit 1
#define I2cAddr8bit 0

//Global variables
void *handle;
wchar_t SerNum = 0x0000075428;
wchar_t LibVer[6];
wchar_t MfrDescriptor[30];
wchar_t ProdDescrip[30];
int ver = 0;
int error = 0;
int flag = 0;
unsigned int PID = 0xDD;
unsigned int VID = 0x4D8;
unsigned int NumOfDev = 0;
unsigned char PowerAttrib;
unsigned char DacVal = 31;
unsigned char SlaveAddress = 0x63;
unsigned char TxBuffer[8];
unsigned char RxBuffer[8];

//Functions prototypes
void ExitFunc();
void Mcp2221_config();

void ExitFunc()
{
    Mcp2221_CloseAll();
 Mcp2221_Reset(handle);
}

void Mcp2221_config()
{
    ver = Mcp2221_GetLibraryVersion(LibVer);  //Get DLL version
    if(ver == 0)
    {
        printf("Library (DLL) version: %ls\n", LibVer);
    }
    else
    {
        error = Mcp2221_GetLastError();
        printf("Version can't be found, version: %d, error: %d\n", ver, error);
    }

    //Get number of connected devices with this VID & PID
    Mcp2221_GetConnectedDevices(VID, PID, &NumOfDev);
    if(NumOfDev == 0)
    {
        printf("No MCP2221 devices connected\n");
        //exit(0);
    }
    else
    {
        printf("Number of devices found: %d\n", NumOfDev);
    }

    //open device by S/N
    //handle = Mcp2221_OpenBySN(VID, PID, &SerNum);

    //Open device by index
    handle = Mcp2221_OpenByIndex(VID, PID, NumOfDev-1);
    if(error == NULL)
    {
        printf("Connection successful\n");       
    }
    else
    {
        error = Mcp2221_GetLastError();
        printf("Error message is %s\n", error);
    }

    //Get manufacturer descriptor
    flag = Mcp2221_GetManufacturerDescriptor(handle, MfrDescriptor);
    if(flag == 0)
    {
        printf("Manufacturer descriptor: %ls\n", MfrDescriptor);

    }
    else
    {
        printf("Error getting descriptor: %d\n", flag);
    }

    //Get product descriptor
    flag = Mcp2221_GetProductDescriptor(handle, ProdDescrip);
    if(flag == 0)
    {
        printf("Product descriptor: %ls\n", ProdDescrip);        
    }
    else
    {
        printf("Error getting product descriptor: %d\n", flag);        
    }

    //Get power attributes
    flag = Mcp2221_GetUsbPowerAttributes(handle, &PowerAttrib, &ReqCurrent);
    if(flag == 0)
    {
        printf("Power Attributes, %x\nRequested current units = %d\nRequested current(mA) = %d\n", PowerAttrib, ReqCurrent, ReqCurrent*2);
    }
    else
    {
        printf("Error getting power attributes: %d\n", flag);      
    }

    //Set I2C bus
    flag = Mcp2221_SetSpeed(handle, 500000);    //set I2C speed to 400 KHz
    if(flag == 0)
    {
        printf("I2C is configured\n");        
    }
    else
    {
        printf("Error setting I2C bus: %d\n", flag);        
    }

    //Set I2C advanced parameters
    flag = Mcp2221_SetAdvancedCommParams(handle, 10, 1000);  //10ms timeout, try 1000 times
    if(flag == 0)
    {
        printf("I2C advanced settings set\n");
    }
    else
    {
        printf("Error setting I2C advanced settings: %d\n", flag);      
    }
}

void main(int argc, char *argv[])
{
    atexit(ExitFunc); //Call exit function

    //Configure any connected MCP2221
    Mcp2221_config();
 
    while(1)
    {
  
  //Write all contents of TxBuffer to I2C slave device 0x63
  flag = Mcp2221_I2cWrite(handle, sizeof(TxBuffer), SlaveAddress, I2cAddr7bit, TxBuffer);    //issue start condition then address
  if(flag == 0)
  {
   printf("Writing to device %x successful\n", SlaveAddress);
  }
  else
  {
   printf("Error writing to I2C device: %x, Error: %d\n", SlaveAddress1, flag);
   Mcp2221_I2cCancelCurrentTransfer(handle);
  }
  
  //Read 8 bytes from I2C slave device 0x63
  flag = Mcp2221_I2cRead(handle, 8, SlaveAddress, I2cAddr7bit, RxBuffer);
  if(flag == 0)
  {
   printf("Data received is %x\n", RxBuffer);
  }
  else 
  {
   printf("Error receiving ack: %d\n", flag);
  } 
    }
}



2 comments:

  1. Hello
    First of all thanks for sharing thi example. I tried to reproduce this example but for me did not work, I was wonderinf if you can help me. Every time I debug this example in Visual Studi(2015) using a project VisualC++/Console Project Win32 and using the librearis donwloaded from Microchip (Unmanaged libraries) i got the error "The program finished with the error -55", the popped up console closed inmediatly though the project was compiled whitout errores.
    (I am triying to reproduce this example in Windows 10 64b using Visual Studio 2015, linking the the librarie mcp2221_dll_um_x86.lib statically and including the file mcp2221_dll_um.h in the project, as well I've putted into the SysWOW64 the mcp2221_dll_um_x86.dll file).

    I hope you can help me.
    Regards :)

    ReplyDelete
    Replies
    1. Hi Alexis, this code was compiled in VS2012 under Windows 7 & 8.1 x64, I haven't compiled yet under VS2015, however it compiled fine with NetBeans and GCC.
      Speaking of the error code you got, it is a compilation error or a message error because one of the functions/configuration calls failed?, can you post a screenshot or a copy of the error because it's not very clear to me.
      Usually I copy the .dll file to the same visual studio project directory, same can apply for the header file as well.

      Delete