Cheap / Easy I2C Dev Kit? - Page 1
Forum section: electronics / general

author: katzohki
author_rank: Frequent Contributor
timestamp: February 23, 2015, 10:01:43 pm
content: Hi all, I'm looking for something that will help me do some simple I2C demonstration / testing. I don't really need to see a protocol / signal analysis, but ideally something "big picture." In my mind, something that would act as a master on the I2C side and a virtual COM port on the PC side would be good so that I can just open a terminal application (Hyper Terminal?) and send / receive data. I was looking at this, UMFT200XD-01, but I don't know if it appears as a master on I2C or exactly how to use it.

author: uChip
author_rank: Contributor
timestamp: February 23, 2015, 10:33:35 pm
content: This might not be what you want to hear, but a super cheap (<$10) easy I2C is to put a bare bones AVR or PIC on a breadboard and write a little code. Plenty of examples out there to get you started and expandable in any direction you would like.- Chip

author: katzohki
author_rank: Frequent Contributor
timestamp: February 23, 2015, 10:47:21 pm
content: Quote from: uChip on February 23, 2015, 10:33:35 pmI didn't think of that since the thing I want to test I2C on is a PIC in the first place, but I guess I could set up a second PIC with serial data in to I2C out.

author: DmitryL
author_rank: Regular Contributor
timestamp: February 23, 2015, 11:07:29 pm
content: Quote from: katzohki on February 23, 2015, 10:01:43 pmgoogle "bus pirate"

author: BlueBill
author_rank: Regular Contributor
timestamp: February 24, 2015, 12:50:38 am
content: Quote from: DmitryL on February 23, 2015, 11:07:29 pm+1Handy tool the bus pirate. It's also PIC based

author: westfw
author_rank: Super Contributor
timestamp: February 24, 2015, 03:51:10 am
content: Note that I2C devices usually have "addresses" and "commands" rather than something that translates easily to a character-oriented "virtual com port."

author: 22swg
author_rank: Frequent Contributor
timestamp: February 24, 2015, 10:23:57 am
content: I found I2C very frustrating to start with,(Bit banging with PIC16F84 –24LC265 EEPROM ) without having any sniffer to assist, Your “Big Picture” does not really exist, I2C is a standard rather than a protocol, other than the basic physical structure and bit sequences eg.. Start , address, R/W , ack ,nak, Stop etc . Control and data bytes are master / slave dependent you can transport anything , at any speed <1Mb this is what makes it so flexible. If you have a specific purpose for I2C then just check out some data sheets, most will have details of their communication requirements. Like below , an SSD1306 I2C OLED display. If you are building a microcontroller master / slave(s) system then you can design your own protocol...

author: katzohki
author_rank: Frequent Contributor
timestamp: February 24, 2015, 04:54:19 pm
content: I really say "big picture" because I want something that I can demo to management like "and if we send a command, the device responds accordingly..." But I do have some tools that I can use to look at the protocol if I need to as it is operating.

author: DmitryL
author_rank: Regular Contributor
timestamp: February 24, 2015, 05:13:08 pm
content: Quote from: katzohki on February 24, 2015, 04:54:19 pmgoogle "saleae logic analyser".Also, bus pirate can do simple I2c sniffing.

author: miguelvp
author_rank: Super Contributor
timestamp: February 24, 2015, 06:36:08 pm
content: The PSoC 4200 prototyping board ($4.00)http://www.cypress.com/?rID=92146Comes with a CY7C65211 configured in UART mode but can be detached and configured as I2C.You will need the USB Serial Software development kit (free but you might need to register to get it) and of course the drivers that they supply.More info on the Cypress USB-Serial device family can be found here:http://www.cypress.com/USBSerial/Edit: the chip itself (USB one not the 4200) is under $2 purchased from Cypress directly and here is where you can find the datasheet:http://www.cypress.com/?rID=82869

author: spudboy488
author_rank: Regular Contributor
timestamp: February 25, 2015, 12:33:56 pm
content: If you are going to demo something to management, I have the following suggestion. Get a PIC and put it on one end of a breadboard. Get an I2C I/O expander (such as a MCP23008 or MCP23017) and put a bunch of LEDs and switches on the expander and put it at the other end. Just have the 2 I2C wires going from the PIC to the expander (of course, common VCC and ground). Write some code to read some switches and blink some LEDs (management loves blinky lights). Emphasize that the expander is being controlled by only the 2 wires. That should help get your point across.

author: andy1
author_rank: Contributor
timestamp: February 25, 2015, 09:59:16 pm
content: Like said before Bus Pirate is almost exactly what you want, easily controllable trough the serial port with realterm etc. supports SPI and I2C and others, I have used it in many projects as a test device as it is really easy to just send some SPI or I2C and check stuff.

author: miguelvp
author_rank: Super Contributor
timestamp: February 26, 2015, 04:26:18 am
content: I wouldn't use the Cypress USB Serial Test program for the final implementation but you could write a program using WinUSB for the last two steps.Here is the setup of the breakoff part of the PSoC4100 prototype board with a CY7C65211-24LTXI single channel interface (CY7C65215 has dual channels, but not in this prototype board) Also I didn't want to break-off the one in the PSoC4200, but the USB-Serial part is the same for both $4 prototype boards.I have an RTC board that uses an NXP PCF8563 that uses I2C at 400KHzI already have all the software and drivers installed so I'm not going to go through that.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 ConfigureEdit: 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/rxSelected 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).Now, since I can't be bothered to write a WinUSB sample program, I just used the provided USB Serial Test Utility from Cypress, but you really wan't to write your own and talk to your VID/PID or search for your custom manufacturer and/or product string when enumerating USB devices.But this test utility will allow me to just read the RTC, Also I didn't bother to program this RTC so it's as it came from China because I never had time to play with it until now, but just wanted to see if I could read data from it using this USB-Serial chip.So I started the test utility and changed the Vendor ID and Product ID to what I programmed the chip with.Then clicked the Read & verify data, and of course the verify part didn't work but it displays what the RTC is sending at 400KHzThe bus pirate might have easier tools, but for the price ($4 plus you get to keep an Cortex M0 ARM processor) it's a good alternative, you can't even buy the chip and make your own board for the fraction of that break off board that comes with that prototyping board.Edit: You can also program the CapSense for capacitance touch, and unsused GPIOs mode on top of the Battery Charge Detect for battery powered devices.

author: miguelvp
author_rank: Super Contributor
timestamp: February 26, 2015, 05:08:53 am
content: Also in case you are curious about SPI and UART settings:

author: miguelvp
author_rank: Super Contributor
timestamp: February 26, 2015, 06:41:50 am
content: And I forgot one more thing, the schematic of the CY7C65211-24LTXI part of the prototype board:And the pins for I2C Master SCL_OUT and SDA go to pin 21 and 22, marked in the silk screen as SCB_2 and SCB_3 (pin 4 & pin 5 on J6 above).

author: jancumps
author_rank: Unknown
timestamp: February 26, 2015, 10:50:43 am
content: Check out this week's embedded.fm podcast. The guest has designed an i2c LED. That would be the simplest gizmo you can use in your showcase.Links are in the notes of this edition on the embedded site.

author: katzohki
author_rank: Frequent Contributor
timestamp: February 26, 2015, 06:26:45 pm
content: @ miguelvp:Wow, thank you! That is a lot of good info. Sounds like a good way to go.@jancumps:The target device is PIC which has an application running on it that will control our product. The idea is to demonstrate the "added capability" that I2C will provide our customers, not so much demonstrate I2C itself.

author: jancumps
author_rank: Unknown
timestamp: February 26, 2015, 06:43:37 pm
content: Quote from: katzohki on February 26, 2015, 06:26:45 pmYes, I see that now when I re-read your original post. I didn't get it the first time around.

author: DmitryL
author_rank: Regular Contributor
timestamp: February 26, 2015, 10:55:39 pm
content: Quote from: katzohki on February 26, 2015, 06:26:45 pmGoogle "managers power point bullshit"

author: katzohki
author_rank: Frequent Contributor
timestamp: February 26, 2015, 11:32:55 pm
content: Quote from: DmitryL on February 26, 2015, 10:55:39 pmlol. I once spent a good couple days preparing to defend my design to upper management (on my boss's advice) and instead spent the presentation being grilled on parts cost. It came out a win, since I was able to push through a fairly unique design somewhat under the radar.

author: miguelvp
author_rank: Super Contributor
timestamp: February 28, 2015, 07:01:50 am
content: Quote from: katzohki on February 26, 2015, 06:26:45 pmAlso FWIW they have a USB-Serial Software Development Kit that supports Windows, Linux/MAC & Android:http://www.cypress.com/?rID=83110I opened up the example project in windows, and requires Visual Studio 2008 or higher, since I have the free Visual Studio Community 2013 (full Visual Studio Professional 2013) I opened the solution and it upgraded the solution to VS2013The sample code has 5 projects:deviceenumerationgpioi2cmasterspimasteruartbut they also provide a pdf with the full documentation of the SDK.Not sure what the example software for Android, Linux/Mac have but they are free to download after a free sign-in to Cypress.Output of the deviceenumeration sampleCode:Displaying information about all devices binded to USB-Serial driver...Number of interfaces: 1Vid: 0x4B4Pid: 0x4Serial Number is:Manufacturer name: Cypress SemiconductorProduct Name: USB-Serial (Single Channel)SCB Number: 0x0Device Type: 3Device Class: 255Number of interfaces: 1Vid: 0x4B4Pid: 0x4Serial Number is:Manufacturer name: Cypress SemiconductorProduct Name: USB-Serial (Single Channel)SCB Number: 0x1Device Type: 5Device Class: 255Displaying information about all devices binded to USB-Serial driver with VID: 0x4B4, PID: 0xA...I would have to alter the i2cmaster example to drive the clock but it looks simple enough.Also it seems the SDK allows you to configure the chip on the fly, not sure if it will allow you to switch from I2C to UART to SPI but if in that mode it lets you modify the settings:Code:Opening I2C device with device number 0...I2C Open successfull. Invoking API for retrieving I2C configuration...I2C Frequency : 1000 , Slave address : 2Setting new I2C configuration...New Configuration - I2C Frequency : 400000 , Slave address : 96, isMaster : 1Setting new I2C configuration successful.Checking the new I2C configuration ...I2C Configuration retrieved - I2C Frequency : 400000 , Slave address : 96, isMaster : 1Performing I2C Read operation...Completed I2C read successfully. Read 2048 bytes of data.Edit: changed the configuration to 1KHz and a different slave address to show that it will change it to the new setting

author: miguelvp
author_rank: Super Contributor
timestamp: March 06, 2015, 06:52:29 pm
content: Last night I started to play with programming the I2C RTC and let me tell you that without a scope it's hard to say why things are not working the way they should.The RTC has a slave address at 0xA2 for wrtie and 0xA3 for read, the write is failing because the scope shows that is masking off bit 7 and trying to communicate with 0x22 instead. So others that have mentioned that I2C can be a pain, I agree. Without the scope I would still be scratching my head, but I can see the 0x22 clearly in the serial decoder.So the API that cypress is not allowing devices past 0x80 and the only way to communicate with it is by using the libusb directly. fortunately I have found old source for the cypress api that might help.

author: 22swg
author_rank: Frequent Contributor
timestamp: March 06, 2015, 09:22:57 pm
content: Most I2C 'start' code shifts the address << 1 so your RTC 0xA2 probably needs to be 0x51 .

author: miguelvp
author_rank: Super Contributor
timestamp: March 07, 2015, 04:01:21 am
content: Quote from: 22swg on March 06, 2015, 09:22:57 pmThanks, that did the trick, I shifted the slave address to the right by one bit and it's all working fine.I modified the circuit to have two 2.2KOhm pull up resistors needed for 400Kbps as per the USB-Serial datasheet.I did probe the SCL and SDA to make sure I was reading/writing the right data:And it workedHere is the altered code from their I2C eeprom sample with the sample 8051 code that came with the RTC board that only used the hour minutes and seconds and modified it to add day, month, year, century bit and weekday.The read is hardcoded to read 11 bytes but that can be changed easily to read an arbitrary number of bytes.Code:#include "stdafx.h"#include <stdio.h>#include <windows.h>#include <dbt.h>#include <conio.h>#include "..\..\..\library\inc\CyUSBSerial.h"/** ****************Data Definitions*** **************** */// Define VID & PID// These numbers depends on individual products#define VID 0x04B4#define PID 0x0004//Variable to store cyHandle of the selected deviceCY_HANDLE cyHandle;//Varible to capture return values from USB Serial APICY_RETURN_STATUS cyReturnStatus;//CY_DEVICE_INFO provides additional details of each device such as product Name, serial number etc..CY_DEVICE_INFO cyDeviceInfo, cyDeviceInfoList;//Structure to store VID & PID defined in CyUSBSerial.hCY_VID_PID cyVidPid;CY_I2C_DATA_CONFIG cyI2CRWDataConfig;CY_DATA_BUFFER cyDataRWBuffer;//Variables used by applicationUINT8 cyNumDevices;unsigned char deviceID;/** ****************Functions*** **************** */#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_BUF0x02#define MINUTE_DATA_BUF0x03#define HOUR_DATA_BUF0x04#define DAY_DATA_BUF0x05#define WEEK_DATA_BUF0x06#define MONTH_DATA_BUF0x07#define YEAR_DATA_BUF0x08#define MINUTE_AE_BUF0x09#define HOUR_AE_BUF0x0A#define DAY_AE_BUF0x0B#define WEEK_AE_BUF0x0C#define CLK_FRQ_BUF0x0D#define TIMER_CTRL_BUF0x0E#define COUNT_VAL_BUF0x0Ftypedef unsigned char uchar;typedef unsigned int uint;void WriteAByte(uchar wordAdr, uchar dat){uchar buffer;buffer = wordAdr;buffer = dat;cyDataRWBuffer.buffer = buffer;cyDataRWBuffer.length = 2;CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);//SMBus_Write(0xA2, wordAdr, dat, 2);}void ReadNByte(uchar wordAdr, uchar *pRdDat){cyDataRWBuffer.buffer = &wordAdr;cyDataRWBuffer.length = 1;CyI2cWrite(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);//SMBus_Write(0xA2, wordAdr, 0, 1);cyDataRWBuffer.buffer = pRdDat;cyDataRWBuffer.length = 11;CyI2cRead(cyHandle, &cyI2CRWDataConfig, &cyDataRWBuffer, 5000);//SMBus_Read(0xA3, pRdDat, 11);}void PCF8563_getTime(uchar *buf){ReadNByte(SECOND_DATA_BUF, buf);buf = buf & 0x7f;//get seconds databuf = buf & 0x7f;//get minutes databuf = buf & 0x3f;//get hours databuf = buf & 0x3f;//get days databuf = buf & 0x07;//get weekdays databuf = buf & 0x9f;//get century_months data (most significant bit Century bit 0=2000 1=1900)//buf = buf;//get years databuf = buf & 0xff;//get minutes_alarm databuf = buf & 0xaf;//get hours_alarm databuf = buf & 0xaf;//get days_alarm databuf = buf & 0x87;//get weekdays_alarm databuf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);}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 bitmonth |= 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 settingWriteAByte(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 datacyI2CRWDataConfig.isStopBit = true;cyI2CRWDataConfig.isNakBit = false;cyI2CRWDataConfig.slaveAddress = 0xA2 >> 1;// Configure the I2Cprintf("Opening I2C device with device number %d...\n", deviceNumber);//Open the device at deviceNumberrStatus = CyOpen(deviceNumber, interfaceNum, &cyHandle);if (rStatus != CY_SUCCESS){printf("I2C Device open failed...\n");return rStatus;}// Get configurationprintf("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 settingsprintf("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 I2Cprintf("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;}/*Function Name: int FindDeviceAtSCB0()Purpose: Demonstates how to enumerate and find device from the list of devices.- Demonstrates how to use deviceBlock member in DEVICE_INFO structureArguments: NoneRetrun Code: returns -1, if no device is present or deviceIndex of the device.*/int FindDeviceAtSCB0(){CY_VID_PID cyVidPid;cyVidPid.vid = VID; //Defined as macrocyVidPid.pid = PID; //Defined as macro//Array size of cyDeviceInfoList is 16cyReturnStatus = 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.numInterfaces,cyDeviceInfoList.vidPid.vid,cyDeviceInfoList.vidPid.pid,cyDeviceInfoList.serialNum,cyDeviceInfoList.manufacturerName,cyDeviceInfoList.productName,cyDeviceInfoList.deviceBlock,cyDeviceInfoList.deviceType,cyDeviceInfoList.deviceClass);// Find the device at device index at SCB0if (cyDeviceInfoList.deviceBlock == SerialBlock_SCB0){deviceIndexAtSCB0 = index;}}return deviceIndexAtSCB0;}/** ********************************Application main() function*** ******************************** */int _tmain(int argc, _TCHAR* argv[]){//Assmumptions://1. SCB0 is configured as I2Cint deviceIndexAtSCB0 = FindDeviceAtSCB0();//Open the device at deviceIndexAtSCB0if (deviceIndexAtSCB0 >= 0){//Assuming that device at index is I2C device//Device Open, Close, Configuration, Data operations are handled in the function I2CMastercyReturnStatus = I2CMasterSetup(deviceIndexAtSCB0);if (cyReturnStatus == CY_SUCCESS){uchar time, tmp = 0;printf("\nI2CMaster returned success.\n");PCF8563_init();// 9 hours, 37 minutes, 30 seconds, day 6, weekday Friday(5), month 3, year 2015PCF8563_setTime(9, 37, 30, 6, 5, 3, 2015);while (1){PCF8563_getTime(time);if (time != tmp){uint year = time > 80 ? 1900 : 2000;year += time;printf("%02d:%02d:%02d %02d/%02d/%04d\n", time, time, time, time, (time > 80) ? time - 80: time , year);}tmp = time;}CyClose(cyHandle);}else{printf("\nI2CMaster returned failure code.\n");}} //cyNumDevices > 0 && cyReturnStatus == CY_SUCCESSreturn 0;}It actually wasn't that painful after all, the only thing I was missing is that the slave address is shifted and the read/write bit is appended by the CyI2cWrite and CyI2cRead calls.

author: miguelvp
author_rank: Super Contributor
timestamp: March 07, 2015, 06:13:44 am
content: Made some changes to get the time set from the systems time by pressing 's' at startup.'r' at startup resets to 30 seconds before midnight on February 28th 2015 to see if it can handle leap years (and it does as seen in this screen capture)Any other key will use the time set in the RTC, I did move the jumper in the board so it uses the battery to backup the time.I didn't implement any of the alarm set and looking at the control status 2 for AF to check the alarm that stays on until cleared.Also I didn't implement the timer countdown and control nor the CLKOUT control, but pretty much all the bases to program and read the RTC via I2C is in here.Edit: also if AF is set and the alarm is enabled, the INT_n will trigger at a specified clock setting based on the control status flags.Code:#include "stdafx.h"#include <stdio.h>#include <windows.h>#include <dbt.h>#include <conio.h>#include "..\..\..\library\inc\CyUSBSerial.h"/** ****************Data Definitions*** **************** */// Define VID & PID// These numbers depends on individual products#define VID 0x04B4#define PID 0x0004//Variable to store cyHandle of the selected deviceCY_HANDLE cyHandle;//Varible to capture return values from USB Serial APICY_RETURN_STATUS cyReturnStatus;//CY_DEVICE_INFO provides additional details of each device such as product Name, serial number etc..CY_DEVICE_INFO cyDeviceInfo, cyDeviceInfoList;//Structure to store VID & PID defined in CyUSBSerial.hCY_VID_PID cyVidPid;CY_I2C_DATA_CONFIG cyI2CRWDataConfig;CY_DATA_BUFFER cyDataRWBuffer;//Variables used by applicationUINT8 cyNumDevices;unsigned char deviceID;/** ****************Functions*** **************** */#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_BUF10x00#define CTRL_BUF20x01#define SECOND_DATA_BUF0x02#define MINUTE_DATA_BUF0x03#define HOUR_DATA_BUF0x04#define DAY_DATA_BUF0x05#define WEEK_DATA_BUF0x06#define MONTH_DATA_BUF0x07#define YEAR_DATA_BUF0x08#define MINUTE_AE_BUF0x09#define HOUR_AE_BUF0x0A#define DAY_AE_BUF0x0B#define WEEK_AE_BUF0x0C#define CLK_FRQ_BUF0x0D#define TIMER_CTRL_BUF0x0E#define COUNT_VAL_BUF0x0Ftypedef unsigned char uchar;typedef unsigned int uint;void WriteAByte(uchar wordAdr, uchar dat){uchar buffer;buffer = wordAdr;buffer = 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 = buf & 0x7f;//get second databuf = buf & 0x7f;//get minute databuf = buf & 0x3f;//get hour databuf = buf & 0x3f;//get day databuf = buf & 0x07;//get weekday databuf = buf & 0x9f;//get century_month data (most significant bit Century bit 0=2000 1=1900)//buf = buf;//get year databuf = buf & 0xff;//get minute_alarm databuf = buf & 0xaf;//get hour_alarm databuf = buf & 0xaf;//get day_alarm databuf = buf & 0x87;//get weekday_alarm databuf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);buf = converseIntToHex(buf);}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 bitmonth |= 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 settingWriteAByte(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 datacyI2CRWDataConfig.isStopBit = true;cyI2CRWDataConfig.isNakBit = false;cyI2CRWDataConfig.slaveAddress = 0xA2 >> 1;// Configure the I2Cprintf("Opening I2C device with device number %d...\n", deviceNumber);//Open the device at deviceNumberrStatus = CyOpen(deviceNumber, interfaceNum, &cyHandle);if (rStatus != CY_SUCCESS){printf("I2C Device open failed...\n");return rStatus;}// Get configurationprintf("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 settingsprintf("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 I2Cprintf("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;}/*Function Name: int FindDeviceAtSCB0()Purpose: Demonstates how to enumerate and find device from the list of devices.- Demonstrates how to use deviceBlock member in DEVICE_INFO structureArguments: NoneRetrun Code: returns -1, if no device is present or deviceIndex of the device.*/int FindDeviceAtSCB0(){CY_VID_PID cyVidPid;cyVidPid.vid = VID; //Defined as macrocyVidPid.pid = PID; //Defined as macro//Array size of cyDeviceInfoList is 16cyReturnStatus = 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.numInterfaces,cyDeviceInfoList.vidPid.vid,cyDeviceInfoList.vidPid.pid,cyDeviceInfoList.serialNum,cyDeviceInfoList.manufacturerName,cyDeviceInfoList.productName,cyDeviceInfoList.deviceBlock,cyDeviceInfoList.deviceType,cyDeviceInfoList.deviceClass);// Find the device at device index at SCB0if (cyDeviceInfoList.deviceBlock == SerialBlock_SCB0){deviceIndexAtSCB0 = index;}}return deviceIndexAtSCB0;}char *weekday[] ={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};/** ********************************Application main() function*** ******************************** */int _tmain(int argc, _TCHAR* argv[]){//Assmumptions://1. SCB0 is configured as I2Cint deviceIndexAtSCB0 = FindDeviceAtSCB0();//Open the device at deviceIndexAtSCB0if (deviceIndexAtSCB0 >= 0){//Assuming that device at index is I2C device//Device Open, Close, Configuration, Data operations are handled in the function I2CMastercyReturnStatus = I2CMasterSetup(deviceIndexAtSCB0);if (cyReturnStatus == CY_SUCCESS){SYSTEMTIME localtime;uchar time, 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);PCF8563_setTime(localtime.wHour, localtime.wMinute, localtime.wSecond, localtime.wDay, localtime.wDayOfWeek, localtime.wMonth, localtime.wYear);}else if (command == 'r'){// 23 hours, 59 minutes, 30 seconds, day 28, weekday Saturday(6), month 2, year 2015PCF8563_setTime(23, 59, 30, 28, 6, 2, 2015);}while (1){PCF8563_getTime(time);if (time != tmp){uint year = time > 80 ? 1900 : 2000;year += time;uint hour = ((time % 12) == 0) ? 12 : time % 12;printf("%-9s %02d:%02d:%02d %s %02d/%02d/%04d\n", weekday[time], hour, time, time, (time>11) ? "PM" : "AM", time, (time > 80) ? time - 80 : time, year);}tmp = time;}CyClose(cyHandle);}else{printf("\nI2CMaster returned failure code.\n");}} //cyNumDevices > 0 && cyReturnStatus == CY_SUCCESSreturn 0;}

author: miguelvp
author_rank: Super Contributor
timestamp: March 09, 2015, 10:30:33 am
content: After over 24 hours since I synced both my computer and the RTC after our hour change here in the US, I tested it this morning to see how much it drifted.I had the module unplugged so the time was being kept by the battery.Only 1 second compared to the PC that fell behind 5 seconds in about 26 hours (I thought it was 27 but we lost one).Oh, of course I modified the time format to our odd way to tell time