One Bit at a Time Part 5 (PIC Microcontroller)

START

This subroutine releases both the SCL and SDA lines which are then pulled high to ensure the bus is in its Idle state for the minimum duration 1.3 us tBUF. Bringing SDA low gives the characteristic Start , which is followed by a 0.6 us delay to implement tHD;STA (see Fig. 12.17) before the subroutine exits with both SCL and SDA low.

Program 12.7 Low-level I2C subroutines.

Program 12.7 Low-level I2C subroutines.

STOP

The Stop condition is implemented by ensuring that both SCL and SDA lines are low (which should be the case after an Acknowledge condition) and then releasing the SCL line which is then pulled high. After a 0.6us delay to implement tSU;STO SDA is released to give the characteristic Stop _/ . The subroutine exits with both lines released and the bus Idling in preparation for the next Start condition. I2C_OUT

This subroutine clocks out the eight bits placed in DATA_OUT by the caller, MSB first, and then checks that the Slave has Acknowledged the transaction.

The first part of this process is implemented by repetitively shifting the datum in DATA_OUT and inspecting the Carry flag. SDA is set to mirror C and the SCL line toggled to accord with the tLOW and tHIGH parameters illustrated in Fig. 12.17.


Once the loop count reaches zero, the Data line is released with SCL low for the duration tLOW. SCL is then released high and the state of SDA, which should have been dragged low by the Slave, checked. If not low, the No ACKnowledge (NACK) situation is returned with ERR = 01 h; otherwise it will be zero.

Our use of errors here is very rudimentary. For instance, errors can also occur if some other device has locked either line low; that is the bus is busy.

We have not coded a Master-Receive I2C counterpart to subroutine I2C_OUT, as the MAX518 only demands a Master-Transmit data interchange. However, Program 12.14 gives the I2C_IN mirror.

As our example we will send the contents of File 20h to the MAX518 Channel0 and then the contents of File 21 h to Channel 1; at that point updating both DAC registers and hence simultaneously outputting the analog equivalent of File 20h to pin Vout0 and File 21 h to pin Vout1. We assume that both AD0 and AD1 pins are connected to Ground.

Our implementation will involve the transmission of a packet of five bytes of information sandwiched between a Stop and a Start condition.

1. Start condition.

2. Address byte: 01011000k Slave address 01011(00), Write.

3. Command byte 1: 00000XX0b

No ReSeT, no Power Down, Channel 0.

4. Data byte 1: Contents of File 20h.

5. Command byte 2: 00000XX1k

No ReSeT, no Power Down, Channel 1.

6. Data byte 2: Contents of File 21 h.

7. Stop condition.

Program 12.8 Interacting with the MAX518 dual-channel I2C DAC.

Program 12.8 Interacting with the MAX518 dual-channel I2C DAC

The listing of Program 12.8 follows our itemization exactly. On return from each call to I2C_OUT the Error datum is tested for zero. If non zero then the process is restarted. Repeated Starts are allowed by the I2C protocol. However, if there was a hardware fault with the bus or Slave then this process would continue indefinitely. Thus, for robustness a time-out mechanism should be implemented to prevent hang-ups.

Although the basic Synchronous Serial Port fully implements most I2C Slave functions, there is little support for the role of Master.7 However, if a PIC with an integral SSP is to be used as a Master then it is advantageous to use pins RC3 and RC4 for SCL and SDA respectively. With the SSP enabled and programmed in Mode 11 (Slave idle – see Table 12.1) these pins conform to the specified relatively slow (300 ns maximum) rise and fall times. A normal port line has transition times of the order of 10 ns. The slower transition times give less cross talk between bus lines and less transmission line reflections at electrical discontinuities.

As in the case for the SPI protocol, many C compilers targeted to the PIC have built-in functions to implement the I2C protocol and avoid bit banging user-defined functions.

To illustrate the technique, consider Program 12.9 which replicates the assembly-level coding of Programs 12.7 and 12.8 using the CCS compiler.

tmp9240_thumb222[2]

Generates the Master Start condition.

tmp9241_thumb222[2]

Generates the Master Stop condition.

tmp9242_thumb222[2]

Reads a byte over the bus. If an optional parameter of 0 is used then the Master will not Acknowledge the received data.

Program 12.9 Interfacing to the MAX518 in C.

Program 12.9 Interfacing to the MAX518 in C.

This is a directive by which the programmer informs the compiler which pins are used for the I2C lines, the fast or standard protocols and Master or Slave mode. The SSP hardware can be designated for the latter situation.

The key characteristic of the various serial protocols discussed up to now is that a clock signal is transmitted by the Master, which allows the Slave to receive or transmit data in perfect synchronization. An alternative approach is to send data under the assumption that the transmitter and receivers are running at approximately the same frequency. This asychronous protocol has been in use for data communications system for over a century to send alphanumeric data over telegraph, telephone and radio links to implement the Telex system.

tmp9244_thumb222[2]

Sends a single byte over the bus.

tmp9245_thumb222[2]

One of the features of early computer development in the 1940/1950s was the extensive use of existing technology. An essential adjunct of any computer-oriented installation is a data terminal. At that time the communications industry made considerable use of the teletypewriter (TTY).9 Serial data were converted between serial and parallel formats in the terminal itself as well as providing keyboarding and printing functions.

Transmitting the message string "PIC" in the asynchronous serial mode, with odd one's parity and a minimum of one stop bit.

Fig. 12.18 Transmitting the message string “PIC” in the asynchronous serial mode, with odd one’s parity and a minimum of one stop bit.

Until the early 1980s, TTYs were electromechanical machines, driven by a synchronous electric motor. This meant that synchronization between remote terminals could only be guaranteed for short periods. To get around this problem, each word transmitted was proceeded by one Start bit and followed by one or more Stop bits. A typical example is shown in Fig. 12.18. While the line is idling, a logic 1 (break level) is transmitted. A logic 0 signals the start of a word. After the word has been sent, a logic 1 terminates the sequence. Electro-mechanical terminals typically print ten characters per second, and require a minimum of two Stop bits. This requires a transmission rate of 110 bits per second, or 110 baud.8

The first purely electronic terminals required only one Stop bit, and could print at 30 characters per second, giving a rate of 300 baud. Traditionally communication channels use multiples of 300; eg. 1200, 2400, 4800, 9600…. PC serial ports can run up to 19,200 baud. However, this X300 rate is not necessary as long as receiver and transmitter are running at the same nominal rate.

Typically a receiver on detecting an incoming datum will try and sample each bit at approximately mid point. This means that a frequency drift of ±0.5 bit time can be tolerated in the space of ten bits. Thus the receiver and transmitter local clocks must be within ± 5%. The two will be resynchronized at the start of each datum.

Although not the most efficient of techniques, the asynchronous protocol outlined here has the major advantage of being an international standard. There are several variants; for instance the word can typically be from five to nine bits long. In our example the word length is eight bits with the eighth bit being used to provide a limited error checking capability. This parity bit is set in our example so that the number of 1 s in the word is always odd. This can be checked at the receiver  to detect a single bit error.

The original teleprinter code developed by Emile Baudot in 1875 is only five bits long.9 Here the string “PIC” is coded as 10110 00110 01110. Although limited in capability, its key advantage over Morse code (Samual Morse, 1840) was its fixed length which considerably simplifies the design of the transmitter and receiver. However, Morse code is more efficient as the number of bits is approximately inversely proportionally to a letter’s statistical frequency of use.

The 7-bit ASCII code of Table 1.1,first adopted in 1963, was the first code specifically developed for computer communication systems. In 8-bit systems the extra 128 code patterns is usually utilized to add a selection of accented, mathematical and graphic symbols rather than for parity. However, parity can be accommodated by using a 9-bit word format.

For our example we have adopted a format of one Start, eight data with no parity and one Stop bit. Using a bit banging approach, as we have already done for our SPI and I2C protocols, is straightforward provided that we have an accuratetmp9247_thumb222[2]delay. For example, for a 4800baud link this would be 104 us. As the delay is so short we can use an in-line approach using a macro in the same manner as in Program 12.6 rather than the subroutine approach of Program 6.8.

Program 12.10 A baud-rate delay macro showing a half 9600baud period delay at 20MHz evocation.

Program 12.10 A baud-rate delay macro showing a half 9600baud period delay at 20MHz evocation.

The macro shown in Program 12.10 is designed to give a suitable bit delay for a range of baud rates from 1200 through 9600 and crystal frequencies of 4 through 20 MHz. Both BAUD and XTAL constants are defined in the program head by the programmer; the example given in the listing showing a baud rate of 9600 and crystal frequency of 20 MHz.

The kernel of our macro is the decrement loop:

tmp9249_thumb222[2]

which gives a total of 4K cycles delay, where each cycle is 4/XTAL microseconds. This can be increased by padding with nop instructions, each adding K cycles to the total.

For any given baud rate we requiretmp9250_thumb222[2]microseconds for a | bit period delay; so to evaluate the value of K we need to calculate the total number N of 4/XTAL cycles.

tmp9251_thumb222[2]

In the macro of Program 12.10 N has been defined accordingly. To determine the constant to be loaded into W at the beginning of the loop this value is divided by the total delay cycles in the loop. For example, if XTAL is greater than 12 MHz then the five extra nop instructions bring the total delay to nine cycles, hence the initial constant K is N/9. Actually the value of K is can be reduced by around 2% to compensate for the instructions outside the macro; hence the use of 980,000 in Program 12.10 in the definition of N rather than 1,000,000 (106).

Notice the use of the local directive to qualify a label inside a macro; in this case BAUD_LOOP. This ensures that when the macro is used several times, the assembler will not object to the same named label appearing more than once in the one program.

With our delay macro in situ, the basic input/output subroutines of Program 12.11 are similar to our bit banging SPI subroutines. The PUTCHAR subroutine simply brings the TX pin low for two Baud_de1ay periods and then toggles the pin eight times mirroring the data in DATA_OUT least-significant bit first – the opposite order to SPI/I2C. Finally TX is held high for the same period to give the Stop/Idle condition.

The input GETCHAR counterpart is more complex. After an Idle state a low-going voltage at pin RX will be treated as a Start bit. However, if the data stream is sub sequentially sampled at intervals of one bit period (two evocations of Baud_de1ay) then as this is just at the transition point of the transmitter, any drift in the two clock rates may cause errors. To avoid this, a half bit period is evoked and then the state of RX checked to ensure that the Start bit is still present. If it is, then subsequent samples are taken at two Baud_de1ay periods, which is approximately at the bit center point. Better noise rejection could be obtained by sampling at a higher rate and then taking a majority decision regarding the logic state of the incoming voltage.

Program 12.11 Asynchronous formatted input and output subroutines.Program 12.11 Asynchronous formatted input and output subroutines.

After the eight data bits have been shifted into DATA_IN, the Stop bit is checked for 1. If Stop is 0 then a Framing error has occurred. This is signalled by returning a value of -1 in ERR. Other more elaborate schemes may return a variety of error types. For example, where parity is used then a Parity error can be returned.

Next post:

Previous post: