AN-1367 APPLICATION NOTE One Technology Way • P.O. Box 9106 • Norwood, MA 02062-9106, U.S.A. • Tel: 781.329.4700 • Fax: 781.461.3113 • www.analog.com I2C Interface Between the ADE7953 and the ADuCM360 by Fermi Lim, Daniel Kim, and Hariharan Mani INTRODUCTION This application note demonstrates the implementation of an I2C interface between the ADE7953 (the slave) and the ADuCM360 (the master), using C programming language. The ADE7953 is a single-phase energy metering IC, and the ADuCM360 is an ARM® Cortex®-M3-based microcontroller. The ADE7953 contains registers that are 8, 16, 24, or 32 bits long. While writing the source code, it is important to make sure that the data size for the read/write operation is identified based on the address of the register. The register list in the ADE7953 data sheet contains all the relevant information. This application note introduces the ARM Cortex-M3 core and the ADuCM360 microcontroller unit (MCU), followed by the initialization steps that need to be completed within the ADuCM360, and finally the implementation of the I2C interface between the ADE7953 and the ADuCM360. The sample codes described in this application note can also be used for other Analog Devices, Inc., processors that are based on the ARM Cortex-M core. The complete source code for establishing the I2C interface is available as a downloadable file, AN_1367_I2C_interface.zip, at www.analog.com/ADE7953 or www.analogcom/ADuCM360. I2C To validate the source code, the following equipment and software were used: ADE7953 and ADuCM360 evaluation module boards (EVMs) Software development environment: Keil MDK-ARM Version 4.72 Terminal emulator: Tera Term Version 4.79 IDE: Visual C++ 2012 Laptop personal computer (PC) The entire lab setup is shown in Figure 1. The two evaluation boards are connected with the help of wires, as shown in Figure 2. Because an isolation interface was not considered for this setup, both boards are powered by a common supply voltage and share a common ground. If isolating the I2C interface, the propagation delay of the isolators must be taken into account. EVAL-ADuCM360 1, 2, 3, OR 4 BYTES INTERNAL REGISTER ACCESS USB TO UART (Cortex-M3) 13338-001 EVAL-ADE7953 This application note describes how to implement the source code in the Visual C++ 2012 integrated development environment (IDE), and provides useful insight regarding the I2C communication ports of the ADE7953 and the ADuCM360. Figure 1. Lab Setup Rev. 0 | Page 1 of 15 AN-1367 Application Note TABLE OF CONTENTS Introduction ...................................................................................... 1 Initializing the ADuCM360 for UART and I2C.............................8 Revision History ............................................................................... 2 I2C Interface: ADuCM360 and ADE7953 ................................... 10 Setup Description ............................................................................. 3 Simulating an Embedded C Code Using Visual C++ ........... 12 ARM Cortex-M3 Core and ADuCM360 MCU ........................... 5 Conclusion....................................................................................... 15 REVISION HISTORY 9/15—Revision 0: Initial Version Rev. 0 | Page 2 of 15 Application Note AN-1367 SETUP DESCRIPTION The terminal emulator software, Tera Term Version 4.79, is used to read from or write to any of the ADE7953 registers through the ADuCM360. The universal asynchronous receiver/transmitter (UART) communication interface is used between the ADuCM360 and the PC to send and receive the read/write commands and data. The Tera Term Version 4.79 software, including examples of complete source code for the UART interface-based communication, is available for free from various sources, including the OSDN Corporation. Figure 3 shows the terminal window where the get and set commands of the example code are used to access the ADE7953 registers. The syntax for the two commands are • Set REG_ADDR value The set command writes the register located at Address REG_ADDR with a specific value. Get START_REG_ADDR REGISTER_NUMBER The get command reads the contents of the registers starting from Address START_REG_ADDR continuously starting from REGISTER_NUMBER. The number of register locations to be read is determined by REGISTER_NUMBER. • The uniqueness of the source code is that it allows the PC to communicate with the ADE7953 even without the knowledge of the data size of each of the registers, because the register lookup table is already implemented. CONNECTOR OF ADuCM360 EVM DIGITAL PORT PINS SDA SCL RESET CONNECTOR OF ADE7953 EVM GND Figure 2. Connection Between ADuCM360 EVM and ADE7953 EVM Rev. 0 | Page 3 of 15 13338-002 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 VDD ZX_ISO MOSI_ISO RESET_ISO CS_ISO SCLK_ISO TX_ISO SDA_ISO MCU_VDD SCLK_ISO IRQ_ISO RX_ISO ZX_I_ISO MISO_ISO REVP_ISO NC15 NC16 NC17 VDDOUT 5VUSB J1-24 J1-23 J1-22 J1-21 J1-20 J1-19 J1-18 J1-17 J1-16 J1-15 J1-14 J1-13 J1-12 J1-11 J1-10 J1-9 J1-8 J1-7 J1-6 J1-5 J1-4 J1-3 J1-2 J1-1 P7 RESET P2.2/BM P2.1 P2.0 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1/IRQ4 P1.0 P0.7/SOUT P0.6/SIN P0.5 P0.4 P0.3/SS1 P0.2/MOSI P0.1/SCLK1 P0.0/MISO1 DVDD AN-1367 Application Note ADDRESSES OF ADE7953 13338-003 REGISTER VALUES OF ADE7953 13338-104 Figure 3. Terminal Window Showing the Use of Get Command Figure 4. Terminal Window Showing the Use of Get and Set Commands Rev. 0 | Page 4 of 15 Application Note AN-1367 ARM CORTEX-M3 CORE AND ADUCM360 MCU The ARM Cortex-M3 core is based on the ARMv7-M architecture. The Cortex-M family is used primarily in the embedded market, in applications requiring a core clock frequency of less than 300 MHz. Most of the embedded applications such as ac motor control and other simple home appliances do not need any sophisticated features such as a memory management unit (MMU) and NEON™, thus making the Cortex-M family a good choice. The architecture of the Cortex-M core is simpler than other Cortex families. Cortex-M family of cores include the following unique features: A fixed memory map A common nested vectored interrupt controller (NVIC) Thumb®-2 instruction set support only The code written for one Cortex-M family MCU can be easily modified to use with another Cortex-M family MCU, even if it is from another vendor. Furthermore, ARM provides useful Cortex Microcontroller Software Interface Standard (CMSIS) software for various applications, for free. Figure 5 compares a fixed memory map of the Cortex-M family core with that of the ADuCM360. As shown in Figure 5, the ADuCM360 includes 8 kB SRAM and 128 kB Flash/EE memory based on a fixed memory map for the Cortex-M family. All of the ADuCM360 peripherals are mapped into the 0x40000000 to 0x4004FFFF address range. The address range of 0xE000E000 to 0xE000EE000 is for the Cortex-M core memory mapped registers (MMRs); the 0x40000000 to 0x4004FFFF address range is for the ADuCM360 MMRs. 511MB VENDOR SPECIFIC MEMORY 0xE000EF00 0xE000E100 1MB PRIVATE PERIPHERAL BUS NVIC 1GB The Cortex-M family of cores has only one core interrupt, whereas older ARM cores have a fast interrupt as well as a normal interrupt. Two sets of registers are available: interrupt set enable registers (ISERs) and interrupt clear enable registers (ICERs). Usually, peripherals such as UART and I2C have their own registers to enable/disable the interrupts. Only one of the interrupts transferred by each peripheral can reach the core according to the ISER/ICER values. The ISERs are located in the 0xE000E100 to 0xE000E13C address range, and ICERs are located in the 0xE000E180 to 0xE000E1BC address range. When a Cortex-M family MCU is used, modify ISERs and ICERs as needed. Of all available IDE tools, Keil MDK-ARM and IAR Embedded Workbench® are the most popular. Both these tools can be used when the executable image is within the specified size limitations. The Keil MDK-ARM IDE was used in the lab setup for this application note. To use the code with the IAR Embedded Workbench IDE, the ADuCM360StartUp.s file, from the downloadable file, AN_1367_I2C_interface.zip, must be changed. When changing the IDE from Keil MDK-ARM to IAR Embedded Workbench, or vice versa, only the assembler directives have to be modified and not the instructions, because the assembler directives depend on the assembler being used and the instruction set depends on the MCU core. 0xFFFFFFFF 0xE0100000 0xE00FFFFF 0xE0000000 0xDFFFFFFF ADuCM360 MEMORY MAP MMRs 0xE000EE00 0xE000E000 EXTERNAL DEVICE 0xA0000000 0x9FFFFFFF 1GB EXTERNAL RAM 0x34FFFFFF 0x42000000 BIT BAND ALIAS 32MB 0x400FFFFF 0x40000000 BIT BAND REGION 0x60000000 0x6FFFFFFF 0.5GB 0x23FFFFFF 0x22000000 0x40000000 0x3FFFFFFF 0.5GB BIT BAND ALIAS 0x20000000 BIT BAND REGION 1MB 8kB SRAM SRAM 32MB 0x200FFFFF MMRs PERIPHERALS 1MB 0x20000000 0x1FFFFFFF 0.5GB CODE 0x00000000 KERNEL SPACE 128kB FLASH/ EE MEMORY 0x4004FFFF 0x40000000 0x20001FFF 0x20000000 0x000207FF 0x00020000 0x0001FFFF 0x0000E000 Figure 5. Memory Map Comparison Between Cortex-M and the ADuCM360 Rev. 0 | Page 5 of 15 13338-005 Note the following regarding the NVIC: AN-1367 Application Note Figure 8 shows the architecture of the ADuCM360. Among the peripherals of the ADuCM360, only the I2C, UART, and GPIOs are used to communicate with the ADE7953 and the PC. Figure 6 and Figure 7 shows the tool chains of the Keil MDKARM and IAR Embedded Workbench IDE, respectively. In Figure 6, armcc, armasm, and armlink are displayed in shaded gray to indicate that they form the C/C++ compiler, assembler, and linker, respectively. Similarly, in Figure 7, iccarm, iasmarm, and ilinkarm are indicated in shaded gray to denote that they are the compiler, assembler, and linker, respectively. First, configure UART to communicate with PC, and then configure the I2C to interface with the ADE7953. Though the focus of this application note is the I2C interface, the sample codes provided in the downloadable file, AN_1367_I2C_interface.zip, have modules for UART interface as well as GPIO usage. LINEAR ASSEMBLY (*.s/*.asm) C SOURCE FILES (*.c) LINKER SCRIPT (*.sct) C COMPILER (armcc) ASSEMBLER (armasm) LIBRARY BUILD UTILITY OBJECT FILES (*.o) OBJECT FILES (*.o) RUN-TIME SUPPORT LIBRARY (*.lib) --scatter CROSSREFERENCE LISTER (*.lst) --list IMAGE MAP FILE (*.map) --map LINKER (armlink) EXECUTABLE IMAGE FILE (*.axf/*.elf) TARGET BOARD HEX CONVERSION UTILITY (fromelf) HEX FILES (*.hex) 13338-006 DISASSEMBLED FILE --asm (*.s) Figure 6. Keil MDK-ARM Tool Chain C SOURCE FILES (*.c) LINKER SCRIPT (*.icf) CROSSREFERENCE LISTER (*.lst) IMAGE MAP FILE (*.map) C COMPILER (iccarm) ASSEMBLER (iasmarm) LIBRARY BUILD UTILITY OBJECT FILES (*.o) OBJECT FILES (*.o) RUN-TIME SUPPORT LIBRARY (*.a) LINKER (ilinkarm) EXECUTABLE IMAGE FILE (*.out) TARGET BOARD HEX CONVERSION UTILITY (ielftool) HEX FILES (*.hex) Figure 7. IAR Embedded Workbench Tool Chain Rev. 0 | Page 6 of 15 13338-107 DISASSEMBLED FILE (*.s) LINEAR ASSEMBLY (*.s/*.asm) Application Note DAC AVDD AGND AN-1367 ON-CHIP 1.8V ANALOG LDO 12-BIT DAC BUFFER AMP BUF MOD2 GAIN VREF 24-BIT Σ-Δ ADC Σ-Δ MODULATOR SINC3/ SINC4 FILTER AIN6/IEXC AIN8/EXTREF2IN– AIN9/DACBUFF+ AIN10 AIN11/VBIAS1 POWER-ON RESET RESET VBIAS GENERATOR AIN0 AIN1 AIN2 AIN3 AIN4/IEXC AIN5/IEXC AIN7/VBIAS0/IEXC/ EXTREF2IN+ ON-CHIP 1.8V DIGITAL LDO SINC2 FILTER MUX VREF AMP BUF MOD2 GAIN 24-BIT Σ-Δ ADC SINC3/ SINC4 FILTER Σ-Δ MODULATOR ON-CHIP OSCILLATOR (1% TYP) 16MHz ARM CORTEX-M3 PROCESSOR 16MHz GPIO PORTS UART PORTS 2 × SPI PORTS I2C PORTS MEMORY 128kB FLASH 8kB SRAM TIMER0 TIMER1 WATCHDOG WAKE-UP TIMER PWM DMA AND INTERRUPT CONTROLLER SERIAL WIRE DEBUG, PROGRAMMING AND DEBUG SELECTABLE VREF SOURCES DAC, TEMP, IOVDD/4, AVDD/4 XTALO XTALI 19 GENERALPURPOSE I/O PORTS SWDIO SWCLK PRECISION REFERENCE ADuCM360 DVDD_REG BUFFER CURRENT SOURCES AVDD_REG BUFFER GND_SW VREF– VREF+ INT_REF Figure 8. ADuCM360 Block Diagram Rev. 0 | Page 7 of 15 IOVDD IOVDD 13338-007 IREF AN-1367 Application Note INITIALIZING THE ADUCM360 FOR UART AND I2C I2CCLK. This is true for all peripherals whose clock can be divided by CLKCON1. If the peripheral clock is slower, the clock to the peripheral is gated and the peripheral does not work. For more information, refer to the ADuCM360/ ADuCM361 Hardware User Guide. When developing any embedded C code, first disable the watchdog timer, and then configure the clock for the core and peripherals as needed. After any reset operation, the watchdog timer is enabled automatically. To disable the watchdog timer of the ADuCM360, write 0’b0 to T3CON[5], the watchdog timer enable bit. As shown in Figure 9, the UART interface with the PC is set up with a baud rate of 115,200 bps. Therefore, configure the Tera Term tool accordingly as well. Refer to the project file of Tera Term named ‘MyTera_Setup2014.INI’, which is available from the downloadable file, AN_1367_I2C_interface.zip. // Step 1. Disable the watchdog timer. *pT3CON=0x0; Next, configure the clocks for the UART, I2C, and the Cortex-M3 core. Figure 9 and Figure 10 show how to configure the clocks for the UART and I2C. Configure the core clock as 16 MHz, and then set the control registers of the UART and the I2C interface accordingly. When selecting the I2C system clock divide ratio via CLKCON1, ensure that the core clock frequency is less than or equal to that of the I2C system clock, that is, HCLK ≤ 16MHz CLKSYSDIV[0] UCLK 16MHz 115200bps CLKCON1[11:9] 16MHz DISUARTCLK = 0 DIV2EN = 0 HOST PC CLKDIS[3] UCLK/1 = 000 BAUDRATE = UCLK/DIV/(2 × 16 × COMDIV)/(M + N/2048) COMDIV = 2 UARTCLK = 16MHz UCLK/DIV = UARTCLK M = 2, N = 348 COMLCR = 0x0003 13338-008 HFOSC To use the Tera Term project file, select the Restore setup option from the Setup menu, as shown in Figure 11. Next, select the MyTera_Setup2014.INI project file from the location saved on the PC. COMFBR = 0x915C Figure 9. Clock Configuration for UART 16MHz CLKSYSDIV[0] UCLK 16MHz DIV2EN = 0 100kHz 400kHz SCL CLKCON1[8:6] = 0 16MHz DISI2CCLK = 0 UCLK/1 = 000 BAUDRATE = UCLK/DIV/(2 × 16 × COMDIV)/(M + N/2048) 100kHz → I2CDIV = 0x4E4F 400kHz → I2CDIV = 0x1213 I2CCLK = 16MHz UCLK/DIV = I2CCLK Figure 10. Clock Configuration for I2C 13338-010 I2C SLAVE CLKDIS[2] = 0 Figure 11. Tera Term Configuration Rev. 0 | Page 8 of 15 13338-009 HFOSC Application Note AN-1367 The following C code instructions, which are extracted from the ADuCM360_I2C_AppNote.c file (from the downloadable file, AN_1367_I2C_interface.zip), show how to configure the UART interface. All the variables in the code denote MMRs related to the clock, GPIOs, and UART. // Step 2. Configure clocks. // UART speed rate is 115,200 bps: UCLK/DIV = 16 MHz. Next, initialize the I2C peripheral of the ADuCM360. The ADE7953 is always the slave and, therefore, the ADuCM360 must be configured as the master. As a master, the I2C modes available in the ADuCM360 include • • *pCLKDIS=0x03F7; *pCLKSYSDIV=0x00; *pCLKCON0=0x0000; The generation method of SCL in standard mode is shown in Figure 12. *pCLKCON1=0x0000; fI2CCLK = 16MHz // Step 3. Set up the behavior of the chosen UART. *pCOMCON=0x00; enabling. Standard mode: 100 kHz First set CLKSYSDIV[0] = 0, CLKCON1[8:6] = 000 and then then set I2CDIV[15:8] = 0x4E, I2CDIV[7:0] = 0x4F Fast mode: 400 kHz First set CLKSYSDIV[0] = 0, CLKCON1[8:6] = 000 and then set I2CDIV[15:8] = 0x12, I2CDIV[7:0] = 0x13 NEED_HIGH_TIME/fI2CCLK – 2 1 // UART peripheral is 15 I2CDIV NEED_LOW_TIME/fI2CCLK – 1 8 7 0 HIGH (0x4E) LOW (0x4F) 5µs 5µs 2 // P0.2 is UART Tx; P0.1 is UART Rx. *pGP0CON=0x003C; // COMDIV = 2; *pCOMFBR=0x915C; // Set to 115,200 bps SCL 10µs = 100kHz // WordLength = 8 bits, stop bit = 1 bit, no parity check. *pCOMLCR=0x0003; // COMTX and COMRX are enabled; COMIEN[1] = COMIEN[0] = 1 Figure 12. Generation Method of Standard 100 kHz SCL As shown in Figure 10 and Figure 12, fI2CCLK is 16 MHz, and if CLKSYSDIV[0] = 0 and CLKCON1[8:6] = 0 are initialized, the SCL bit rate, fSCL, is calculated using the following formula: f SCL = *pCOMIEN=0x0003; The interrupt enable register for the UART, COMIEN, is for UART peripheral interrupts only (see the ADuCM360/ADuCM361 Hardware User Guide for more information). For the UART transmitter (Tx)/receiver (Rx) interrupts to be transferred to Cortex-M3 core, set the corresponding ISER, as follows: // ISER = 0xE000E100; enabling UART interrupt. write_reg(0xE000E100,0x00020000); It is important to differentiate between an interrupt and an exception. An exception can be classified as synchronous or asynchronous. Any system fault can generally be called a synchronous exception, whereas an interrupt is an asynchronous exception. The UART is located in the 17th position in the interrupt vector table of the ADuCM360. Therefore, to enable the UART interrupt, set the 0xE000E100 address location of the ISER as 0x00020000. Similarly, to enable the I2C interrupts, set the ISER as follows: OldRegVal=read_reg(0xE000E100); RegVal = OldRegVal | 0x00200000; // for I2C write_reg(0xE000E100,RegVal); 0xE000E100; //ISER = 13338-011 *pCOMDIV=0x0002; f I 2CCLK [Hz] (Low + High + 3) where: Low is the low period of SCL, which is set by I2CDIV[7:0]. High is the high period of SCL, which is set by I2CDIV[15:8]. In standard mode, I2CDIV[7:0] is set as 0x4F (0d'78) and I2CDIV[15:8] is set as 0x4E (0d’79). Using these values, 100 kHz is obtained as the SCL clock rate. To use this code with Visual C++, the following piece of instructions was added: #ifdef FermiEmulation_Mode //to initialize all of the ADuCM360 register set. ADuCM360_RegsInit(); #endif For more information about this sample code, see the I2C Interface: ADuCM360 and ADE7953 section. This sample code is based on the super loop architecture. Therefore, this code style cannot handle multiple tasks. The use of menus via the Tera Term tool allows any graphic user interface (GUI) component to be implemented easily with Visual C++ or Visual Basic. Most of factory automation systems use this approach. Rev. 0 | Page 9 of 15 AN-1367 Application Note I2C INTERFACE: ADUCM360 AND ADE7953 An I2C interface is implemented using two pins, SCL and SDA. (Note that, throughout this section, multifunction pins, such as P2.0/SCL/UARTCLK, are referred to by a single function, for example, SCL, when only that function is relevant.) • The I2C interface of the ADuCM360 has a 2-byte Tx and Rx FIFO scheme, as shown in Figure 13. 2 SCL: serial clock pin. Only the master can generate the I C clock; SCL can be used in either standard mode or fast mode. SDA: serial data pin. The core clock and peripheral clock are usually different. If data in one clock domain is transferred into the other clock domain, metastability can occur leading to error in communication. To avoid metastability, it is common to use a FIFO or dual-port RAM. Metastability cannot be resolved by the use of combinational logic. Both SCL and SDA are bidirectional and must be connected to a positive supply voltage using a pull-up resistor. Although, SCL is generated by the ADuCM360 in this case, in theory, it can be bidirectional because the I2C interface of the ADuCM360 can be set as a slave. The I2C interface of the ADE7953 can only be used as a slave. TXFSTA (I2CMSTA[1:0]) TXREQ (I2CMSTA[2]) I2CMTX Note that the ADE7953 requires a minimum delay of 0.1 µs between the SCL and SDA edges; see the tHD;DAT specification in the data sheet. The ADE7953 data sheet also lists other timing specifications that must be maintained. FIFO FIFO 8 BITS 8 BITS FIFO FIFO IENTX (I2CMCON[5]) TSR IENTX (I2CSCON[10]) I2CSTX TXREQ (I2CSSTA[2]) TXFSEREQ (I2CSSTA[0]) Figure 14 shows a typical I2C transfer sequence. I2C TRANSMIT PATH The ADuCM360 has two I2C interfaces: one via the P0.1/ SCLK1/SCL/SIN and P0.2/MOSI1/SDA/SOUT pins and the other via the P2.0/SCL/UARTCLK and P2.1/SDA/UARTDCD pins. For this example, the P2.0/SCL/UARTCLK and P2.1/SDA/UARTDCD pins are used. RXREQ (I2CMSTA[3]) I2CMRX FIFO FIFO 8 BITS 8 BITS FIFO // P2.0/SCL/UARTCLK is used for SCL, P2.1/SDA/UARTDCD is used for SDA. IENRX (I2CMCON[4]) RSR IENRX (I1CSCON[9]) FIFO I2CSRX RXREQ (I2CSSTA[3]) *pGP2CON |= 0x05; // Master Enable, Tx/Rx Request Interrupt Enable. I2C RECEIVE PATH 13338-013 • The I2C addressing type can be either 7-bit or 10-bit. Due to the addressing type of the ADE7953, 7-bit addressing is used in this case. Figure 13. Datapath of I2C Tx/Rx *pI2CMCON = 0x131; Every slave has an address for I2C operation and a master can identify a slave using this address, which is set by the vendor. For example, the ADE7953 address is 0x38. MSB LSB SLAVE ADDRESS SCL MSB LSB R/W DATA 3 TO 6 1 START BIT 2 2 TO 7 7 8 9 ACK BIT Figure 14. Typical I2C Transfer Sequence Rev. 0 | Page 10 of 15 1 8 9 ACK BIT STOP BIT 13338-012 SDA Application Note AN-1367 15 8 7 0 VALUE (SLAVE ADDRESS R/W RESERVED MSB I2CADR0 LSB SDA SLAVE ADDRESS SCL R/W 3 TO 6 2 7 8 9 START BIT 13338-014 1 ACK BIT 15 8 7 0 23 16 15 8 7 0 7 STOP START Figure 15. 7-Bit Addressing Mode 0 SLAVE ADDRESS P A C K MSB OF REGISTER ADDRESS A C K A C K LSB OF REGISTER ADDRESS BYTE 3 (MSB) OF REGISTER A C K BYTE 2 OF REGISTER A C K BYTE 1 OF REGISTER A C K BYTE 0 (LSB) OF REGISTER A C K 13338-015 READ/WRITE S 0 1 1 1 0 0 0 0 ACK GENERATED BY ADE7953 START Figure 16. I2C Write Sequence of the ADE7953 15 0 1 1 1 0 0 0 SLAVE ADDRESS 8 7 0 0 A A A C MSB OF REGISTER ADDRESS C LSB OF REGISTER ADDRESS C K K K READ/WRITE S ACK GENERATED BY ADE7953 1 1 1 0 0 SLAVE ADDRESS 0 16 A C 15 K 8 A C K 7 0 A C K 7 0 1 P A C K BYTE 3 (MSB) OF REGISTER BYTE 2 OF REGISTER BYTE 1 OF REGISTER BYTE 0 (LSB) OF REGISTER 13338-016 0 READ/WRITE S 23 STOP START ACK GENERATED BY MASTER ACK GENERATED BY ADE7953 Figure 17. I2C Read Sequence of the ADE7953 Figure 15 shows how the master sends the 7-bit address (Bits[7:1]) and the directional (read or write) bit (Bit 0) to the slave. The I2CADR0 register stores the slave address and the directional bit. The I2C interface of the ADE7953 operates at a maximum serial clock frequency of 400 kHz. The I2C write and read operations of the ADE7953 are shown in Figure 16 and Figure 17, respectively. The ADE7953 I2C address is 0b'0111000x, where x is a directional bit. A 0 indicates a write, and a 1 indicates a read. A write operation on the ADE7953 is initiated when the master issues a 7-bit device address and the directional bit is set to 0 (that is, 0x70). It is then followed by the 16-bit address of an internal register. Whenever each byte is received, the ADE7953 issues an acknowledge to the master. Following that, the master sends the register data, MSB first. The length of this data can be 8, 16, 24, or 32 bits long, depending on the register. When transmission of the final byte is complete, the master issues a stop condition, and the bus returns to the idle condition. Rev. 0 | Page 11 of 15 AN-1367 Application Note When writing source code, it is essential to understand how the I2C is implemented in the target device. The following piece of code represents the ADE7953 I2C write operation: void I2C_Write_ADE7953(void) { int i=0; assigned by the MMU of the operating system (OS). The virtual addresses may change when the program is run. The Cortex-M family microcontrollers do not include a MMU; therefore, a MCU based on the Cortex-M core cannot be ported to, for example, Windows® CE or Linux® OS, easily. To learn how to use Visual C++ with embedded C code, refer to the Simulating an Embedded C Code Using Visual C++ section. SIMULATING AN EMBEDDED C CODE USING VISUAL C++ if (((I2CMasterTxDat[0] >4) && (I2CMasterTxDat[0] <= 6))||((I2CMasterTxDat[0] >9))) { After completing the entire C code in Visual C++, to make an executable image for the ADuCM360, perform a rebuild in the Keil MDK-ARM or IAR Embedded Workbench IDE. This rebuild is possible because of the following C/C++ precompiler directive in the sample code: printf("The specified ADE7953 register address is out of range\n"); } else { ReadFlag=0; #ifdef FermiEmulation_Mode uiMasterTxIndex = 0; // to initialize all of the ADuCM360 register set. // Master case : send 1st data. *pI2CMTX = I2CMasterTxDat[uiMasterTxIndex++]; ADuCM360_RegsInit(); #endif I2cMWrCfg(0x70); The following step by step procedure is useful to understand the debugging process when using the Visual C++ 2012 debugger tool. Note that the following method can be used with any Visual Studio version. while (!ucComplete){} ucComplete = 0; } 1. } Create a new project as shown in Figure 18. The if condition in the preceding code is based on the ADE7953 address range. The MSB of the register address determines whether the address is out of range. Refer the ADE7953 data sheet and the ADE7953 Evaluation Board User Guide for more information. Whenever each byte is received, the ADE7953 issues an acknowledgement to the master and the ADuCM360 generates an I2C interrupt to invoke the I2C0_Master_Int_Handler function found in the ADuCM360_Test_Lib.h file, which changes the value of ucComplete in the preceding code. If the ucComplete value is changed, I2C_Write_ADE7953() exits from the while loop and continues to send a byte to the ADE7953. 13338-017 The I2cMWrCfg(0x70) routine sends 0x01110000 (0x70) to the ADE7953, as shown in Figure 15 and Figure 16. Figure 18. Create New Project 2. Select Empty Project as shown in Figure 19. Use Visual C++ debugger to help with debugging when there are bugs in the code, particularly while working on initial projects or with new ICs. Using the Visual C++ debugger may also help the user understand how a piece of code works. Generally, the embedded code involves physical addresses but Visual C++ can only interpret virtual addresses, which are Rev. 0 | Page 12 of 15 13338-018 When writing to any of the ADE7953 registers, it is essential to make sure that the length of the data matches the description of the register. The same concept applies while reading back data from the ADE7953 IC. The I2C0_Master_Int_Handler function considers the register data length during both write and read operations. Figure 19. Select Empty Project Application Note Add all the sample files and existing items into the project, as shown in Figure 20 and Figure 21. 5. Select the folder that contains the sample codes under C/C++. Click Additional Include Directories. Refer to Figure 23 and Figure 24. 13338-022 3. AN-1367 13338-019 Figure 23. Search for Sample Codes 13338-023 Figure 20. Add Sample Files Figure 24. Select Folder with Visual Studio Sample Code 13338-020 6. Figure 21. Add Existing Items 13338-024 Modify certain properties as shown in Figure 22 to Figure 25. Figure 25. Define the Code Compile and link all the sample codes under Visual C++, as shown in Figure 26. 13338-025 7. 13338-021 4. For Visual C++ compiler only, define FermiEmulation_Mode, as shown in Figure 25. This step predefines FermiEmulation_Mode based on which Visual C++ code can be programmed to work with the embedded C code. When using other Visual Studio versions, the corresponding options shown in Figure 22 to Figure 25 need to be searched in the menu options, but the procedure is the same. Add _CRT_SECURE_NO_ WARNINGS only for .NET (see Figure 25). Figure 22. Select Properties Figure 26. Compile and Link all Sample Codes As shown in Figure 26, there are no errors and warnings in the code. Rev. 0 | Page 13 of 15 AN-1367 Application Note debugger is that the I2C0_Master_Int_Handler function and the set/get commands can be analyzed easily. Figure 27 shows how to simulate the embedded code using Visual C++. The following code of the I2C0_Master_Int_Handler function is for synchronization: #ifndef FermiEmulation_Mode __asm{ nop} __asm{ nop} __asm{ nop} __asm{ DSB} __asm{ nop} 13338-026 __asm{ nop} Figure 27. Simulate Embedded Code To understand how Visual C++ works, analyze both ADuCM360_Regs.c and ADuCM360_Regs.h carefully. These files define real addresses related to the ADuCM360 and enable the MMU to assign virtual addresses corresponding to the real addresses so that Visual C++ can debug the files. Note that the files can also be debugged by Keil MDK-ARM or IAR Embedded Workbench. If debugging is done using Keil MDKARM or IAR Embedded Workbench, FermiEmulation_Mode does not need to be used. #endif The printf function in the downloaded sample code is specially developed to reduce code size when using Visual C++; therefore, if the Keil MDK-ARM or IAR Embedded Workbench runtime library is used, the code size may be larger. The compact printf function can be found in the JongSuLib_V2.c library file, which includes many other useful functions, such as register read/write functions. One useful library file, named ADuCM360_Test_Lib.c, includes functions to support ADuCM360 peripherals such as I2C, SPI, UART, and ADCs/DACs. These two general-purpose libraries can be ported to other projects as well, as needed. This debugging method is very simple and can be used on all types of processors. The advantage of using Visual C++ Rev. 0 | Page 14 of 15 Application Note AN-1367 CONCLUSION This application note demonstrates how to implement I2C C code to monitor and modify the registers of the ADE7953 using the ADuCM360. To develop any embedded code, it is recommended that Visual C++ be used because coding and debugging are very simple using this tool. Then use Keil MDKARM or IAR Embedded Workbench to compile and link the C code to make an executable image without additional modification. I2C refers to a communications protocol originally developed by Philips Semiconductors (now NXP Semiconductors). ©2015 Analog Devices, Inc. All rights reserved. Trademarks and registered trademarks are the property of their respective owners. AN13338-0-9/15(0) Rev. 0 | Page 15 of 15