Freescale Semiconductor Application Note Document Number: AN3291 Rev. 2, 04/2007 How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs by: Stanislav Arendarik Application Engineer Roznov, Czech Republic 1 Introduction This application note is an example of how to use the IIC module on Freescale’s MCUs. The IIC module can be used in the master or slave mode, respectively. In this case, the master mode communicates with the serial EEPROM because the IIC bus is used mainly for communication between an MCU and a IIC peripheral device. The IIC bus can communicate directly between two MCUs, but the SPI bus is better for this task. This application note summarizes the common IIC bus states and definitions and provides an example of how to communicate with serial EEPROMs (24C16 and 24C512). You can easily use another IIC device instead of an EEPROM, but you must change the IIC address byte that characterizes the slave device. © Freescale Semiconductor, Inc., 2007. All rights reserved. Contents 1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 IIC Bus Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 IIC Bus Terminology . . . . . . . . . . . . . . . . . . . . . . . 2.2 Bit Transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 START and STOP Conditions . . . . . . . . . . . . . . . . 2.4 Bus Communication. . . . . . . . . . . . . . . . . . . . . . . . 2.5 Control Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Address Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7 Acknowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8 Read/Write Format . . . . . . . . . . . . . . . . . . . . . . . . 3 IIC Software Routines for MCUs . . . . . . . . . . . . . . . . . . . 5 3.1 Initialization of the IIC . . . . . . . . . . . . . . . . . . . . . . 6 3.2 Write Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.3 Read Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.4 Example with Interrupt Used . . . . . . . . . . . . . . . . 13 3.4.1 MCU as Master . . . . . . . . . . . . . . . . . . . . . 13 3.4.2 MCU as Slave . . . . . . . . . . . . . . . . . . . . . . 16 4 Conclusion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2 2 2 3 3 3 4 4 5 IIC Bus Summary 2 IIC Bus Summary The IIC bus is a bidirectional, two-wire bus based on the wired AND (open drain) connection between master and slave devices. For proper functionality, pull-up resistors are used. Each transfer originates from the master device and is acknowledged or answered by the slave device. 2.1 IIC Bus Terminology The following IIC bus terminology is used in this application note: • Transmitter — Device that sends data to the bus. A transmitter can put data on the bus of its own accord (master transmitter), or respond to a request for data from another device (slave transmitter). • Receiver — Device that receives data from the bus. • Master — Component that initializes a transfer, generates the clock signal, and terminates the transfer. A master can be a transmitter or a receiver. • Slave — Device addressed by master. A slave can be a receiver or a transmitter. • Multi-master — Ability for more than one master to co-exist on the bus without collision or data loss. • Arbitration — Prearranged procedure that authorizes only one master at a time to take control of the bus. • Synchronization — Prearranged procedure that synchronizes the clock signals provided by two or more masters. • SDA — Data signal line (Serial DAta). • SCL — Clock signal line (Serial CLock). The SDA and SCL are bidirectional lines connected to a positive supply voltage via a current source or pull-up resistor. When the bus is free, both lines are high. Data on the IIC bus can transfer at rates up to 100 kbit/s in standard mode, up to 400 kbit/s in fast mode or up to 3.4 Mbit/s in high-speed mode. The number of devices connected to the bus depends on only the bus capacitance; the limit is 400 pF. 2.2 Bit Transfer The data on the SDA line must be stable during the clock’s high period. The SDA line’s high or low state changes only when the clock signal on the SCL line is low. See Figure 1. SDA SCL Data Line Stable Data Valid Change of Data Allowed Figure 1. Bit Transfer How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 2 Freescale Semiconductor IIC Bus Summary 2.3 START and STOP Conditions Within the IIC bus procedure, unique situations arise, which are defined as START and STOP conditions (see Figure 2). While the SCL line is high, a high-to-low transition on the SDA line is a START condition. While the SCL line is high, a low-to-high transition on the SDA line is a STOP condition. The master always generates the START and STOP conditions. The bus is free if the SDA and SCL lines remain at a high level after STOP and before START conditions. SDA SCL S P S = START Condition P = STOP Condition Figure 2. START and STOP Conditions 2.4 Bus Communication The bus transfer protocol is based on the byte transfers followed by an acknowledge bit (ACK). The byte transfer starts with the most significant bit (MSB) to the least significant bit (LSB). The SCL positive clock impulses clock each bit. The 9th SCL impulse clocks the ACK bit. Every bus transfer originates from a master device which sends the START condition to the bus. The the next consecutive bytes’ sequence depends on the data being transferred through the IIC bus. 2.5 Control Byte The control byte always follows the START condition. The control byte selects and activates specific devices on the bus; see Figure 3 for the control-byte structure. The first four bits represent the slave device’s control code. For example, the control byte for the serial EEPROM is A0 (control code is ‘1010’ binary). The next three bits represent the chip selects of the connected EEPROMs on the bus. The EEPROM uses these three bits for multiple device operations, but they are used as the higher bits of the internal EEPROM address if the memory address byte is wider than 8 or 16 bits. This address depends on the EEPROM capacity. For example, if the capacity is in the range of 16 kbits, these three bits represent the highest three bits of the address. The 8th bit is the R/W (read/write) bit. This bit determines the requested operation for the slave device: • If bit equals 0, this means a write operation • If bit equals 1, this means a read operation. The last 9th bit is the ACK bit and, in this case, always generated by the slave. How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 3 IIC Bus Summary Control Code S 1 0 1 Address Bits 0 A10 A9 A C K A8 RW Slave Address START Bit Read/Write Bit Acknowledge Bit Figure 3. Control-Byte Structure 2.6 Address Byte The address byte brings the address information to the slave device. This byte determines the real address in the EEPROM, to or from the data to be written or read. The address information structure depends on the connected EEPROM capacity. The EEPROMs up to 16 kbits use one address byte, but EEPROMs with higher capacity use two byte addresses (address H and address L). Address H is sent first. The structure of address bytes for a one-byte address are in Figure 4, and in Figure 5 for two byte addresses. The EEPROMs type 24C16 and 24C512 are used as communication devices. Control Byte Bus Activity Master SDA Word Address Data Byte S P A C K Bus Activity A C K A C K Figure 4. One Byte Address IIC Write Format Control Byte Bus Activity Master SDA Word Address H Word Address L Data Byte S Bus Activity P A C K A C K A C K A C K Figure 5. Two Byte Address IIC Write Format 2.7 Acknowledge The acknowledge bit (ACK) is the low-level impulse on the SDA line during the 9th pulse on the SCL line. The master always generates the SCL pulses. The receiver generates ACK pulses. This means in the write operation the slave device generates ACK after each byte transfers. In the read operation, the slave generates ACK when the control byte and address byte are sent from the master; the master generates ACK when it receives the data from the slave. How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 4 Freescale Semiconductor IIC Software Routines for MCUs 2.8 Read/Write Format There are two types of data transfers on the IIC bus: • Read from the slave • Write to the slave When the write operation executes, a data byte follows the address byte. This data byte contains the actual data to be written to the address in the address byte; see Figure 4 and Figure 5. When the read operation executes in the first part of the communication protocol: 1. The master writes the actual address to the slave. 2. The master sends the repeat START condition to the bus, followed by the control byte with R/W equal to 1. 3. The slave device sends ACK and immediately sends the actual requested data. See Figure 6 for the read-operation structure. Control Byte Bus Activity Master SDA Bus Activity S Word Address Control Byte 0 S A C K Data Byte 1 A C K P A C K N O A C K Figure 6. Read-Operation Structure See Figure 4, Figure 5, and Figure 6 for read- and write-byte operations. The second style of data transfer is page-write and page-read. For more information on these styles refer to the slave-device data sheet. 3 IIC Software Routines for MCUs Detailed descriptions of all IIC modules can be found in the MCU data sheet. A short review follows: • Address register — Used differently in the HC908 than in the S08 and S12 MCU types. In the HC908 core, the address register’s content is sent automatically after the START condition, and the data register content follows the condition. This address register also serves as its own IIC-slave address in slave mode. In the S08 and S12 core, the address register is active only in the slave mode and comprises its own IIC slave address of the MCU on the bus. This can be used by the multi-MCU connection on the bus. • Frequency divider register — Determines the SCL clock speed. The bus frequency acts as the source frequency for the IIC module. • Control register — Controls all IIC module functionality. • Status register — Comprises the information about the actual bus state. • Data register — Serves as the input and output point for all information transferred through the bus. How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 5 IIC Software Routines for MCUs 3.1 Initialization of the IIC The main task is to set the right speed of the SCL clock signal. These clocks are based on the bus frequency. The next task is to set the IIC module functionality — to use or not use the interrupt service routine, activate the IIC module, and set the slave mode. Refer to Example 1, Example 2, and Example 3. Example 1. Software for HC908 MCU (MC68HC908AP64 Used) void init_I2C (void) { MMCR1_MMEN = 1; MMCR1_MMCLRBB = 1; MMCR1_MMTXAK = 1; MMCR2_MMRW = 0; MMCR2_MMAST = 0; MMCR2_MMNAKIF = 0; MMCR2_MMALIF = 0; MMSR = 0; MMFDR = 3; } // Enable IIC; // Clear bus busy flag; // R/W bit = 0; // Slave mode actually; // Clear flags; // Clear all flags (Status register); // Set speed to 25kHz for Bus = 4MHz; Example 2. Software for 9S12 MCU (MC9S12DP256B Used) void { IBFD IBAD IBCR } Init_I2C(void) = 0x4C; = 0x00; = 0x80; // frequency divider register: Bus = 8MHz => SCL = 91kHz; // slave address of this module; // enable I2C module and No interrupts; Example 3. Software for the 9S08 MCU (MC9S08GB60 Used) void Init_I2C (void) { IIC1C_IIC1EN = 1; IIC1C_TXAK = 1; IIC1C_MST = 0; IIC1F = 0x99; IIC1S_SRW = 0; } // // // // // // Enable I2C; not generate ACK by master after transfer; Slave mode actually; Set speed to 50kHz for Bus = 18.8743MHz; 12.5k->0x39; 50k->0x99; 100k->0x59; R/W bit = 0; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 6 Freescale Semiconductor IIC Software Routines for MCUs 3.2 Write Function The write to slave at an address will be discussed first. To maintain this task, activate communication with the slave by sending the START bit followed by the slave-address byte. These bits’ content are discussed in Section 2.6, “Address Byte.” When the master sends the byte, the slave sends the ACK bit during the 9th SCL impulse. The slave must acknowledge each byte the master sends. The next byte (second byte) is the internal address of the memory array. This address can be one or two bytes, depending on memory size. The slave must acknowledge each byte the master sends. The third (fourth for large memory) is the data byte — this data will write to a specified address. The slave ACK follows this data byte. When the master receives this ACK bit, it generates the STOP bit. At this moment, the slave internally disconnects from the IIC bus and internally processes the write operation. While the slave processes the requested operation (write) it cannot answer the next master request. Therefore, the master must wait for the amount of time defined in the slave-device data sheet, or it must periodically send requests to the slave and test for the right answer (ACK from the slave). Example 4. Write Byte for HC908 MCU (MC68HC908AP64 and 24C16 Used) void I2C_write_byte (byte addr, byte wr_data) { MMCR2_MMRW = 0; // Set Write mode; MMADR = own_sl_addr; // set combined address of Slave for write; MMDTR = addr; // set address of Slave to read; //-------start of transmit bytes to IIC bus----MMCR2_MMAST = 1; // Start transfer - Master bit = 1; while (!(MMSR_MMTXBE)); // wait till data transferred; while (MMSR_MMRXAK); // wait for ACK from slave; //-----Slave ACK occurred-----------MMDTR = wr_data; // write data byte into EEPROM; while (!(MMSR_MMTXBE)); // wait till data transferred; MMDTR = 0xFF; // generate SCL impulse for slave to send ACK bit; while (MMSR_MMRXAK); // wait for ACK from slave; MMCR2_MMAST = 0; // STOP bit; } Example 6 and Example 7 are for a larger type of EEPROM (24C512). The word address is divided into two parts (two bytes): low byte and high byte, as defined in Example 5. How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 7 IIC Software Routines for MCUs Example 5. Word Address Divided into Low Byte and High Byte typedef union { word EE_Address; struct { byte Address_H; byte Address_L; }Bytes; }tAddr; tAddr sADDR; #define Address sADDR.EE_Address #define Addr_L sADDR.Bytes.Address_L #define Addr_H sADDR.Bytes.Address_H Example 6. Write Byte for 9S08 MCU (MC9S08GB60 and 24C16 Used) void IIC_write_byte(word addr, byte data) { Address = addr; // load address; temp = (Addr_H & 0x07) << 1; IIC1C_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0; IIC1C |= 0x30; // And generate START condition; //-------start of transmit first byte to IIC bus----IIC1D = IIC_SLAVE | temp; // Address the slave and set up for master transmit; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; while(IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1D = Addr_L; // Send low byte of the word address; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; while(IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1D = data; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; while(IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1S_IICIF=1; // clear the interrupt event flag; IIC1C_MST = 0; // generate STOP condition; } Example 7. Write Byte for 9S12 MCU (MC9S12XDT512 Used) void IIC_write_byte(word addr, byte data) { Address = addr; // load address; IIC0_IBCR_TXAK = 0; // TXAK = 0; IIC0_IBCR |= 0x30; // RX/TX = 1; MS/SL = 1; TXAK = 0; // And generate START condition; //-------start of transmit first byte to IIC bus----IIC0_IBDR = slavewrite; // Address the slave and set up for master transmit; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 8 Freescale Semiconductor IIC Software Routines for MCUs while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBDR = Addr_H; // Send high byte of the word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBDR = Addr_L; // Send low byte of the word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBDR = data; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBCR_MS_SL = 0; // generate STOP condition; } 3.3 Read Function The read function is similar to the write function. First, write the address (byte or word) into the slave. An ACK bit from the slave always follows these write cycles. When the address properly writes to the slave, the master generates the REPEAT START condition. Then, the master again sends the control byte but with the R/W bit equal to 1. This means the read-from-slave function. The ACK bit from the slave follows this byte. The master must then switch to receive mode and perform the read data from the IIC-data register (IICDR) function. This instruction generates the SCL pulses for the slave to send data from the requested address. There are two possible options: • If the master does not need the next data byte from the slave, it sends the NOACK (ACK = 1) and the STOP condition. • If the master wants to read the next data byte from the slave, it generates the ACK bit (ACK = 0). The slave recognizes this ACK bit and moves the internal address pointer to the next address. Then, the master performs the read data from the IICDR function to generate the next series of SCL pulses for the slave to send data. This sequence can perform infinitely. Example 8. Read Byte for HC908 Family (HC908AP64 Used) byte I2C_read_byte (byte addr)//output is byte "rd_data"; { MMCR2_MMRW = 0; // Set Write mode; MMADR = own_sl_addr; // set combined address of Slave for write; MMDTR = addr; // set address; //-------start of transmit first byte to IIC bus----MMCR2_MMAST = 1; // Start transfer - Master bit = 1; while (!(MMSR_MMTXBE)); // wait till data transferred; while (MMSR_MMRXAK); // wait for ACK from slave; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 9 IIC Software Routines for MCUs //-----Slave ACK occurred-----------MMCR2_MMRW = 1; // set read operation; MMCR1_REPSEN = 1; // enable repeat Start bit; MMCR1_MMTXAK = 0; // Master will generate ACK; MMCR2_MMAST = 1; // Start transfer - Master bit = 1; //------start of transmit Repeat start & "A1" to IIC bus------MMDTR = 0xFF; // send repeated start and combined address; while (!(MMSR_MMTXBE)); // wait till data transferred; while (MMSR_MMRXAK); // wait for ACK from slave; MMDTR = 0xFF; // send SCL clocks for the slave to send data; MMCR1_MMTXAK = 1; // Disable master ACK after read byte from Slave; while (!(MMSR_MMRXBF)); // wait till data received; rd_data = MMDRR; // read received data; MMCR2_MMAST = 0; // generate STOP bit - End of transfer; return rd_data; } Example 9 and Example 10 are for a larger type of the EEPROM (24C512). The word address is divided into two parts (two bytes): low byte and high byte (see Example 5). Example 9. Read Byte for 9S08 Family (MC9S08GB60 and 24C16 Used) typedef union { word EE_Address; struct { byte Address_H; byte Address_L; }Bytes; }tAddr; tAddr ADDR; #define Address ADDR.EE_Address #define Addr_L ADDR.Bytes.Address_L #define Addr_H ADDR.Bytes.Address_H byte IIC_read_byte(word addr) { Address = addr; temp = (Addr_H & 0x07) << 1; IIC1C_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0; IIC1C |= 0x30; // And generate START condition; IIC1D = IIC_SLAVE | temp; // Address the slave and set up for master transmit; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; while(IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1D = Addr_L; // Send low byte of word address; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; while(IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1C_RSTA = 1; // set up repeated start; IIC1D = IIC_SLAVE | temp | 1; // (slave_address) | (RW = 1); while (!IIC1S_IICIF); // wait until IBIF; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 10 Freescale Semiconductor IIC Software Routines for MCUs IIC1S_IICIF=1; // clear the interrupt event flag; while (IIC1S_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC1C_TX = 0; // set up to receive; IIC1C_TXAK = 1; // acknowledge disable; RD_data = IIC1D; // dummy read; while (!IIC1S_IICIF); // wait until IBIF; IIC1S_IICIF=1; // clear the interrupt event flag; IIC1C_MST = 0; // generate stop signal; RD_data = IIC1D; // read right data; return RD_data; } Example 10. Read Byte for 9S12 Family (MC9S12DT512 and 24C512 Used) typedef union { word EE_Address; struct { byte Address_H; byte Address_L; }Bytes; }tAddr; tAddr ADDR; #define Address ADDR.EE_Address #define Addr_L ADDR.Bytes.Address_L #define Addr_H ADDR.Bytes.Address_H void IIC_read_byte(word addr) { Address = addr; IIC0_IBCR_TXAK = 0; // TXAK = 0; IIC0_IBCR |= 0x30; // RX/TX = 1; MS/SL = 1; TXAK = 0; // And generate START condition; IIC0_IBDR = slavewrite; // Address the slave and set up for master transmit; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBDR = Addr_H; // Send high byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBDR = Addr_L; // Send low byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; //-----Slave ACK occurred-----------IIC0_IBCR_RSTA = 1; // set up repeated start; IIC0_IBDR = slaveread; // (slave_address) | (RW = 1); while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while (IIC0_IBSR_RXAK); // check for RXAK; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 11 IIC Software Routines for MCUs //-----Slave ACK occurred-----------IIC0_IBCR_TX_RX = 0; // set up to receive; IIC0_IBCR_TXAK = 1; // acknowledge disable; RD_data = IIC0_IBDR; // dummy read; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; IIC0_IBCR_MS_SL = 0; // generate stop signal; RD_data = IIC0_IBDR; // read right data; } Example 11 gives a routine for 9S12 MCU core and 24C512 EEPROM block-write and block-read functions. Example 11. Block-Write / Block-Read for 9S12 Core and 24C512 EEPROM (MC9s12XDT512 Used) void IIC_write_block(word addr, byte len) { byte page; Address = addr; // load address; page = len; // load length of data pack to be written; if(page > MAX_PAGE) page = MAX_PAGE; // set limit; IIC0_IBCR_TXAK = 0; // TXAK = 0; IIC0_IBCR |= 0x30; // RX/TX = 1; MS/SL = 1; TXAK = 0; // And generate START condition; IIC0_IBDR = slavewrite; // Address the slave and set up for master transmit; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBDR = Addr_H; // Send high byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBDR = Addr_L; // Send low byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; for(i=0;i<page;i++) { IIC0_IBDR = WRData[i]; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; } IIC0_IBCR_MS_SL = 0; // generate stop signal; } void IIC_read_block(word addr,word len) { byte dummy; Address = addr; length = len; if(length > MAX_LENGTH) length = MAX_LENGTH; IIC0_IBCR_TXAK = 0; // TXAK = 0; IIC0_IBCR |= 0x30; // RX/TX = 1; MS/SL = 1; // And generate START condition; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 12 Freescale Semiconductor IIC Software Routines for MCUs IIC0_IBDR = slavewrite; // Address the slave and set up for master transmit; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBDR = Addr_H; // Send high byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBDR = Addr_L; // Send low byte of word address; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while(IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBCR_RSTA = 1; // set up repeated start; IIC0_IBDR = slaveread; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; while (IIC0_IBSR_RXAK); // check for RXAK; IIC0_IBCR_TX_RX = 0; // set up to receive; dummy = IIC0_IBDR; // dummy read; for(i=0;i<length-1;i++) { while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; RDData[i] = IIC0_IBDR; // save data to RAM; } IIC0_IBCR_TXAK = 1; // acknowledge disable; while (!IIC0_IBSR_IBIF); // wait until IBIF; IIC0_IBSR_IBIF=1; // clear the interrupt event flag; IIC0_IBCR_MS_SL = 0; // generate stop signal; RDData[i] = IIC0_IBDR; // save data to RAM; } 3.4 Example with Interrupt Used This section shows two options when the IIC interrupt service routine is used: • MCU as master and write or read from slave used • MCU as slave on IIC bus 3.4.1 MCU as Master This routine is used when the main software loop cannot poll the IIC communication sequence. The first action executes in only the main loop; this is the first write into the IIC data register. The IIC-interrupt-service routine then maintains the whole communication. Example 12 explains how to set the MCU. Example 12. IIC-Module-Initialization Routine void Init_IIC(void) { IICF = 0; // IICA = 0; // IICS = 0x12; // IICC = 0xC0; // frequency divider register: Bus = 8MHz => SCL = 400kHz; slave address of this module; clear the IBAL and IICIF flags; enable IIC module with interrupt; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 13 IIC Software Routines for MCUs } Example 13 shows the Read_block and Write_block functions for the serial EEPROM 24AA256 and the MC9S08QG8 MCU in the main loop: Example 13. Read_block and Write_block Functions (24AA256 EEPROM and MC9S08QG8 Used) void IIC_read_block(word addr,byte len) { Address = addr; length = len; i = 0; // for interrupt only; IIC_Res_flg = 0; // for interrupt only; flag = 10; // defines receive function in the interrupt service routine; if(length > MAX_LENGTH) length = MAX_LENGTH; IICC_TXAK = 0; // RX/TX = 1; MS/SL = 1, TXAK = 0; IICC |= 0x30; // And generate START condition; IICD = IIC_SLAVE; // Address the slave and set up for master transmit; } void IIC_write_block(word addr, byte len) { Address = addr; // load address; length = len; // load length of data pack to be written; i = 0; // for interrupt only; IIC_Res_flg = 0; // for interrupt only; flag = 2; // defines transmit function in the interrupt service routine; if(length > MAX_PAGE) length = MAX_PAGE; // set limit; IICC_TXAK = 0; // RX/TX = 1; MS/SL = 1; TXAK = 0; IICC |= 0x30; // And generate START condition; IICD = IIC_SLAVE; // Address the slave and set up for master transmit; } The flag variable is byte variable used in the IIC interrupt service routine to recognize which byte of communication protocol is processed. Example 14 shows the read function from the serial EEPROM (24LC16B) and the MCU (S12DP256B) in the main loop. Example 14. EEPROM (24LC16B) and MCU (S12DP256B) in Main Loop void i2c_read_byte(unsigned char read_addr) { flag = 0; temp = read_addr; IBCR_MS_SL = 1; // Set transmit and master mode; IBCR_TX_RX = 1; // And generate start condition; IBDR = slave_IIC_addr; } How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 14 Freescale Semiconductor IIC Software Routines for MCUs The temp variable is a common byte variable; the flag variable is used in the IIC interrupt service routine to recognize which communication-protocol byte is processed. Then, the interrupt-service-routine code would be as shown in Example 15. Example 15. Interrupt-Service-Routine Code for MC9S08QG8 and 24C512 EEPROM __interrupt void isrViic(void) { IICS_IICIF = 1; // clear the interrupt event flag; switch(flag) { case 2: // TX mode; { IICD = Addr_H; // Send high byte of word address; flag++; return; } case 3: // TX mode; { IICD = Addr_L; // Send low byte of word address; flag++; return; } case 4: // TX mode; { if(length) { IICD = WR_Data[i]; length--; i++; return; } else { IICC_MST = 0; // generate stop signal; flag = 0; IIC_Res_flg = IIC_OK; // END of write cycle; return; } } case 10: { IICD = Addr_H; // Send high byte of word address; flag++; return; } case 11: { IICD = Addr_L; // Send low byte of word address; flag++; return; } case 12: { IICC_RSTA = 1; // set up repeated start; IICD = IIC_SLAVE | 1; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 15 IIC Software Routines for MCUs flag++; return; } case 13: { IICC_TX = 0; dummy = IICD; flag++; return; } case 14: { if(length > 1) { RD_Data[i] = IICD; length--; i++; return; } else if(length == 1) { IICC_TXAK = 1; RD_Data[i] = IICD; i++; flag++; return; } } case 15: { IICC_MST = 0; //RD_Data[i] = IICD; flag = 0; IIC_Res_flg = IIC_OK; return; } // set up to receive; // dummy read; // save data to RAM; // acknowledge disable; // save data to RAM; // generate stop signal; // save data to RAM; } } 3.4.2 MCU as Slave This routine is used when the MCU is presented as a slave device on the IIC bus. The MCU needs to catch all IIC bytes intended for it. The recognition of the valid bytes is based on the match of its own slave address saved in the IBAD register. If the master sends an address to the IIC bus, the slave generates an IIC interrupt when this address matches its own slave address in the IBAD register. Then, for example, the slave saves all bytes from the IIC bus to a RAM buffer and processes them later. Example 16 shows the slave MCU (S12DP256B) connected to a master MCU of the same type (two EVBS12DP256B boards connected together). The variables defined are: byte RD_data[20]; byte i2c_cnt, temp; How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 16 Freescale Semiconductor Conclusion Example 16. Slave-Initialization Routine void Init_IIC(void) { IBFD = 0x2B; IBAD = My_IIC_addr; IBCR = 0xC0; IBSR_IBAL = 1; } // // // // frequency divider register: Bus = 8MHz => SCL = 91kHz; slave address of this module; enable IIC module and interrupts, RX mode, Slave mode, ACK = 0; clear the IBAL flag; Example 17. Interrupt-Service Routine __interrupt void I2C_ISR(void) { if(IBSR_IAAS) { IBCR_TX_RX = IBSR_SRW; // and clear the IAAS bit; IBSR = IBSR_IBIF_MASK; // temp = IBDR; // i2c_cnt = 0; // } else { IBSR = IBSR_IBIF_MASK; // RD_data[i2c_cnt] = IBDR; // i2c_cnt++; } } 4 set Rx/Tx mode in accordance to received calling address byte clear the flag; dummy read to initiate the read data byte; clear the received data counter; clear the flag; save received data to data buffer; Conclusion This application note explains using the IIC module in Freescale’s HC908, 9S08, and 9S12 family MCUs. The user routines are tested on the mentioned MCUs and boards. The serial EEPROMs are often used as IIC devices and serve as good examples. If you need to use something other than an IIC device (for example, a real-time clock [RTC]), change the device address (0xD0 for RTC, 0xA0 for EEPROM) and manage the right byte sequence, as described in the appropriate data sheet. How to Use IIC Module on M68HC08, HCS08, and HCS12 MCUs, Rev. 2 Freescale Semiconductor 17 How to Reach Us: Home Page: www.freescale.com E-mail: [email protected] USA/Europe or Locations Not Listed: Freescale Semiconductor Technical Information Center, CH370 1300 N. Alma School Road Chandler, Arizona 85224 +1-800-521-6274 or +1-480-768-2130 [email protected] Europe, Middle East, and Africa: Freescale Halbleiter Deutschland GmbH Technical Information Center Schatzbogen 7 81829 Muenchen, Germany +44 1296 380 456 (English) +46 8 52200080 (English) +49 89 92103 559 (German) +33 1 69 35 48 48 (French) [email protected] Japan: Freescale Semiconductor Japan Ltd. Headquarters ARCO Tower 15F 1-8-1, Shimo-Meguro, Meguro-ku, Tokyo 153-0064 Japan 0120 191014 or +81 3 5437 9125 [email protected] Asia/Pacific: Freescale Semiconductor Hong Kong Ltd. Technical Information Center 2 Dai King Street Tai Po Industrial Estate Tai Po, N.T., Hong Kong +800 2666 8080 [email protected] For Literature Requests Only: Freescale Semiconductor Literature Distribution Center P.O. Box 5405 Denver, Colorado 80217 1-800-441-2447 or 303-675-2140 Fax: 303-675-2150 [email protected] Document Number: AN3291 Rev. 2 04/2007 Information in this document is provided solely to enable system and software implementers to use Freescale Semiconductor products. There are no express or implied copyright licenses granted hereunder to design or fabricate any integrated circuits or integrated circuits based on the information in this document. Freescale Semiconductor reserves the right to make changes without further notice to any products herein. Freescale Semiconductor makes no warranty, representation or guarantee regarding the suitability of its products for any particular purpose, nor does Freescale Semiconductor assume any liability arising out of the application or use of any product or circuit, and specifically disclaims any and all liability, including without limitation consequential or incidental damages. “Typical” parameters that may be provided in Freescale Semiconductor data sheets and/or specifications can and do vary in different applications and actual performance may vary over time. All operating parameters, including “Typicals”, must be validated for each customer application by customer’s technical experts. Freescale Semiconductor does not convey any license under its patent rights nor the rights of others. Freescale Semiconductor products are not designed, intended, or authorized for use as components in systems intended for surgical implant into the body, or other applications intended to support or sustain life, or for any other application in which the failure of the Freescale Semiconductor product could create a situation where personal injury or death may occur. Should Buyer purchase or use Freescale Semiconductor products for any such unintended or unauthorized application, Buyer shall indemnify and hold Freescale Semiconductor and its officers, employees, subsidiaries, affiliates, and distributors harmless against all claims, costs, damages, and expenses, and reasonable attorney fees arising out of, directly or indirectly, any claim of personal injury or death associated with such unintended or unauthorized use, even if such claim alleges that Freescale Semiconductor was negligent regarding the design or manufacture of the part. Freescale™ and the Freescale logo are trademarks of Freescale Semiconductor, Inc. All other product or service names are the property of their respective owners. © Freescale Semiconductor, Inc. 2007. All rights reserved. RoHS-compliant and/or Pb-free versions of Freescale products have the functionality and electrical characteristics as their non-RoHS-compliant and/or non-Pb-free counterparts. For further information, see http://www.freescale.com or contact your Freescale sales representative. For information on Freescale’s Environmental Products program, go to http://www.freescale.com/epp.
© Copyright 2024