cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 4 MCU

Anonymous
Not applicable

Not sure if this goes here or in the USB forum but since it's part of the PSoC 4xxx prototype boards I decided to post it in here:

   

Someone in a forum asked for a cheap and easy USB to I2C Dev Kit, so I suggested using the break off USB Serial part of the CY8CKIT-049.

   

As my example I used an RTC clock based on the PCF8563 chip from NXP

   

So first I open the Cypress USB-Serial Configuration Utility after plugin in the board to my PC USB port, and selected my USB-Serial (Single Channel) target and clicked on Connect:

   

   


I left the USB configuration alone, but you can change the VID/PID manufacturer and product strings etc, also left the IO levels to CMOS (you can select TTL) and clicked on the SCB tab:



Next I selected the mode to be I2C and clicked Configure

   

Note that you can set the notification LEDs to use GPIO pins to drive transmit and receive individual LEDs or a single one for both tx/rx

   

Selected 400KHz and set it to be in Master mode and ok.

   




Back to the previous screen click on program.



And it will come back with success (if everything is setup right).

   


   

 

   

I added two 2.2K Ohm pull-up resistors as required for 400Kbps

   

   

Altered the I2cmaster example that came with the USB-Serial Software Development Kit

   

http://www.cypress.com/?rID=83110

   

I'll include the code at the end of the post.

   

I did probe the SCL and SDA to make sure I was reading/writing the right data:

   

   

 And it worked great:

   

   

So that little chip that we use for communicating with the boot loader has other uses, it can also do UART of course, and SPI.

   

Here is the code (Windoes based):

   
        
   
        
   
    #include "stdafx.h"   
   
        
   
    #include <stdio.h>   
   
    #include <windows.h>   
   
    #include <dbt.h>   
   
    #include <conio.h>   
   
    #include "..\..\..\library\inc\CyUSBSerial.h"   
   
        
   
    // Define VID & PID   
   
    // These numbers depends on individual products   
   
    #define VID 0x04B4   
   
    #define PID 0x0004    
   
        
   
    //Variable to store cyHandle of the selected device   
   
    CY_HANDLE cyHandle;    
   
    //Varible to capture return values from USB Serial API    
   
    CY_RETURN_STATUS cyReturnStatus;    
   
        
   
    //CY_DEVICE_INFO provides additional details of each device such as product Name, serial number etc..   
   
    CY_DEVICE_INFO cyDeviceInfo, cyDeviceInfoList[16];    
   
        
   
    //Structure to store VID & PID defined in CyUSBSerial.h   
   
    CY_VID_PID cyVidPid;   
   
        
   
    //Data configuration and buffer structures   
   
    CY_I2C_DATA_CONFIG cyI2CRWDataConfig;   
   
    CY_DATA_BUFFER cyDataRWBuffer;   
   
        
   
    //Variables used by application   
   
    UINT8 cyNumDevices;   
   
    unsigned char deviceID[16];   
   
        
   
    #define changeIntToHex(dec)     ( (((dec)/10) <<4) + ((dec)%10) )   
   
    #define converseIntToHex(dec)     ( (((dec)>>4) *10) + ((dec)%16) )   
   
    #define changeHexToInt(hex)     ( (((hex)>>4) *16 ) + ((hex)%16) )   
   
    #define converseHexToInt(hex)     ( (((hex)/10) <<4 ) + ((hex)%10) )   
   
        
   
    #define CTRL_BUF1     0x00   
   
    #define CTRL_BUF2     0x01   
   
        
   
    #define SECOND_DATA_BUF     0x02   
   
    #define MINUTE_DATA_BUF     0x03   
   
    #define HOUR_DATA_BUF     0x04   
   
        
   
    #define DAY_DATA_BUF             0x05   
   
    #define WEEK_DATA_BUF     0x06   
   
    #define MONTH_DATA_BUF     0x07   
   
    #define YEAR_DATA_BUF     0x08   
   
        
   
    #define MINUTE_AE_BUF     0x09   
   
    #define HOUR_AE_BUF     0x0A   
   
    #define DAY_AE_BUF     0x0B   
   
    #define WEEK_AE_BUF     0x0C   
   
        
   
    #define CLK_FRQ_BUF     0x0D   
   
    #define TIMER_CTRL_BUF     0x0E   
   
    #define COUNT_VAL_BUF     0x0F   
   
        
   
    typedef unsigned char uchar;   
   
    typedef unsigned int uint;   
   
        
   
    void WriteAByte(uchar wordAdr, uchar dat)   
   
    {   
   
     uchar buffer[2];   
   
     buffer[0] = wordAdr;   
   
     buffer[1] = dat;   
   
     cyDataRWBuffer.buffer = buffer;   
   
     cyDataRWBuffer.length = 2;   
   
     CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
   
    //     SMBus_Write(0xA2, wordAdr, dat, 2);   
   
    }   
   
        
   
    void ReadNByte(uchar wordAdr, uchar *pRdDat, uchar length)   
   
    {   
   
     cyDataRWBuffer.buffer = &wordAdr;   
   
     cyDataRWBuffer.length = 1;   
   
     CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
   
    //     SMBus_Write(0xA2, wordAdr, 0, 1);   
   
        
   
     cyDataRWBuffer.buffer = pRdDat;   
   
     cyDataRWBuffer.length = length;   
   
     CyI2cRead(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);   
   
    //     SMBus_Read(0xA3, pRdDat, 11);   
   
    }   
   
        
   
    void PCF8563_getTime(uchar *buf)   
   
    {   
   
     ReadNByte(SECOND_DATA_BUF, buf, 11);   
   
     buf[0] = buf[0] & 0x7f;     //get second data   
   
     buf[1] = buf[1] & 0x7f;     //get minute data   
   
     buf[2] = buf[2] & 0x3f;     //get hour data   
   
     buf[3] = buf[3] & 0x3f;     //get day data   
   
     buf[4] = buf[4] & 0x07;     //get weekday data   
   
     buf[5] = buf[5] & 0x9f;     //get century_month data (most significant bit Century bit 0=2000 1=1900)   
   
    //     buf[6] = buf[6];     //get year data   
   
     buf[7] = buf[7] & 0xff;     //get minute_alarm data   
   
     buf[8] = buf[8] & 0xaf;     //get hour_alarm data   
   
     buf[9] = buf[9] & 0xaf;     //get day_alarm data   
   
     buf[10] = buf[10] & 0x87;     //get weekday_alarm data   
   
        
   
     buf[0] = converseIntToHex(buf[0]);   
   
     buf[1] = converseIntToHex(buf[1]);   
   
     buf[2] = converseIntToHex(buf[2]);   
   
     buf[3] = converseIntToHex(buf[3]);   
   
     buf[4] = converseIntToHex(buf[4]);   
   
     buf[5] = converseIntToHex(buf[5]);   
   
     buf[6] = converseIntToHex(buf[6]);   
   
    }   
   
        
   
    void PCF8563_setTime(uchar hour, uchar minute, uchar second, uchar day, uchar weekday, uchar month, uint year)   
   
    {   
   
     hour = changeIntToHex(hour);   
   
     minute = changeIntToHex(minute);   
   
     second = changeIntToHex(second);   
   
     day = changeIntToHex(day);   
   
     weekday = changeIntToHex(weekday);   
   
     month = changeIntToHex(month);   
   
     if (year < 2000)   
   
     {   
   
     // if 19xx set Century bit   
   
     month |= 0x80;   
   
     }   
   
     year %= 100;   
   
     year = changeIntToHex(year);   
   
        
   
     WriteAByte(HOUR_DATA_BUF, hour);   
   
     WriteAByte(MINUTE_DATA_BUF, minute);   
   
     WriteAByte(SECOND_DATA_BUF, second);   
   
     WriteAByte(DAY_DATA_BUF, day);   
   
     WriteAByte(WEEK_DATA_BUF, weekday);   
   
     WriteAByte(MONTH_DATA_BUF, month);   
   
     WriteAByte(YEAR_DATA_BUF, year);   
   
    }   
   
        
   
    void PCF8563_init(void)   
   
    {   
   
     WriteAByte(CTRL_BUF1, 0x00);     //basic setting   
   
     WriteAByte(CTRL_BUF2, 0x12);     //alarm enable   
   
    }   
   
        
   
    CY_RETURN_STATUS I2CMasterSetup(int deviceNumber)   
   
    {   
   
     CY_I2C_CONFIG cyI2CConfig;   
   
     CY_RETURN_STATUS rStatus;   
   
     int interfaceNum = 0;   
   
        
   
     // Configure the I2C read and write data   
   
     cyI2CRWDataConfig.isStopBit = true;   
   
     cyI2CRWDataConfig.isNakBit = false;   
   
     cyI2CRWDataConfig.slaveAddress = 0xA2 >> 1;   
   
        
   
     // Configure the I2C   
   
     printf("Opening I2C device with device number %d...\n", deviceNumber);   
   
        
   
     //Open the device at deviceNumber   
   
     rStatus = CyOpen(deviceNumber, interfaceNum, &cyHandle);   
   
     if (rStatus != CY_SUCCESS)   
   
     {   
   
     printf("I2C Device open failed...\n");   
   
     return rStatus;   
   
     }   
   
        
   
     // Get configuration   
   
     printf("I2C Open successfull. Invoking API for retrieving I2C configuration...\n");   
   
     rStatus = CyGetI2cConfig(cyHandle, &cyI2CConfig);   
   
     if (rStatus != CY_SUCCESS)   
   
     {   
   
     printf("CyGetI2cConfig returned failure code.\n");   
   
     return rStatus;   
   
     }   
   
     printf("I2C Frequency : %d , Slave address : %d\n",   
   
     cyI2CConfig.frequency,   
   
     cyI2CConfig.slaveAddress);   
   
        
   
     // Set configuration   
   
        
   
     // Configure I2C with different settings   
   
     printf("Setting new I2C configuration...\n");   
   
     cyI2CConfig.frequency = 400000;   
   
     cyI2CConfig.slaveAddress = 0x60; // Ain't matter, this is for slave mode.   
   
     cyI2CConfig.isMaster = 1;   
   
     printf("New Configuration - I2C Frequency : %d , Slave address : %d, isMaster : %d\n",   
   
     cyI2CConfig.frequency,   
   
     cyI2CConfig.slaveAddress,   
   
     cyI2CConfig.isMaster);   
   
        
   
     rStatus = CySetI2cConfig(cyHandle, &cyI2CConfig);   
   
     if (rStatus != CY_SUCCESS)   
   
     {   
   
     printf("CySetI2cConfig returned failure code.\n");   
   
     return rStatus;   
   
     }   
   
     printf("Setting new I2C configuration successful.\n");   
   
        
   
     // Check to see if the new configuration is applied on I2C   
   
     printf("Checking the new I2C configuration ...\n");   
   
     rStatus = CyGetI2cConfig(cyHandle, &cyI2CConfig);   
   
     if (rStatus != CY_SUCCESS)   
   
     {   
   
     printf("CyGetI2cConfig returned failure code.\n");   
   
     return rStatus;   
   
     }   
   
     printf("I2C Configuration retrieved - I2C Frequency : %d , Slave address : %d, isMaster : %d\n",   
   
     cyI2CConfig.frequency,   
   
     cyI2CConfig.slaveAddress,   
   
     cyI2CConfig.isMaster);   
   
     return rStatus;   
   
    }   
   
        
   
    int FindDeviceAtSCB0()   
   
    {   
   
     CY_VID_PID cyVidPid;   
   
        
   
     cyVidPid.vid = VID; //Defined as macro   
   
     cyVidPid.pid = PID; //Defined as macro   
   
        
   
     //Array size of cyDeviceInfoList is 16    
   
     cyReturnStatus = CyGetDeviceInfoVidPid (cyVidPid, deviceID, (PCY_DEVICE_INFO)&cyDeviceInfoList, &cyNumDevices, 16);   
   
        
   
     int deviceIndexAtSCB0 = -1;   
   
     for (int index = 0; index < cyNumDevices; index++)   
   
     {   
   
     printf ("\nNumber of interfaces: %d\n \   
   
     Vid: 0x%X \n\   
   
     Pid: 0x%X \n\   
   
     Serial name is: %s\n\   
   
     Manufacturer name: %s\n\   
   
     Product Name: %s\n\   
   
     SCB Number: 0x%X \n\   
   
     Device Type: %d \n\   
   
     Device Class: %d\n\n\n",   
   
     cyDeviceInfoList[index].numInterfaces,                     
   
     cyDeviceInfoList[index].vidPid.vid,   
   
     cyDeviceInfoList[index].vidPid.pid,   
   
     cyDeviceInfoList[index].serialNum,   
   
     cyDeviceInfoList[index].manufacturerName,   
   
     cyDeviceInfoList[index].productName,   
   
     cyDeviceInfoList[index].deviceBlock,   
   
     cyDeviceInfoList[index].deviceType[0],   
   
     cyDeviceInfoList[index].deviceClass[0]);   
   
        
   
     // Find the device at device index at SCB0   
   
     if (cyDeviceInfoList[index].deviceBlock == SerialBlock_SCB0)   
   
     {   
   
     deviceIndexAtSCB0 = index;   
   
     }   
   
     }   
   
     return deviceIndexAtSCB0;   
   
    }   
   
        
   
    char *weekday[] =   
   
    {   
   
     "Sunday",   
   
     "Monday",   
   
     "Tuesday",   
   
     "Wednesday",   
   
     "Thursday",   
   
     "Friday",   
   
     "Saturday"   
   
    };   
   
        
   
    char *month[] =   
   
    {   
   
     "January",   
   
     "February",   
   
     "March",   
   
     "April",   
   
     "May",   
   
     "June",   
   
     "July",   
   
     "August",   
   
     "September",   
   
     "October",   
   
     "November",   
   
     "December"   
   
    };   
   
        
   
    /** ********************************   
   
    Application main() function   
   
    *** ******************************** */        
   
    int _tmain(int argc, _TCHAR* argv[])   
   
    {   
   
     //Assmumptions:   
   
     //1. SCB0 is configured as I2C    
   
        
   
     int deviceIndexAtSCB0 = FindDeviceAtSCB0();   
   
        
   
     //Open the device at deviceIndexAtSCB0   
   
     if (deviceIndexAtSCB0 >= 0)   
   
     {   
   
     //Assuming that device at index is I2C device   
   
     //Device Open, Close, Configuration, Data operations are handled in the function I2CMaster   
   
        
   
     cyReturnStatus = I2CMasterSetup(deviceIndexAtSCB0);   
   
     if (cyReturnStatus == CY_SUCCESS)   
   
     {   
   
     SYSTEMTIME localtime;   
   
     uchar time[16], tmp = 0;   
   
     char command;   
   
     printf("\nI2CMaster returned success.\n");   
   
        
   
     PCF8563_init();   
   
        
   
     printf("\nType s to set, r to reset, anything else to resume current time\n");   
   
     command = getch();   
   
     if (command == 's')   
   
     {   
   
     GetLocalTime(&localtime);   
   
     // 21 hours, 37 minutes, 30 seconds, day 6, weekday Friday(5), month 3, year 2015   
   
     PCF8563_setTime(localtime.wHour, localtime.wMinute, localtime.wSecond, localtime.wDay, localtime.wDayOfWeek, localtime.wMonth, localtime.wYear);   
   
     }   
   
     else if (command == 'r')   
   
     {   
   
     // 21 hours, 37 minutes, 30 seconds, day 6, weekday Friday(5), month 3, year 2015   
   
     PCF8563_setTime(23, 59, 30, 28, 6, 2, 2015);   
   
     }   
   
     while (1)   
   
     {   
   
     PCF8563_getTime(time);   
   
     if (time[0] != tmp)   
   
     {   
   
     uint year = time[5] > 80 ? 1900 : 2000;   
   
     year += time[6];   
   
     uint hour = ((time[2] % 12) == 0) ? 12 : time[2] % 12;   
   
     printf("%s, %s %d, %04d %02d:%02d:%02d %s\n", weekday[time[4]], month[((time[5] > 80) ? time[5] - 80 : time[5])-1], time[3], year, hour, time[1], time[0], (time[2]>11) ? "PM" : "AM");   
   
     }   
   
     tmp = time[0];   
   
     }   
   
     CyClose(cyHandle);   
   
     }   
   
     else   
   
     {   
   
     printf("\nI2CMaster returned failure code.\n");   
   
     }   
   
     } //cyNumDevices > 0 && cyReturnStatus == CY_SUCCESS   
   
     return 0;   
   
    }   
   
        
0 Likes
8 Replies
JoMe_264151
Expert II

Thank you *VERY* much for posting your experiences here and sharing them with us. What realy satisfied me was your last picture that showed me that not only my "PSoC bench" looks a bit like the Laokoon Group  but others as well (although the wires are thinner)

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Thanks,

   

I thought I shared because you can configure the PSoC4200 to have an I2C slave, so you can use the snap off board to communicate with the PSoC4200 via I2C or if you need higher speeds then use SPI

   

You can make custom programs with the USB-Serial Software Development Kit that supports not only Windows, but also Android, Linux and OSX.

   

So if you have a cool design based on the CY8CKIT-049 that needs to interact with the PC other than the COM port, or even via the COM port but with a dedicated program with graphics and everything, that little break off board is there for you 🙂

   

BTW the RTC module is running great, only lost one second in one day versus the PC that lost 5 seconds.

   

I did synchronized them both at the same time, well the PC first then the RTC based on the PC time.

   

0 Likes
JoMe_264151
Expert II

A small tip: you can save some of the precious sram when you write

   

char * const weekday[] =
                {
                    "Sunday",
                    "Monday",
                    "Tuesday",
                    "Wednesday",
                    "Thursday",
                    "Friday",
                    "Saturday"
                };
 
This will allocate the strings in flash.

   

 

   

Happy coding

   

Bob

0 Likes
Anonymous
Not applicable

 Thanks, but the code runs on the PC.

   

That's the beauty of that USB-Serial bridge, you can program the PSoC4 to deal with the hardware and communicate it back to the PC/Laptop/Tablet/etc via I2C/SPI/UART for the GUI via that break-off module hooked into your system that has plenty of resources.

0 Likes
ETRO_SSN583
Esteemed Contributor

If I am reading your Rigol screenshot correctly you have ~ 2V of

   

undershoot, would be a good idea to address that issue with

   

either diode clamps or layout.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Well spoted,

   

 

   

When I reset my scope, which doesn't happen often, it changes the multipliers for both channels to x1 and I have x10 probes.

   

Since I mainly use only CH1 I forgot to set CH2 (blue) to x10, so the 500mV is really 5V.

   

 

   

I should have taken better care for an image I was going to post. Also I should have use the ground springs to get rid off all that ringing that shows on the capture.

0 Likes
ETRO_SSN583
Esteemed Contributor

I assumed that the channel was 5V and the undershoot caught my attention,

   

fairly significant.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Great miguelvp, i want to try this project 😄

0 Likes