The purpose of this project is to investigate concepts involving synchronous communications using a basic master-slave multi-drop network communications. The project uses the I2C protocol to communicate with the 24LC256 I2C™ CMOS Serial EEPROM.
|1||Digilent chipKIT™ Pro MX7 processor board with USB cable|
|1||MPLAB® X IDE|
|1||Digilent PmodCLP™ Parallel Character LCD|
|1||Logic analyzer (Digilent Analog Discovery™)|
|1||Microchip MPLAB® XC32 Compiler|
Communications are defined as the process or activity of exchanging information among devices. As discussed in Project 7, serial communications involve sending data one bit at a time, as opposed to Project 6, where eight bits of data are sent at a time to the LCD. One of the biggest motivations for implementing serial communications is to minimize the number of processor pins and wires needed to pass data between two points. The longer the physical distance between the end points, the more expensive the communications media becomes. However, there is a cost to this benefit. Serial communications almost always requires more time to send the same quantity of information.
This project will focus on the inter-integrated circuit interface (I2 C) protocol, which is only one out of a list of many interfaces. As supplemental information for project 8, the Serial Protocols list provides a partial list of the available serial protocols. You may ask, “Why so many serial protocols?” The simple answer is that the protocols are optimized for data rates, physical media, physical distance, and connectivity. Some protocols are strictly for point-to-point communications, such as the asynchronous serial communications used in Project 7. Other protocols are for multi-drop applications where many senders can be connected to many receivers—an Ethernet network is an example.
As the term implies, a transmitter communicates between a sender and a receiver using a synchronizing clock. The synchronizing clock can be a separate signal or a transition embedded into the data waveform.
The handshaking theory behind asynchronous and synchronous communication is essentially the same: Point B needs to know when a transmission from Point A begins, when it ends, and if it was processed correctly. However, the difference lies in how the transmission is broken down. Think of the difference in terms of a friendly chat. With asynchronous communication you would need to stop after every word to make sure the listener understood your meaning, and knew that you were about to speak the next word. With synchronous communication, you would establish with your listener that you were speaking English, that you will be speaking words at measured intervals, and that you would utter a complete sentence, or paragraph, or extended soliloquy, before pausing to confirm understanding. Further, you would establish with your listener beforehand that any extraneous noises you make during the speech or between speeches (coughing, burping, hiccupping, etc.) should be ignored. Clearly, the second approach is much faster, even though initializing communication may take slightly longer. In fact, by replacing the start, stop, and parity bits around individual words as used for asynchronous communications with start, stop, and control (processing instructions and error checking) sequences around large continuous data blocks, synchronous communication is about 30% faster than asynchronous communication, before any other factors are considered. See the Synchronous Serial Communication Overview1 for more information.
Fundamentally, a communications network is the connection of multiple devices to exchange information. A network system can consist of one device talking to many listeners (one-to-many) or many devices talking to one listener (many-to-one). A many-to-one system is characteristic of master-slave operations. A one-to-many is characteristic of a broadcast-based network. Peer-to-peer networks have many devices talking and listening, making a many-to-many network system.
Networks are characterized by multiple devices connected to shared data communication resources. Network communications can use the radio frequency (RF) spectrum, fiber optics (FO), electrical wires, and acoustic media such as air, water, or solid materials. Most often, network systems share a common resource—the media over which they communicate. If more than one sender exists on a network, there must be a mechanism to detect and arbitrate conflicts when two devices attempt to transmit at the same time. The master-slave networks with a single master that are described below do not require any form of arbitration.
It is common practice to model the processing of information as layers within software: each layer adding information or modifying the presentation of the information. Various network models have evolved over the years. The partitioning and activities represented by the seven-layer open systems interconnection (OSI) model are shown in Table 1. Network communications do not always require all seven layers of processing. Typically, embedded systems applications use layer 7, which represents a specific application; layer 3, which manages that device addressing; layer 2, which is used for error correction; and layer 1, which is responsible for controlling the electronics that modulate the communications media.
Table 1. Seven-level OSI model.
|Host layers||Data||7. Application||Network process to application.|
|6. Presentation||Data representation, encryption and decryption, convert machine-dependent data to machine-independent data.|
|5. Session||Inter-host delivery of packets between points on a network.|
|Segments||4. Transport||Reliable delivery of packets between points on a network.|
|Media layers||Packet /Datagram||3. Network||Addressing, routing and (not necessarily reliable) delivery of datagrams between points on a network.|
|Bit /Frame||2. Data Link||A reliable direct point-to-point data connection.|
|Bit||1. Physical||A (not necessarily reliable) direct point-to-point data connection.|
There are two kinds of operating modes for multi-drop or network configurations: master-slave and peer-to-peer. This represents processing in layer 2 of the OSI model. The master-slave mode of operation is characterized by one processor, acting as the master, controlling when slave devices are permitted to transmit information. Although multiple processors can be connected to a network, only one microprocessor is designated as the master at any given time. The master processor dictates the data direction and the timing of the data exchange between the master and slave nodes. Project 6 is an example of a master-slave operation where the microprocessor communicates with the LCD unit.
Peer-to-peer communications allow data exchange at any time and between any two communications devices, or nodes, and communications can be initiated by any node at any time. An example of peer-to-peer is in Project 7, where the PIC processor communicates with a PC running a terminal emulation application.
However, neither Project 6 nor Project 7 are examples of a network, because only two nodes are communicating. Point-to-point communications refers to communications that are limited to be exclusively between two endpoints or nodes.
One of the responsibilities of layer 1 in the OSI model is controlling the timing of the communications. Depending on the communications electronics hardware, both master-slave and peer-to-peer configurations can be implemented using half- or full-duplex connections. The distinction between the two duplex operations is that for half-duplex, nodes can both send and receive simultaneously; whereas full-duplex allows simultaneous sending and receiving.
I2C (inter-integrated circuit communications) and SPI (serial peripheral interface) are examples of master-slave networks supported directly by hardware in many microprocessors. I2C is a half-duplex scheme where the slave devices are enabled or selected by encoding data in a message sent by the master. SPI uses master-controlled dedicated device select signals, along with separate data send and receive signals, to enable simultaneous communications (full-duplex) between the master and a specific slave device.
Synchronous and asynchronous communications pertain to the individual symbol or bit timing and are controlled at level 1 in the OSI model. Project 6 investigated communications involving asynchronous communications. Although some references might claim that asynchronous communications takes place outside of real-time, this does not mean that timing is not critical to the transmission of data. Each data symbol is uniform in period and has critical timing requirements. In digital communications, symbol rate (also known as baud or modulation rate) is the number of symbol changes (waveform changes or signaling events) made to the transmission medium per second, using a digitally modulated signal or a line code. The symbol rate is measured in baud or symbols/second. Each symbol can represent or convey one or several bits of data. The symbol rate is related to, but should not be confused with, the gross bit rate expressed in bits/second. See Symbol Rate for more information.
Asynchronous communications rely on the fact that both sending and receiving devices are using clocks that are derived from independent oscillators resulting in clock frequencies that are a few percent different from each other. To compensate for differences in an oscillator's frequencies, asynchronous communications requires frequent clock synchronizing. As we saw in Project 6, the start bit of each byte received is used to synchronize the receiver’s clock. For asynchronous communications, the only part of the communications that is not time critical is the inter-byte period time between the first stop bit and the next start bit.
Synchronous communications use a separate signal or characteristic of the bit wave form to implement that handshaking, indicating when the receiving device should sample the input to determine the symbol value. As such, each symbol can have differing and arbitrary periods. Although synchronous communications are generally characterized as bit streams that require no start and stop bits, most implementations of synchronous communications use some mechanism to partition the data into segments. As you will see from the discussion below, the I2C protocol uses a 9-bit partition for each data byte (8 bits of information).
The I2C protocol was developed in the early 1980s by Philips Semiconductors. Its original purpose was to provide an easy way to connect a CPU to peripheral chips in a TV-set. The original specification supported data rates of up to 100 Kbits/s. Conventional hardware now supports up to 400 Kbits/s. Based on the previous discussion, you will readily see that the I2C protocol implements a half-duplex master-slave synchronous network.
At any one time, there is only one active master and one or more slave devices. Although slave devices can assert a degree of control over the clock signal, the master is designated as the device that asserts the clock signal, indicating when the data signal line should be read by all slave devices or when a slave device should assert control over the data signal line. Each slave device has a unique device identification number. The data is always sent as 8-bit unsigned characters. An I2C message is always initiated with a start signal and terminated with a stop signal that the master controls. The I2C message can be an arbitrarily long set of data bytes. Each byte of data exchanged between the master and slave device is acknowledged by the receiving master or slave.
Figure 1 shows the general format of an I2C message. There are two signals used in the I2C protocol: the serial clock signal (SCL) and the serial data signal (SDA). Other than the start and stop sequences, the SDA is not allowed to change states while the SCL signal is high. When the I2C communications is in an idle state, both the SCL and the SDA signals are in the high state.
The Master always initiates communications with all slave devices that share the SDA and SCL signals by generating a start sequence. The master causes the SDA signal to make a high to low transition while the SCL signal is high. The master must assert the SCL signal low before the process of sending data begins. Data bits are sent by asserting the SDA signal high or low, followed by asserting the SCL signal high for a specified interval of time. The most significant data bit is sent first.
The master always sends the first 8 data bits that consist of a 7-bit slave device address, identified as A7 through A1 in Fig. 1 and a control bit, R/!W, that specifies the direction of data flow for successive communications. The R/!W bit is low if subsequent data is to be written from the master to the slave device. If the R/!W bit is high, then subsequent bits of data are read from the slave.
Each slave device has, within the device's hardware, a unique identification number. The device that has the identification number that matches the device address field sent from the master will acknowledge the first byte in the I2C message with an ACK bit. The microprocessor serving as the I2C master will terminate communications if no acknowledgement is generated after any 8-bit data transfer from the master to the slave. The communications message is terminated by generating a stop sequence as follows: the SDA signal is set to the high state. Then, the SCL signal is set to a high state. Finally, the SDA makes a low to high transition.
I2C networks consist of a data signal (SDA) and a clock signal (SCL) that have a common reference—usually digital ground. A pull-up resistor to VDD is required to be connected to each signal line. Both clock and data signals are connected in a wired-AND configuration that requires an open collector (also called open drain for CMOS transistors) outputs from both master and slave devices. The output of both devices must be in the open collector state for the signal line to be in the high state (also called the recessive state). The SDA or SCL line is low if the output transistor of either the master or any slave device pulls the signal low. The low state is also referred to as the dominant state. As shown in Fig. 3, both slave and master devices can always determine the state of the SCL or SDA lines by reading the value of the output pin.
As stated above, the SDA cannot change while the SCL is high, except to implement the START and STOP sequences. As illustrated in Fig. 3, a start sequence is generated when the SDA line makes a recessive to dominant transition when the SCL line is in the recessive state. Figure 5 shows that a STOP sequence is generated when the SDA signal transitions from the dominate state to the recessive state while the SCL line is in the recessive state. Figure 5 shows that data is either written to the slave or read from the slave during the period identified as 2 to 3. The master or slave (depending on whether it is a write or read operation) is allowed to change the state of the SDA line while the SCL line is in the dominant state identified as 1 and 4 in Fig. 5. Figure 6 shows an acknowledge sequence that is generated by the slave after the master writes a byte of data or is generated by the master after the master reads a byte of data from the slave.
No ACK bit is generated if the SDA line is not pulled to the dominate state by either the master or the slave during the ninth clock pulse. There are two uses of a no ACK condition. When a master intends to terminal read sequence, it will not generate an ACK. This is called a NACK condition and does not constitute an error condition. The second use of a NO ACK is when the slave fails to pull the SDA to the dominate state during the ninth SCL pulse. This is an error condition and is detectible by the master. Possible reasons for a NO ACK condition are that the slave is not connected to the I2C lines, the incorrect device address was sent by the master, or that the slave device is not functional.
Figure 7 shows a conventional I2C network connection between the master and one or more slave devices. The architecture is classified as a bus network. All devices on the network share the same physical communications medium.
Slower slave devices can synchronize high speed masters by asserting control over the SCL signal. The master generates its own clock on the SCL line to transfer messages on the I2C-bus. Data is only valid during the HIGH period of the clock. A well-defined clock is thus needed for the bit-by-bit arbitration procedure to take place.
I2C clock synchronization is performed using the wired-AND connection of I2C interfaces to the SCL line. As soon as the master asserts the SCL line in the recessive state, a slave device that wants to slow the master down simply holds the SCL line in the dominate state until the slave determines when to release the SCL line to the recessive state. Meanwhile, the master always reads of the SCL I/O pin and doesn’t start the I2C clock cycle until it detects the SCL line in the recessive state. Thus the slowest device on the I2C network is able to dictate the maximum data transfer rate.
I2C technology allows for multiple masters to operate on a single I2C network, as shown in Fig. 8. As stated previously, the controlling master asserts the state of the SCL line. Hence, the master that is not controlling the SCL line must behave like a slave device. Each master must be able to implement an arbitration scheme that dictates that if two devices start to communicate at the same time, the one writing more zeros (dominant bits) to the bus wins the arbitration, and the other master device immediately discontinues any operation on the bus. The second requirement is that each master device must be able to detect when the network is in use by another master. Each potential device must detect an ongoing bus communication and must not interfere with it. This is achieved by recognizing traffic and waiting for a stop condition to appear before starting to transmit on the bus. Figure 9 shows a timing diagram where two master devices attempt to simultaneously access the same slave device. The SCL signals will be automatically synchronized according to the process described above for slow slave devices. A bus conflict will be detected by the master device that attempts to send a recessive bit but detects the SDA line in the dominate state, as shown for CPU2. At this point, CPU2 places its SCL and SDA outputs in the recessive state and continues to monitor the SCL line. After there has been no activity on the SCL line for a predetermined length of time, CPU2 will attempt to assume control of the I2C bus once again.
EEPROM stands for electrically erasable programmable read only memory. It is a form of non-volatile memory used in many computer-based systems (including PCs) to store configuration settings and other data that must be remembered from one power up cycle to the next. The memory must be retained even if the power has been removed from the device. In this project we will be interfacing with the 24LC256 EEPROM. The value 256 in the part name indicates that the device is capable of storing 256 k bits of data organized as 32768 bytes. Pay special attention to Section 6 of the 24LC256 data sheet before writing the code to write data to the EEPROM, and in particular the control flow diagram in Fig. 7 of that data sheet. This data sheet should be studied closely before continuing on with project.
Drivers take care of the nitty-gritty details required to interface user software to peripheral computing ICs and devices. With a little extra effort, code that you have already developed could be packaged as drivers. Examples of possible drivers are the software delay function, the stepper motor step FSM, the LCD interface, and even the button decoding function. For this project, you will generate code in a file called I2C_EEPROM_LIB.c that provides multiple byte read and write access to the 24LC256 EEPROM.
Microchip® provides example code for a PIC32 I2C interface with a 24LC256 EEPROM as well as the application note, AN735, concerning I2C communications using PIC processors (not PIC32). The PIC32 I2C example code will serve as the basis for this project. You will be required to repackage the code to create a device driver for the 24LC256 serial EEPROM according to the driver specifications below. The Microchip example code uses the PIC32 I2C1 port, whereas the chipKIT Pro MX7 uses the PIC32 I2C2 port to interface to the on-board 24LC256 EEPROM. Note that the example code writes less than one page of data to the EEPROM starting at a page boundary. The driver that you will produce will not be so constrained, in that you will be able to start at any address and store any amount of data up to the capacity of the EEPROM (32 K bytes).
This project requires you to create a library file to provide read and write access to the 24LC256 EEPROM. Along with the functions that are in the library file, you will generate an applications file called Project8.c that will write a block of data to the EEPROM, read it back, and check the each byte written to the EEPROM matches the bytes read back. You will report the success or failure of the write/read operation on the LCD. The specifications of the functions in the I2C_EEPROM_LIB.c file that you will generate the functions that are described below.
EEPROM device driver specifications:
The I2C EEPROM interface can be organized as shown in the collaboration diagram in Fig. 10. The code functionality is partitioned to maximize code reuse. Table 2 describes the operation of each function depicted in Fig. 10. It is worth noting that the functions shown on the bottom row of Fig. 10 could be moved to a separate I2C driver file that would allow other driver applications to be developed using those common I2C port interface files.
For tutorial purposes, Microchip provides I2C example C code that uses the XC32 peripheral library. This example code was developed for a different hardware platform and must be modified before it can be run on the chipKIT Pro MX7. The example code is located on the XC32 installation drive at:
Software control flow diagrams for the eight functions are provided in Figs. 11 through 19 below. The significant challenge in completing this project is generating the code for the eight functions that are needed for the I2C EEPROM interface. All eight functions will be placed in files called I2C_EEPROM.c and I2C_EEPROM.h. Both the Project 8 application file and the I2C_EEPROM.c must contain the directive #include “I2C_EEPROM.h.” Refer to the source for guidelines to proper method to write an include file. An example header file is shown in the I2C_Header File link available to the right. The rest of the links in the related material section provide the code for the functions depicted in the bottom row of Fig. 10.
Using the interface descriptions shown in Table 2 and the software control flow diagrams shown in Figs. 12, 17, and 18, complete the functions to implement the code for the functions I2CReadEEPROM, I2CWriteEEPROM, and I2C_wait_xfer.
Table 2. I2C software functions for EEPROM interface.
|Functions Name||Purpose||Call Arguments||Return||Dependencies||i2cinit||Sets master bit rate and opens I2C port||I2C Port #||None||Defined bit rate, XC32 peripheral library functions|
|I2CReadEEPROM||Reads block of EEPROM memory||I2C Port #, Device ID, EEPROM Address, *Data Pointer, # of bytes to read||I2C xfer Result||I2C_start_xfer, I2C_write_1_byte, I2C_read_1_byte, I2C_stop_xfer, XC32 peripheral library functions|
|I2CWriteEEPROM||Writes block of EEPROM memory||I2C Port #, Device ID, EEPROM Address, Data pointer, # of bytes to read||I2C xfer Result||I2C_start_xfer, I2C_write_1_byte, I2C_stop_xfer, XC32 peripheral library functions|
|I2C_wait_xfer||Waits for page of data to be transferred to the FLASH memory||I2C Port #, Device ID||Iteration Count to ACK received||XC32 peripheral library functions|
|I2C_start_xfer||Generates a I2C start sequence||I2C Port #, ACK / NACK flag||BOOL—Success / Fail||XC32 peripheral library functions|
|I2C_stop_xfer||Generates a I2C stop sequence||I2C Port #||None||XC32 peripheral library functions|
|I2C_write_1_byte||Writes a single byte of data||I2C Port #, Data Byte||BOOL—Pass/Fail||XC32 peripheral library functions|
|I2C_read_1_byte||Reads a single byte of data||I2C Port #, *Data byte ACK / NACK flag||BOOL—Success / Fail||XC32 peripheral library functions|
What information is necessary to be able to use the EEPROM read and write function? Take the position from someone other than the author who might use the driver.
What are the limitations to using this driver on an EEPROM other than the 24LC256?
Ignoring the first byte, determine the I2C read data rate.
Using the core timer, determine the effective I2C data write rate for 100 Bytes of data.