NEW DATABASE - 350 MILLION DATASHEETS FROM 8500 MANUFACTURERS
AN438 8XC528 EIE/AN90015 PL/M-51 PLM51 IIC51 ETV/AN89004 SU00411 SU00412 OM4142 - Datasheet Archive
AN438 I2C routines for 8XC528 Philips Semiconductors Application Note EIE/AN90015 Philips Semiconductors 1991 Mar Philips
INTEGRATED CIRCUITS AN438 AN438 I2C routines for 8XC528 8XC528 Philips Semiconductors Application Note EIE/AN90015 EIE/AN90015 Philips Semiconductors 1991 Mar Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 Philips Semiconductors Application Note EIE/AN90015 EIE/AN90015 The advantages of using the bit-level I2C hardware compared with a full software implementation are: Summary This application note presents a set of software routines to drive the I2C interface in 8xC528 type of microcontrollers. A description of the I2C interface is given. Examples show how to use these routines in PL/M-51 PL/M-51, C and assembly source code. Higher bit rate No critical software timing requirements Less software overhead 1.0 More reliable data transfer INTRODUCTION This application note describes the I2C interface of the 8xC528 microcontroller and gives a set of routines in application programs to drive this interface. The bit-level I2C hardware can perform the following functions: Filtering the incoming serial data and clock signals. Glitches shorter than 4 XTAL periods are rejected. Chapter 2.0 gives a hardware description of the bit level I2C. It gives an overview of what functions are done in hardware by the interface and the functions that should be implemented by software. The registers described are accessible with software and control the I2C interface. Recognition of a START or STOP condition. Generating an interrupt request after reception of a START condition. Setting the Bus Busy flag when a START condition is detected. Chapter 3.0 gives a description of the routines that may be used by the application program. The routines are written in such a way that the I2C interface becomes transparent to the user. the slave program is described in more detail, because this routine may be adapted by the user for his specific application. Clearing the Bus Busy flag when a STOP condition is detected. Recognition of a serial clock pulse on the SCL line. Latching the serial data bit on the SDA line at every rising edge on the SCL line. Chapter 4.0 gives simple example programs that show how to use the routines in assemble, PL/M and C application programs. Stretching the LOW period of the serial clock SCL to synchronizer with external master devices. References: The I2C-bus specification 80C51-based 8-bit Microcontrollers Setting the Read Bit Finished (RBF) or Write Bit Finished (WBF) flag is an error free bit transfer has occurred. 9398 358 10011 Data handbook IC20 PLM51 PLM51 I2 C Software Interface IIC51 IIC51 Setting a Clock LOW-to-HIGH (CLH) flag when a leading edge is detected on the SCL line. ETV/AN89004 ETV/AN89004 Generation of serial clock pulse on SCL in master mode. 2.0 2.1 The following functions must be done with software: THE I2C INTERFACE Characteristics of I2C Interface Handling the I2C interrupt caused by a detected START condition. Conversion of serial to parallel data when receiving. The Block diagram of the bit-level I2C interface is shown on page 2159. P1.6/SCL and P1.7/SDA are the serial I/O pins. These two pins meet the I2C specification concerning the input levels and output drive capability. Consequently, these pins have an open drain configuration. All four modes of the I2C bus can be used: Conversion of parallel to serial data when transmitting. Comparing received slave address with own slave address. Interpretation of acknowledge information. Guarding the I2C status if the RBF and WBF flags indicate a not regular bit transfer. Master transmitter Master receiver Generating START/STOP conditions when in master mode. Slave transmitter Handling bus arbitration when in master mode. Slave receiver March 1991 2158 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 Special Function Registers 1) S1INT (DAh) R/W S1 X X X X X X X 7 6 5 4 3 2 1 0 S1BIT SDI 0 0 0 0 0 0 0 R (D9h) SDO X X X X X X X W DF DE DD DC DB DA D9 D8 Bit Address Output SFR Latch P1.7 Input P1.7 Open drain buffer Q P1.7/SDA SDO S1SCS SDI SCI BB CLH 2) 2) 1) SDO SCO CLH (D8h) RBF WBF STR ENS R X X X STR ENS W DIS FSDA FILTER D 1) Software can only clear this bit 2) This bit is read with readmodifywrite operation SDI X =Undefined (R) or don't care (W) R = Read access W = Write access CLK FSCL Output SFR Latch P1.6 Input P1.6 Open drain buffer Q SDO P1.6/SCL DIS S AUTOCL SI S START/STOP condition detection logic SCI FILTER FSCL R STRETCH BB R R/W S1BIT FSCL S Q CLR R/W R Q ENS Qn STR ENABLE RBF STRETCH Read/Writ bit finished logic Stretch Logic R/W S1BIT START Auto-clock generator AUTOCL WBF DIS S1BIT SU00411 SU00411 Figure 1. March 1991 2159 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 2.2 AN438 AN438 read or write operation of S1SCS.7 does not start an auto-lock pulse, with not finish clock stretching, and will not clear flags. Control and Status Registers Control of the I2C bus hardware is done via 3 Special Function Registers: S1SCS.6 represents two physical latches, the Serial Clock Output (SCO) latch for write operations and the Serial Clock Input (SCI) latch for read operations. The output of SCO is "OR-ed" with the auto-clock pulse. If SCO = `1' the auto-clock generation is disabled and its output is LOW. Internal clock stretching logic and external devices can then pull the SCL line LOW. S1INT This register contains the serial interrupt flag SI. S1BIT For read, this register contains the received bit SDI. For write, this register contains bit SDO to be transmitted. If the auto-clock is not used, the SCL line has to be controlled by setting SCO = `1', waiting for CLH to become `1' and setting SCO = `0' after the specified SCL HIGH time. Data access should be done via S1SCS.7. S1SCS For read, this register contains status information. For write, this register is used as control register. 2.2.1 S1INT: I2C Interrupt Register S1SCS.5 is the serial Clock LOW-to-HIGH transition flag (CLH). This flag is set by a rising edge of the filtered serial clock. CLH = `1' indicates that no devices are stretching SCL LOW, and since the last CLH reset, a new valid data bit has been latched in SDI. S1INT.7 is the Serial Interrupt request flag (SI). If the serial I/O is enabled (ENS = 1), then a START condition will be detected and the SI flag is set on the falling edge of the filtered SCL signal. CLH can be cleared by writing `0' to S1SCS.5 or by a read or write operation to the S1BIT register. Clearing CLH also clears RBF and WBF. Writing a `1' to S1SCS.5 will not affect CLH. Provided that EA (global enable) and ES1 (enable I2C interrupt) are set (in the interrupt enable IE register), SI generates an interrupt that will start the slave address receive routine. S1SCS.4 is the Bus Busy flag (BB). BB is set or cleared by hardware only. If set, it indicates that a START condition has been detected on the I2C bus. A STOP condition clears the BB flag. SI is cleared by accessing the S1BIT register or by writing `00H' to S1INT. SI cannot be set by software. S1SCS.3 is the Read Bit Finished flag (RBF). If RBF = 1, it indicates that a serial bit has been received and latched into SDI successfully. If during a bit transfer RBF is `0', the cause is indicated as follows: After reception of a START condition, the LOW period of the SCL pulse is stretched, suspending serial transfer to allow the software to take appropriate action. This clock stretching is ended by accessing the S1BIT register. 2.2.2 SCI = `1' and CLH = `1' S1BIT: Single Bit Data Register S1BIT.7 contains two physical latches: the Serial Data Output (SDO) latch for a write operation, and the filtered Serial Data Input (SDI) latch for a read operation. SDI data is latched on the rising edge of the filtered SCL pulse. S1BIT.7 accesses the same physical latches as S1SCS.7, but S1BIT.7 is not bit addressable. CLH = `0' A STOP-condition has been detected during the bit transfer. This should be considered as a bus-error. SI = `1' A START-condition has been detected during the bit transfer. This should be considered as a bus-error. RBF can be cleared by clearing CLH or by a read or write operation to the S1BIT register. The auto-lock is an active HIGH SCL pulse that starts 28 Xtal periods after an access to S1BIT. SCL remains high for 100 Xtal periods. If the SCL line is kept LOW by any device that wants to hold up the bus transfer, the auto-clock counter still runs for 20 Xtal periods to try to make SCL high and then go into a wait-state. This will result in a minimum SCL HIGH time of 80 Xtal periods (5µs at fXtal = 16 MHz). S1SCS.2 is the Write Bit Finished flag (WBF). If set, it indicates that a serial bit in SDO has been transmitted successfully. If during bit transfer WBF is `0', the following conditions may be the cause: SCI = `1' and CLH = `1' The auto-clock signal will be inhibited if the SCO flag in the S1SCS register is set to `1'. SCL pulses must then be generated by software. In this situation, access to S1BIT may be used to clear the SI, CLH, RBF and WBF flags. The SCL pulse is not finished and still HIGH. CLH = `0' S1SCS.7 represents two physical latches, the Serial Data Output (SDO) latch for write operations and the Serial Data Input (SDI) latch for read operations. S1SCS.7 accesses the same physical latches as S1BIT.7, but S1SCS.7 is bit addressable. However, a A STOP-condition has been detected during the bit transfer. This should be considered as a bus-error. SI = `1' S1SCS: Control and Status Register A bus device is delaying the transfer by stretching the LOW level on the SCL line. BB = `0' A quick check on a successful bit transfer from/to SDO/SDI is carried out be testing only the RBF or WBF flag (see 2.2.3). March 1991 A bus device is delaying the transfer by stretching the LOW level on the SCL line. BB = `0' Reading or writing S1BIT register starts the next additional actions: SI, CLH, RBF and WBF flags are cleared. Stretching the LOW period of the SCL clock is finished. Auto-clock pulse is started if enabled. 2.2.3 The SCL pulse is not finished and still HIGH. A START-condition has been detected during the bit transfer. This should be considered as a bus-error. WBF can be cleared by clearing CLH or access to the S1BIT register. 2160 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 S1SCS.0 is the ENable Serial I/O flag (ENS). S1SCS.1 is the STRetch control flag (STR). STR can be set or cleared by software only. Setting STR enables the stretching of SCL LOW periods. Stretching will occur after a falling edge on the filtered serial clock. This allows synchronization with the SCL clock signal of an external master device. ENS can be set or cleared by software only. ENS = `0' disables the serial I/O. The I/O signals P1.6/SCL and P1.7/SDA are determined by the port latches of P1.6 and P1.7 (open drain). If P1.6 and P1.7 are connected to an I2C bus, then the flags SDI, SCI, CLH, and BB still monitor the I2C bus status, but will not influence the I/O lines, nor will they request an interrupt. If STR is cleared, no stretching of the SCL LOW period will occur after the transfer of a serial bit. The LOW level on the SCL line is also stretched after a START condition is received, regardless of the STR contents. The stretching of the SCL LOW period is finished by a read or write operation of the S1BIT register. ENS = `1' enables the START detection and clock stretching logic. Note that the P1.6 and P1.7 latches and the SDO and SCO control flags must be set to `1' before ENS is set to avoid SCL and/or SDA to pull the lines LOW. CONDITIONS: ENS=1 AND STR=1 SDI-0 SCI-0 READ/WRITE S1BIT (CLEARS SI) (STARTS AUTO-CLOCK) READ/WRITE S1BIT (CLEARS CLH, RBF, WBF) (STARTS AUTO-CLOCK) SCI-1 SDI-1 SDA SCL LOW PERIOD STRETCHED BB SET SI SET START CONDITION LOW PERIOD STRETCHED CLH SET RBF OR WBF SET BB CLEARED ONE BIT TRANSFER NEXT BIT TRANSFERS STOP CONDITION SU00412 SU00412 Figure 2. Example of a Serial Transfer March 1991 2161 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 3.0 I2C ROUTINES 3.1 AN438 AN438 Introduction 3.2.1 Init_IIC Declaration Init_IIC: PROCEDURE (Own_Slave_Address, Slave_Sub_Address) EXTERNAL; DECLARE (Own_Slave_Address, Slave_Sub_Address) BYTE; END; I2C A set of routines is written for the interface that supports multi-master and slave operation. The routines are placed in a library I2C_DR.LIB. If I2C_DR.LIB is linked to an application program, only the needed object modules are linked in the output file. Description Init_IIC must be called after RESET, before any procedure is called. The I2C interface and I2C interrupt will be enabled. The global enable interrupt flag, however, will not be affected. This should be done afterwards. Own_Slave_Address is passed to Init_IIC for use as slave. Slave_Sub_Address is the pointer to a DATA buffer that is used for data transfer in slave mode. When used as master in a single master system, these parameters are not used. The routines can be used as device driver for PL/M-51 PL/M-51, C and 8051-assembly code. By using these routines the bit-level I2C interface is fully transparent for the user. The routines use the following 8xC528 resources: Exclusive use of Register_Bank_1. Only R7 of this register bank contains static data (Own Slave Address). R0.R6 may be used by the application program when the I2C routine is finished. 7 bytes DATA used for parameter passing. Example CALL Init_IIC (54h,.Slave_Data_Buffer); ENABLE; /* Enable Interrupts; EA=1 */ 1 byte Bit-Addressable DATA for status flags. When using routines from this library DPH, DPL, PSW (except CY) and B are not altered. 3.2.2 An n-bytes data buffer is used as destination or source buffer for the bytes to be received/transmitted and reside in DATA or IDATA memory space. Dis_IIC Declaration Dis_IIC: PROCEDURE EXTERNAL; The code is written to generate the highest transfer rate on the I2C bus. At fXtal = 16MHz this will result in a bit rate of 87.5kbit/sec. Description Dis_IIC will disable the I2C-interface and the I2C-interrupt. The I2C interface will still monitor the bus, but will not influence the SDA and SCL lines. The following software tools from BSO/Tasking are used for program development: OM4142 OM4142 Cross Assembler 8051 for DOS: V3.0b Example CALL Dis_IIC; OM4144 OM4144 PL/M 8051 Compiler for DOS: V3.0a OM4136 OM4136 C8051 C8051 Compiler for DOS: V1.1a 3.2.3 IIC_Test_Device OM4129 OM4129 XRAY51 XRAY51 debugger: V1.4c 3.2 Declaration IIC_Test_Device: PROCEDURE (Slave_Address) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address) BYTE; END; Functional Description When using these routines in a PL/M application program, they must be declared EXTERNAL. In this declaration the user can specify the type returned by each procedure. All procedures (except Init_IIC and Dis_IIC) can return a BIT or BYTE, depending on the chosen EXTERNAL declaration. The BIT or BYTE returned is `0' if the I2C was successful. If a BYTE is returned, the following check bits are available for the user: BYTE.0 No ACK received. BYTE.2 Arbitration lost. BYTE.3 Time out error. This may be caused by an external device pulling SCL LOW. BYTE.4 A bus error has occurred. This may be a spurious START/STOP during a bit transfer. BYTE.5 No access to I2C bus. BYTE.6 0 BYTE.7 I2C Protocol S-SlvW-A-P S-SlvW-N-P An I2C error has been detected. BYTE.1 Description IIC_Test_Device just sends the slave address to the I2C bus. It can be used to check the presence of a device on the I2C bus. 0 Example DECLARE IIC_Error BIT; . IIC_Error=IIC_Test_Device(8Ch); IF (IIC_Error) THEN "Device not acknowledging on slave address" ELSE "Device acknowledges on slave address" Note that typed procedures must be called using an expression. If the result of an I2C procedure is to be ignored, a dummy assignment must be done for a typed procedure. The examples in the following section assume that the procedures are called from a PL/M program. Examples will be given later how to use these routines with C and assembly application programs. March 1991 : Device is present, IIC_Error=0 : Device is not present, IIC_Error=1 2162 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 3.2.4 AN438 AN438 3.2.6 IIC_Write Declaration IIC_Write_Sub_SWInc: PROCEDURE (Slave_Address, Count, Source_Ptr, Sub_Address) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Source_Ptr, Sub_Address) BYTE; END; Declaration IIC_Write: PROCEDURE (Slave_Address, Count, Source_Ptr) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Source_Ptr) BYTE; END; Description IIC_Write is the most basic procedure to write a message to a slave device. I2C Protocol L D1[0.L1] Description Some I2C devices addressed with a sub-address do not automatically increment the sub-address after reception of each byte. IIC_Write_Sub_SWInc can be used for such devices the same way as IIC_Write_Sub is used. IIC_Write_Sub_SWInc splits up the message in smaller messages and increments the sub-address itself. =Count BASED by Source_Ptr S-SlvW-A-D1[0]-A.A-D1[L-1]-A-P I2C Protocol L Sub D1[0.L1] Example DECLARE Data_Buffer(4) BYTE; . CALL IIC_Write(02Ch, LENGTH(Data_Buffer),.Data_Buffer); 3.2.5 =Count =Sub_Address BASED by Source_Ptr S-SlvW-A- (Sub+0) A-D1[0] A-P S-SlvW-A- (Sub+1) A-D1[1] A-P . S-SlvW-A- (Sub+L1)-A-D1[L-1]-A-P IIC_Write_Sub Declaration IIC_Write_Sub: PROCEDURE (Slave_Address, Count, Source_Ptr, Sub_Address) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Source_Ptr, Sub_Address) BYTE; END; Example DECLARE Data_Buffer(6) BYTE; . CALL IIC_Write_Sub_SWInc(80h,LENGTH (Data_Buffer),.Data_Buffer,2); 3.2.7 Description IIC_Write_Sub writes a message preceded by a sub-address to a slave device. I2C Protocol L Sub D1[0.L1] IIC_Write_Sub_SWInc IIC_Write_Memory Declaration IIC_Write_Memory: PROCEDURE (Slave_Address, Count, Source_Ptr, Sub_Address) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Source_Ptr, Sub_Address) BYTE; END; =Count =Sub_Address BASED by Source_Ptr Description I2C Non-Volatile Memory devices (such as PCF8582 PCF8582) need an additional delay after writing a byte to it. IIC_Write_Memory can be used to write to such devices the same way IIC_Write_Sub is used. IIC_Write_Memory splits up the message in smaller messages and increments the sub-address itself. After transmission of each message a delay of 40 milliseconds (fXtal = 16 MHz) is inserted. S-SlvW-A-Sub-A-D1[0]-A-D1[1]-A.A-D1[L-1]-A-P Example DECLARE Data_Buffer(8) BYTE; . CALL IIC_Write_Sub (48h,LENGTH(Data_Buffer),.Data_Buffer,2); I2C Protocol L Sub D1[0.L1] =Count =Sub_Address BASED by Source_Ptr S-SlvW-A- (Sub+0) A-D1[0] A-P Delay 40ms S-SlvW-A- (Sub+1) A-D1[1] A-P Delay 40ms . S-SlvW-A- (Sub+L1)-A-D1[L-1]-A-P Delay 40ms Example DECLARE Data_Buffer(10) BYTE; . CALL IIC_Write_Memory(0A0h,LENGTH (Data_Buffer),.Data_Buffer,0F0h); March 1991 2163 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 3.2.8 AN438 AN438 3.2.9 IIC_Write_Sub_Write IIC_Write_Sub_Read Declaration IIC_Write_Sub_Write: PROCEDURE (Slave_Address, Count1, Source_Ptr1, Sub_Address, Count2, Source_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count1, Source_Ptr1, Sub_Address, Count2, Source_Ptr2) BYTE; END; Declaration IIC_Write_Sub_Read: PROCEDURE (Slave_Address, Count1, Source_Ptr1, Sub_Address, Count2, Dest_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count1, Source_Ptr1, Sub_Address, Count2, Dest_Ptr2) BYTE; END; Description IIC_Write_Sub_Write writes 2 data blocks preceded by a sub-address in one message to a slave device. This procedure can be used for devices that need an extended addressing method, without the need to put all data into one large buffer. Such a device is the ECCT (I2C controlled teletext device; see example). Description IIC_Write_Sub_Read writes a data block preceded by a sub-address, generates an I2C restart condition, and reads a data block. This procedure can be used for devices that need an extended addressing method. Such a device is the ECCT. I2C Protocol L M Sub D1[0.L1] D2[0.M1] I2C Protocol L M Sub D1[0.L1] D2[0.M1] =Count1 =Count2 =Sub_Address BASED by Source_Ptr1 BASED by Source_Ptr2 =Count1 =Count2 =Sub_Address BASED by Source_Ptr1 BASED by Source_Ptr2 S-SlvW-A-Sub-A-D1[0]-A-D1[1]-A-. -A-D1[L-1]-A-S-SlvR-A-D2[0]-A-D2[1]-A-. -A-D2[M-1]-N-P S-SlvW-A-Sub-A-D1[0]-A-D1[1]-A-. -A-D1[L-1]-A-D2[0]-A-D2[1]-A-. -A-D2[M-1]-A-P Example PROCEDURE Read_CCT_Memory (Chapter, Row, Column, Data_Buf, Data_Count); DECLARE (Chapter, Row, Column, Data_Buf, Data_Count) BYTE; Example PROCEDURE Write_CCT_Memory (Chapter, Row, Column, Data_Buf, Data_Count); DECLARE (Chapter, Row, Column, Data_Buf, Data_Count) BYTE; /* The extended address (CCT-Cursor) is formed by Chapter, Row and Column. These three bytes are written after the sub-address (8). After that the actual data will be read relative to the extended address. /* The extended address (CCT-Cursor) is formed by Chapter, Row and Column. These three bytes are written after the sub-address (=8) followed by the actual data that will be stored relative to the extended address. */ */ CALL IIC_Write_Sub_Write (22h, 3, .Chapter, 8, Data_Buf, Data_Count); END Read_CCT_Memory; CALL IIC_Write_Sub_Write (22h, 3, .Chapter, 8, Data_Buf, Data_Count); END Write_CCT_Memory; March 1991 2164 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 3.2.10 IIC_Write_Com_Write 3.2.11 Declaration IIC_Write_Com_Write: PROCEDURE (Slave_Address, Count1, Source_Ptr1, Count2, Source_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count1, Source_Ptr1, Count2, Source_Ptr2) BYTE; END; Declaration IIC_Write_Rep_Write: PROCEDURE (Slave_Address1, Count1, Source_Ptr1, Slave_Address2, Count2, Source_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address1, Count1, Source_Ptr1, Slave_Address2, Count2, Source_Ptr2) BYTE; END; Description IIC_Write_Com_Write writes two data blocks from different data buffers in one message to a slave receiver. This procedure can be used for devices where the message consists of 2 different data blocks. Such devices are, for instance, LCD-drivers, where the first part of the message consists of addressing and control information, and the second part is the data string to be displayed. Description Two data strings are sent to separate slave devices, separated with a repeat START condition. This has the advantage that the bus does not have to be released with a STOP condition before the transfer from the second slave. I2C Protocol L M SlvW1 SlvW2 D1[0.L1] D2[0.M1] I2C Protocol L M D1[0.L1] D2[0.M1] =Count1 =Count2 BASED by Source_Ptr1 BASED by Source_Ptr2 S-SlvW-A-D1[0]-A-D1[1]-A-. -A-D1[L-1]-A-D2[0]-A-D2[1]-A-. -A-D2[M-1]-A-P =Count1 =Count2 =Slave_Address1 =Slave_Address2 BASED by Source_Ptr1 BASED by Source_Ptr2 S-SlvW-A-D1[0]-A-D1[1]-. -A-D1[L-1]-A-S-SlvW-A-D2[0]-A-D2[1]-. -A-D2[M-1]-A-P Example DECLARE Control_Buffer(2) BYTE; DECLARE Data_Buffer(20) BYTE; . CALL IIC_Write_Com_Write(74h, LENGTH(Control_Buffer), .Control_Buffer, LENGTH(Data_Buffer), .Data_Buffer); March 1991 IIC_Write_Rep_Write Example DECLARE Data_Buffer_1(10) BYTE; DECLARE Data_Buffer_2(4) BYTE; . CALL IIC_Write_Rep_Write (48h, LENGTH(Data_Buffer_1), .Data_Buffer_1, 50h, LENGTH(Data_Buffer_2), .Data_Buffer_2); 2165 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 3.2.12 IIC_Write_Rep_Read 3.2.14 IIC_Read_Status Declaration IIC_Write_Rep_Read: PROCEDURE (Slave_Address1, Count1, Source_Ptr1, Slave_Address2, Count2, Dest_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address1, Count1, Source_Ptr1, Slave_Address2, Count2, Dest_Ptr2) BYTE; END; Declaration IIC_Read_Status: PROCEDURE (Slave_Address, Dest_Ptr) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Dest_Ptr) BYTE; END; Description Several I2C devices can send a one byte status-word via the bus. IIC_Read_Status can be used for this purpose. IIC_Read_Status works the same way as IIC_Read but the user does not have to pass a count parameter. Description A data string is sent and received to/from two separate slave devices, separated with a repeat START condition. This has the advantage that the bus does not have to be released with a STOP condition before the transfer from the second slave. I2C Protocol L M SlvW1 SlvW2 D1[0.L1] D2[0.M1] I2C Protocol Status S-SlvR-A-Status-N-P =Count1 =Count2 =Slave_Address1 =Slave_Address2 BASED by Source_Ptr1 BASED by Dest_Ptr2 Example DECLARE Status_Byte BYTE; . CALL IIC_Read_Status (84h, .Status_Byte); S-SlvW-A-D1[0]-A-D1[1]-. -A-D1[L-1]-A-S-SlvR-A-D2[0]-A-D2[1]-. -A-D2[M-1]-N-P 3.2.15 IIC_Read_Sub Declaration IIC_Read_Sub: PROCEDURE (Slave_Address, Count, Dest_Ptr, Sub_Address) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Dest_Ptr, Sub_Address) BYTE; END; Example DECLARE Data_Buffer_1(10) BYTE; DECLARE Data_Buffer_2(4) BYTE; . CALL IIC_Write_Rep_Read (48h, LENGTH(Data_Buffer_1), .Data_Buffer_1, 57h, LENGTH(Data_Buffer_2), .Data_Buffer_2); Description IIC_Read_Sub reads a message from a slave device, preceded by a write of the sub-address. Between writing the sub-address and reading the message, an I2C restart condition is generated without releasing the bus. This prevents other masters from accessing the slave device in between and overwriting the sub-address. 3.2.13 IIC_Read Declaration IIC_Read: PROCEDURE (Slave_Address, Count, Dest_Ptr) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address, Count, Dest_Ptr) BYTE; END; I2C Protocol M Sub D2[0.M1] Description IIC_Read is the most basic procedure to read a message from a slave device. I2C Protocol M D2[0.M1] =Count =Sub_Address BASED by Dest_Ptr Example DECLARE Data_Buffer(5) BYTE; . CALL IIC_Read_Sub (0A3h, LENGTH(Data_Buffer), .Data_Buffer, 2); =Count BASED by Dest_Ptr S-SlvR-A-D2[0]-A-D2[1]-A.A-D2[M-1]-N-P Example DECLARE Data_Buffer(4) BYTE; . CALL IIC_Read (0B5, LENGTH(Data_Buffer), .Data_Buffer); March 1991 BASED by Dest_Ptr 2166 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 3.2.16 IIC_Read_Rep_Read 3.2.17 IIC_Read_Rep_Write Declaration IIC_Read_Rep_Read: PROCEDURE (Slave_Address1, Count1, Dest_Ptr1, Slave_Address2, Count2, Dest_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address1, Count1, Dest_Ptr1, Slave_Address2, Count2, Dest_Ptr2) BYTE; END; Declaration IIC_Read_Rep_Write: PROCEDURE (Slave_Address1, Count1, Dest_Ptr1, Slave_Address2, Count2, Source_Ptr2) [BIT|BYTE] EXTERNAL; DECLARE (Slave_Address1, Count1, Dest_Ptr1, Slave_Address2, Count2, Source_Ptr2) BYTE; END; Description Two data strings are read from separate slave device, separated with a repeat START condition. This has the advantage that the bus does not have to be released with a STOP condition before the transfer from the second slave. Description A data string is received and sent from/to two separate slave devices, separated with a repeat START condition. This has the advantage that the bus does not have to be released with a STOP condition before the transfer from the second slave. I2C Protocol L M SlvW1 SlvW2 D1[0.L1] D2[0.M1] I2C Protocol L M SlvW1 SlvW2 D1[0.L1] D2[0.M1] =Count1 =Count2 =Slave_Address1 =Slave_Address2 BASED by Dest_Ptr1 BASED by Dest_Ptr2 =Count1 =Count2 =Slave_Address1 =Slave_Address2 BASED by Dest_Ptr1 BASED by Source_Ptr2 S-SlvR-A-D1[0]-A-D1[1]-. -A-D1[L-1]-N-S-SlvR-A-D2[0]-A-D2[1]-. -A-D2[M-1]-N-P S-SlvR-A-D1[0]-A-D1[1]-. -A-D1[L-1]-N-S-SlvW-A-D2[0]-A-D2[1]-. -A-D2[M-1]-A-P Example DECLARE Data_Buffer_1(10) BYTE; DECLARE Data_Buffer_2(4) BYTE; . CALL IIC_Read_Rep_Read (49h, LENGTH(Data_Buffer_1), .Data_Buffer_1, 51h, LENGTH(Data_Buffer_2), .Data_Buffer_2); Example DECLARE Data_Buffer_1(10) BYTE; DECLARE Data_Buffer_2(4) BYTE; . CALL IIC_Read_Rep_Write(49h, LENGTH(Data_Buffer_1), .Data_Buffer_1, 58h, LENGTH(Data_Buffer_2), .Data_Buffer_2); March 1991 2167 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 Auto-clock generation will be disabled and SCL stretching enabled. The byte will be continued to be received and can later be compared with the own slave address. 3.2.18 Slave Mode Routines There are two ways for the I2C interface to enter the slave-mode: After an I2C interrupt the software must enter the slave-receiver mode to receive the slave address. This address will then be compared with its own address. If there is a match either slave-transmitter or slave-receiver mode will be entered. If no match occurs, the interrupted program will be continued. The second entry point is via an interrupt when a START condition is detected. At _PIP0A the context of the interrupted program is stored. Next Auto-clock generation is disabled and SCL stretching enabled. Reception of the slave address can now begin by calling RCV_SL_BY. When the received slave-address is compared with the own-slave-address the R/W-bit is ignored. If there is no match between the 2 addresses, a negative ACK bit is sent and the slave routine is left via EXIT. If there was a match the R/W bit is checked to enter the slave-receiver or slave-transmitter mode. During transmission of a slave-address in master-mode, arbitration is lost to another master. The interface must then switch to slave-receiver mode to check if this other master wants to address the 8xC528 interface. The slave-mode protocol is very application dependent. In this note the basic slave-receive and slave-transmit routines are given and should be considered as examples. The user may for instance send NO_ACK after receiving a number of bytes to signal to the master-transmitter that a data buffer is full. A description of the code will be given later. The slave-transmitter mode starts at NXT_TRX. After getting the byte from the data buffer via BUF_POINT and initializing the bit counter BIT_CNT the transmission loop is entered. A bit is written via access to S1BIT because this will automatically reset the CLH and WBF status flags, and also SCL stretching. Now WBF must be tested until the transmission is successful. When WBF becomes true, SCL will be stretched again. When 8 bits are sent, the SDA line is released and RBF is tested until the ACK bit is received. The ACK bit is read by reading SDI instead of S1BIT to maintain SCL stretching. If ACK was false, no more bytes have to be sent and the routine is left. If another byte has to be transmitted, BUF_POINT is updated and transmission will continue. Slave parameters are given with the Init_IIC procedure. The passed parameters are the own-slave-address and a source/destination-pointer to a data buffer. The slave-routine will be suspended at the following conditions: Interrupts with higher priority. Slave-routine will be resumed again after interrupt is handled. The slave-receiver mode starts at RCV_SLAVE. A byte is received by calling RCV_SL_BY. This routine will clear the CY-flag when a STOP condition has been received. This means that the master will send no more bytes to this slave and the slave routine will be left. When no STOP condition was detected, the received byte will be stored @BUF_POINT and an ACK bit will be sent. After this, a new byte can be received. If a NO_ACKNOWLEDGE is received form a master-receiver. If a STOP condition is detected from a master transmitter. Constraints for user software. The user must control the global enable (EA) bit. The user must control the priority level of the I2C interrupt. If the slave routine is interrupted by a higher priority interrupt, the SCL line will be stretched to postpone bus transfer until the higher interrupt is finished. 3.3 When calling RCV_SL_BY the bit counter BIT_CNT will be initialized and the SCL stretching stopped by a dummy access to S1BIT. In the receive loop both BB and RBF will be checked. When BB is cleared, a STOP condition is detected and the routine will be left with CY=0. The Slave Routine: SLAVE.ASM The first 7 bits are received via S1BIT because this will release stretching. The 8th bit is accessed via SDI because stretching must be maintained. The listing of the slave routine can be seen on page 2169. The routine is written in such a way that stretching of SCL is minimized. Application code can be inserted in this routine and this will increase stretching time. If the slave routine is left via EXIT, the STR bit is cleared (to disable stretching on SCL edges when the 8xC528 is not addressed as slave) and a dummy access to S1BIT is done to finish current SCL stretching. If the slave routine was entered via an interrupt the previous context is restored. The routine has 2 entry points. Entry via MST_ENTRY happens when an arbitration error has occurred when transmitting a slave address in master mode. March 1991 2168 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 PAGE 1 LOC OBJ LINE 0053: 020000 R REG END REG END REG END 0000: C0E0 0002: C0D0 0004: 75D008 75D008 R 0007: 43D842 43D842 000A: 1142 000C: A2E0 000E; 92D5 0010: 6F March 1991 R 1 2 3 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 Slave interrupt routine SOURCE $TITLE(Slave interrupt routine) $DEBUG $NOLIST ; ;This routine handles I2C interrupts. ;8xC528 I2C interface enters in slave mode. ;After testing R/W bit, 8xC528 will go in slavetransmit or ;slavereceive mode. ;Source or destination buffer for data uses pointer SLAVE_SUB_ADDRESS ;Slave routine will use register bank 01 ; ;* ;Interrupt entry point CSEG AT 53H LJMP _PIP0A ;Vector to interrupt handler ; ;* I2C_DRIVER SEGMENT CODE INBLOCK RSEG I2C_DRIVER PUBLIC MST_ENTRY EXTRN DATA(SLAVE_SUB_ADDRESS) EXTRN BIT(ARB_LOST) BUF_POINT SET R0 OWN_SLAVE SET R7 BIT_CNT SET R2 ;* _PIP0A:PUSH ACC PUSH PSW MOV PSW,#08H ;Push CPU status on stack ;Select registerbank 01 ;* ;Check slave address ;* 45 46 47 48 AN438 AN438 PROC: ORL S1SCS,#01000010B 01000010B ;Disable SCL generation and enable SCL ;stretching stretching ACALL RCV_SL_BY ;Receive slave address, on exit SCL is ; stretched MOV C,ACC.0 ;Store R/W bit in F0 MOV F0,C XRL A,OWN_SLAVE ;Compare received slave address 2169 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 PAGE 2 LOC OBJ 0011: 0013: 0015: 0016: 0018: 001A: 001C: C2E0 7050 C3 115C A800 A2D5 5019 LINE R R 001E: E6 001F: 7A08 0021: 0021: 0023: 0024: 0027: F5D9 23 30DAFD 30DAFD DAF8 0029: 002B: 002D: 0030: 0032: 0034: D2DF E5D9 30DBFD 30DBFD A2DF 4040 08 0035: 80E7 0037: 0037: 0039: 003B: 003C: 003D: 003F: 0040: 1142 5039 F6 C3 115C 08 80F5 March 1991 R R 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 AN438 AN438 Slave interrupt routine SOURCE CLR ACC.0 ;Ignore R/W bit JNZ NO_MATCH ;Leave slaveroutine if there is no match CLR C ;Send ACK ACALL SEND_ACK MOV BUF_POINT,SLAVE_SUB_ADDRESS ;Get buffer pointer MOV C,F0 ;Restore R/W bit JNC RCV_SLAVE ;Test R/W bit ;* ;Slave transmitter mode ;* NXT_TRX:MOV A,@BUF_POINT;Get byte to send MOV BIT_CNT,#08 ;Init bit counter NXT_TRX_BIT: MOV S1BIT,A ;Trx bit RL A ;Prepare JNB WBF,$ ;Test if DJNZ BIT_CNT,NXT_TRX_BIT SETB SDO MOV A,S1BIT JNB RBF,$ MOV C,SDI JC EXIT INC BUF_POINT and stretch after transmission next bit to send bit is sent ;Test if all bits are sent ;Release SDA line for NO_ACK/ACK reception ;Stop stretching ;Test if ACK bit is received ;Read bit, SCL remains stretched ;NO_ACK received. Exit slave routine ;ACK received. Update pointer for next byte to ;send SJMP NXT_TRX ;* ;Slave receiver mode ;* RCV_SLAVE: ACALL RCV_SL_BY JNC EXIT MOV @BUF_POINT,A CLR C CALL SEND_ACK INC BUF_POINT SJMP RCV_SLAVE ;Entry in slavereceiver mode ;Receive byte ;If STOP is detected, then exit ;Store received byte ;Send ACK ;Update pointer ;Receive next byte 2170 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 PAGE 3 LOC OBJ 0042: 0042: 0044: 0046: 0047: 0047: 004A: 004D: 30DC10 30DC10 30DBFA 30DBFA BA0105 BA0105 0050: 0052: 0053: 0054: LINE A2DF 33 D3 22 7A08 E5D9 E4 0055: 0055: 45D9 0057: 23 0058: DAED 005A: 005A: C3 005B: 22 005C: 005C: 005D: 005F: 0062: 0064: 13 F5D9 30DAFD 30DAFD D3DF 22 0065: 0065: D3 0066: 115C 0068: 800A March 1991 R 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 AN438 AN438 Slave interrupt routine SOURCE ;* ;Receive byte routine ;On exit, received byte in accu ;On exit CY=0 if STOP is detected ;* RCV_SL_BY: MOV BIT_CNT,#08 MOV A,S1BIT ;Disable stretching from START or previous ACK CLR A RCV_BIT: JNB BB,STOP_RCV ;Test if STOPcondition is received JNB RBF,RCV_BIT ;Wait till received bit is valid CJNE BIT_CNT,#01,ASSEM_BIT ;Check if last bit is to be received MOV C,SDI RLC A SETB C RET ;Get last bit without stopping stretching ;No STOP detected ASSEM_BIT: ORL A,S1BIT ;Receive bit; release RBF,CLH and SCL stretching RL A DJNZ BIT_CNT,RCV_BIT STOP_RCV: CLR C RET ;STOP detected ;* ;Send ACK/NO_ACK. Value of ACK in Carry ;* SEND_ACK: RRC A MOV S1BIT,A ;Carry to SDA line JNB WBF,$ ;Test if ACK/NO_ACK is sent SETB SDO ;Release SDA line RET ;* ;No match between received slaveaddress and ownslaveaddress ;* NO_MATCH: SETB C ;Send NO_ACK ACALL SEND_ACK SJMP EXIT 2171 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 PAGE 4 LOC OBJ LINE 139 141 142 143 144 145 146 006A: 006A: 23 006B: C2E0 006D: 43D842 43D842 0070: 1147 0072: 8098 0074: 0076: 0078: 007B: 007C: 007E: 0080: C2D9 E5D9 30001 22 D0D0 D0E0 32 0081: March 1991 R R 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 AN438 AN438 Slave interrupt routine SOURCE ;* ;Entry point when an arbitrationlost condition is detected in ;mastermode. ;* MST_ENTRY: RL A ;Restore slave address sofar CLR ACC.0 ORL S1SCS,#01000010B 01000010B ;Disable SCL generation and enable SCL ;strectching ACALL RCV_BIT ;Proceed with receiving rest of slave address SJMP PROC ;* ;Exit from interrupt routine ;* EXIT: EX_SL: CLR STR ;Disable stretching on next falling SCL edges MOV A,S1BIT ;Stop current SCL stretching JNB ARB_LOST,EX_SL RET ;Exit when entered from master mode POP PSW ;Restore old CPU status POP ACC RETI END 2172 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 4.0 IIC_Read is then called in the following way: EXAMPLES 4.1 AN438 AN438 Introduction %IIC_Read(Slave_Adr,Count_1,Source_Ptr_1); I2C Note that in the listing the contents of the macro are shown, instead of the call. Some examples are given how to use the routines in an applicatIon program. Examples are given for assembly, PL/M and C program. The macro must be written as follows: The program displays time from the PCF8583P PCF8583P clock/calendar/RAM on an LCD display driven by the PCF8577 PCF8577. %* DEFINE (IIC_Read(SLAVE_ADR,COUNT_1,SOURCE_PTR_1) (MOV _IIC_READ_BYTE,#%SLAVE_ADR MOV _IIC_READ_BYTE+1,#%COUNT_1 MOV _IIC_READ_BYTE+2,#%SOURCE_PTR_1 LCALL _IIC_READ) The example can be executed on the OM4151 OM4151 I2C evaluation board. 4.2 Using the Routines with Assembly Sources The listing of the example program is shown on page 2174. The most important aspect when using the I2C routines is preparing the input parameters before the sub-routine call. When, for example, the IIC_Write routine must be called, the parameters must be called in the following order: Macros for the I2C CALLs are found in I2C.MAC. This file should be included in all modules making use of the macros. One of the modules should also include the variable definitions needed by the I2C routines. These are found in file VAR_DEF.ASM. If the program consists of more than 1 module, then these modules should also include EXT_VAR.ASM. This file contains the EXTRN- definitions of the I2C routines. MOV _IIC_READ_BYTE,#SLAVE_ADR MOV _IIC_READ_BYTE+1,#COUNT_1 MOV _IIC_READ_BYTE+2,#SOURCE_PTR_1 CALL _IIC_READ When and I2C routine is called, the accumulator contains status information and the CY-bit is set if an error has occurred. The contents of the accumulator are the same as the returned byte when using PL/M. Note that the order of defining the parameters is the same as in a PL/M-call. An easier way to call the routines is making a macro that includes the initializing of the parameters. The example program makes use of macros. March 1991 2173 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 LOC OBJ LINE 1 2 3 4 5 6 7 8 74 8 9 35 10 11 12 13 14 15 00A2 0001 0074 0000: 000A: 000E: R 0000: 020000 R 0000: 0000: 900073 0003: 7581FF 7581FF 0006: 750E00 750E00 R R R R 0009: 750022 000C: 75010A 000F: 120000 R R R 0012: E4 0013: F50A 0015: F50B R R 0017: 001A: 001D: 0020: R R R R 7500A2 7500A2 750102 75020A 120000 March 1991 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 AN438 AN438 Assembly example program PAGE 1 SOURCE $TITLE(Assembly example program) $DEBUG ;Hours and minutes will be displayed on LCD display ;Dot between hours and minutes will blink $ # 1 "C:\USER\VAR_DEF.ASM" # 8 "DEMO_ASM.ASM" $ # 1 "C:\USER\I2C.MAC" # 9 "DEMO_ASM.ASM" CLOCK_ADR EQU 0A2h CL_SUB_ADR EQU 01h LCD_ADR EQU 74h ;Include I2C var. definitions RAMVAR USER ;Segment for variables ;Segment for application ;program ;Include I2C macro's ;Address of PCF8583 PCF8583 ;Sub address for reading time ;Address of PCF8577 PCF8577 SEGMENT DATA SEGMENT DATA RSEC RAMVAR STACK: DS 10 TIME_BUFFER:DS 4 LCD_BUFFER: DS 5 ;Stack area ;Buffer for I2C strings CSEG AT 00 LJMP APL_START RSEG USER APL_START: MOV DPTR,#LCD_TAB MOV SP,#STACK1 MOV LCD_BUFFER,#00 ;Pointer to segment table ;Initialize stack ;Control word for LCD driver MOV _Init_IIC_Byte ,#22h MOV _Init_IIC_Byte+1,#TIME_BUFFER LCALL _Init_IIC ;Initialize I2C interface CLR A MOV TIME_BUFFER,A MOV TIME_BUFFER+1,A MOV _IIC_Write_Byte ,#CLOCK_ADR MOV _IIC_Write_Byte+1,#2 MOV _IIC_Write_Byte+2,#TIME_BUFFER LCALL _IIC_Write 2174 ;Prepare buffer for clock int. Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 LOC 0023: 0023: 0026: 0029: 002C: 002F: OBJ 7500A2 7500A2 750104 75020A 750301 120000 LINE R R R R R 0032: E50D 0034: 543F 0036: F50D R R 0038: 120054 R 003B: 431101 R 003E: 0040: 0041: 0043: R 0046: 0046: 0049: 004C: 004F: E50B 13 4003 430F01 430F01 750074 750105 75020E 75020E 120000 R R R R R 0052: 80CF 0054: 0056: 0058: 0059: 005C: 005E: 0061: 0063: 0064: 0067: 0069: 780F E50D C4 12006D 12006D E50D 12006D 12006D E50C C4 12006D 12006D E50C 12006D 12006D March 1991 R R R R R R R R R 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 AN438 AN438 Assembly example program PAGE 2 SOURCE ;Initialize clock REPEAT: MOV _IIC_Read_Sub_Byte ,#CLOCK_ADR MOV _IIC_Read_Sub_Byte+1,#4 MOV _IIC_Read_Sub_Byte+2,#TIME_BUFFER MOV _IIC_Read_Sub_Byte+3,#CL_SUB_ADR LCALL _IIC_Read_Sub ;Read time ;Time has been read. Order: hundreds of sec's, sec's, min's and hr's MOV A,TIME_BUFFER+3 ;Mask of hour counter ANL A,#3Fh MOV TIME_BUFFER+3,A CALL CONVERT ;Convert time data to LCD ;segment data ;Check if dot has to be switched on ORL LCD_BUFFER+3,#01h ;If lsb of seconds is '0', then switch on dp MOV A,TIME_BUFFER+1 ;Get seconds RRC A JC PROCEED ORL LCD_BUFFER+1,#01 ;Switch on dp ;Display new time PROCEED: MOV _IIC_Write_Byte ,#LCD_ADR MOV _IIC_Write_Byte+1,#5 MOV _IIC_Write_Byte+2,#LCD_BUFFER LCALL _IIC_Write SJMP REPEAT ;Read new time ;CONVERT converts BCD data of time to segment data CONVERT:MOV R0,#LCD_BUFFER+1 ;R0 is pointer MOV A,TIME_BUFFER+3 ;Get hours SWAP A ;Swap nibbles CALL LCD_DATA ;Convert 10's of hours MOV A,TIME_BUFFER+3 CALL LCD_DATA ;Convert hours MOV A,TIME_BUFFER+2 ;Get minutes SWAP A CALL LCD_DATA ;Convert 10's of minutes MOV A,TIME_BUFFER+2 CALL LCD_DATA ;Convert minutes 2175 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 TSWASM51 ASM51 V3.0b Serial #00052252 LOC OBJ 006C: 22 006D: 006D: 006F: 0070: 0071: 0072: 540F 93 F6 08 22 0073: 0073: 0076: 0079: 007C: FC60DA FC60DA F266B6 F266B6 3EE0FE E6 007D: 4.3 LINE 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 AN438 AN438 Assembly example program 3 SOURCE RET ;LCD_DATA gets data from segment table and stores it in LCD_BUFFER LCD_DATA: ANL A,#0FH ;Mask off LSnibble MOVC A,@A+DPTR ;Get segment data MOV @R0,A ;Save segment data INC R0 RET ; ;Conversion table for LCD LCD_TAB: DB 0FCH,60H,0DAH ;'0','1','2' DB 0F2H,66H,0B6H ;'3','4','5' DB 3EH,0E0H,0FEH ;'6','7','8' DB 0E6H ;'9' ; END Using the Routines with PL/M-51 PL/M-51 Sources The following listing shows the listing of the clock program in PL/M-51 PL/M-51. The procedures are untyped. The routines are used the same way as in the examples of chapter 3.2. $OPTIMIZE(4) $DEBUG $CODE /* Hours and minutes will be displayed on LCD display Dots between hours and minutes will blink */ Demo_plm: Do; /* External declarations */ Init_IIC: Procedure(Own_Adr,Slave_Ptr) External; Declare (Own_Adr,Slave_Ptr) Byte Main; End Init_IIC; IIC_Write: Procedure(Sl_Adr,Nr_Bytes,Source_Ptr) External; Declare (Sl_Adr,Nr_Bytes,Source_Ptr) Byte Main; End IIC_Write; IIC_Read_Sub: Procedure(Sl_Adr,Nr_Bytes,Dest_Ptr,Sub_Adr) External; Declare(Sl_Adr,Nr_Bytes,Dest_Ptr,Sub_Adr) Byte Main; End IIC_Read_Sub; March 1991 PAGE 2176 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 AN438 AN438 Clock: Do; /* Variable and constant declarations */ Declare LCD_TAB(*) Byte Constant (0FCh,60H,0DAH,0F2H,66H, 0B6H,3EH,0E0H,0FEH,0E6H); Declare Time_Buffer(4) Byte Main; Declare LCD_Buffer(5) Byte Main; Declare Tab_Point Word Main; Declare (LCD_Point,Time_Point) Byte Main; Declare Segment Based LCD_Point Byte Main; Declare Time Based Time_Point Byte Main; Declare Tab_Value Based Tab_Point Byte Constant; Declare clock_Adr Literally '0A2h'; Declare LCD_Adr Literally '74h'; Declare C1_Sub_Adr Literally '01h'; Call Init_IIC(22h,.Time_Buffer); LCD_Buffer(0)=0; /* LCD control word */ Time_Buffer(0)=0; Time_Buffer(1)=0; Call IIC_Write(Clock_Adr,2,.Time_Buffer); /* Initialize clock */ Do While LCD_Buffer(0)=0; /* Program loop */ Call IIC_Read_Sub(Clock_Adr,4,.Time_Buffer,Cl_Sub_Adr); /* Get time */ LCD_Point=.LCD_Buffer+1; /* Initialize pointers */ Time_point=.Time_Buffer(3); Tab_Point=.LCD_Tab(0)+SHR(Time,4); /* 10HR's */ Segment=Tab_Value; LCD_Point=LCD_Point+1; Tab_Point=.LCD_Tab(0)+(Time AND 0FH); /* HR's */ Segment=Tab_Value; Time_Point=Time_Point1; LCD_Point=LCD_Point+1; Tab_Point=.LCD_Tab+SHR(Time,4); /* 10MIN's */ Segment=(Tab_Value OR 01H); /* dp */ LCD_Point=LCD_Point+1; Tab_Point=.LCD_Tab+(Time AND 0FH); /* MIN's */ Segment=Tab_Value; Time_Point=.Time_Buffer(1)+1; /*Check sec's for blinking */ LCD_Point=.LCD_Buffer+1; If (Time AND 01H)>0 then Segment=(Segment OR 01H); Call IIC_Write(LCD_Adr,5,.LCD_Buffer); /* Display time */ End; End Clock; End Demo_plm; March 1991 2177 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 4.4 AN438 AN438 Using the Routines with C Sources An example of a C program using the I2C routines follows. Function prototypes are found in header file "i2c.h". In this example the function prototypes are written in such a way that not value is returned by the function. If the STATUS byte is needed, the header file may be changed to return a byte. Note that the function calls are written in upper-case. This is due to the fact that the used version of the assembler/linker is case sensitive. #include rom char LCD_Tab[]={0xFC,0x60,0xDA,0xF2,0x66,0xB6,0x3E, 0xE0,0xFE,0xE6}; void main() { #define Clock_Adr #define LCD_Adr #define C1_Sub_Adr 0xA2 0x74 0x01 rom data data data data * Tab_Ptr; Time_Buffer[4]; * Time_Ptr; LCD_Buffer[5]; * LCD_Ptr; char char char char char INIT_IIC(0x22,&Time_Buffer); LCD_Buffer[0]=0; /* LCD control word */ Time_Buffer[0]=0; Time_Buffer[1]=0; IIC_WRITE(Clock_Adr,2,&Time_Buffer); /* Initialize clock */ while (1) /* Program loop */ { IIC_READ_SUB(Clock_Adr,4,&Time_Buffer,C1_Sub_Adr); /* Get time */ LCD_Ptr = &LCD_Buffer[1]; /* Initialize pointers */ Time_Ptr = &Time_Buffer[3]; Tab_Ptr = (LCD_Tab+(*Time_Ptr >> 4); /* 10HR's */ *(LCD_Ptr+) = *Tab_Ptr; Tab_Ptr = (LCD_Tab+(*(Time_Ptr) & 0x0F); /* HR's */ *(LCD_Ptr+) = *Tab_Ptr; Tab_Ptr = (LCD_Tab+(*Time_Ptr >> 4); /* 10MIN's */ *(LCD_Ptr+) = (*Tab_Ptr | 0x01); /* dp */ Tab_Ptr = (LCD_Tab+(*Time_Ptr & 0x0F); /* MIN's */ *LCD_Ptr = *Tab_Ptr; Time_Ptr = &Time_Buffer[1]; /* Check sec's for blinking */ LCD_Ptr = &LCD_Buffer[1]; if (*Time_Ptr & 0x01)>0) *LCD_Ptr = (*LCD_Ptr | 0x01); IIC_WRITE(LCD_Adr,5,&LCD_Buffer); /* Display time */ } } March 1991 2178 Philips Semiconductors Application note I2C routines for 8XC528 8XC528 5.0 AN438 AN438 CONTENTS OF DISK A disk contains the following 3 directories: 1: \USER This director contains the files that may be used in the user program. I2C_DR.LIB Library with I2C routines. I2C.H Header file for C applications. I2C.MAC Macro's for the I2C routine calls in assembly programs. VAR_DEF.ASM Include file with variable definitions for assembly programs. EXT_VAR.ASM Include file with external definitions for assembly programs. LIB.BAT Example batch file to create I2C_DR.LIB. ASM.BAT Example batch file to assemble source modules for library. 2: \EXAMPLE This directory contains the source files of the examples described in chapter 4.0. DEMO_ASM.* Assembly example. DEMO_PLM.* PL/M example. HEAD_51.SRC Example of environment file for PL/M example. DEMO_C.* C example. CSTART.ASM Example of environment file for C example. 3: \SOURCE This directory contains the source files of the modules in the library. March 1991 2179 Philips Semiconductors Products I2C routines for 8XC528 8XC528 Product specification AN438 AN438 Philips Semiconductors and Philips Electronics North America Corporation reserve the right to make changes, without notice, in the products, including circuits, standard cells, and/or software, described or contained herein in order to improve design and/or performance. Philips Semiconductors assumes no responsibility or liability for the use of any of these products, conveys no license or title under any patent, copyright, or mask work right to these products, and makes no representations or warranties that these products are free from patent, copyright, or mask work right infringement, unless otherwise specified. Applications that are described herein for any of these products are for illustrative purposes only. Philips Semiconductors makes no representation or warranty that such applications will be suitable for the specified use without further testing or modification. LIFE SUPPORT APPLICATIONS Philips Semiconductors and Philips Electronics North America Corporation Products are not designed for use in life support appliances, devices, or systems where malfunction of a Philips Semiconductors and Philips Electronics North America Corporation Product can reasonably be expected to result in a personal injury. Philips Semiconductors and Philips Electronics North America Corporation customers using or selling Philips Semiconductors and Philips Electronics North America Corporation Products for use in such applications do so at their own risk and agree to fully indemnify Philips Semiconductors and Philips Electronics North America Corporation for any damages resulting from such improper use or sale. Philips Semiconductors 811 East Arques Avenue P.O. Box 3409 Sunnyvale, California 940883409 Telephone 800-234-7381 © Copyright Philips Electronics North America Corporation 1997 All rights reserved. Printed in U.S.A.