Файл: The quintessential PIC microcontroller (S. Katzen, 2000).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 15.06.2025

Просмотров: 5359

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

12. One Bit at a Time 329

In all cases the Stop condition updates the analog outputs according to the commands and data byte. If there have been several Command:Data byte pairs since the last Stop then the most recent command and data are reflected in the state and output of the device.

In order to interface to the MAX518 we will need to design subroutines to send out a Start condition, a Stop condition and a Master-Write byte. See Program 12.14 for a Master-Read subroutine. To design the device driver we need to look more closely at the time relationship between Clock and Data signals, which generally are more tightly defined than in the SPI protocol.

Stop

Idle

Start

tSU;STO

tHD;STA

tLOW

tHIGH

tSU;DAT

SCL

1300 ns

600 ns

tBUF

1300 ns

600 ns

600 ns

100 ns

SDA

Fig. 12.17 Minimum timing relationships for the Fast I2C mode.

The MAX518 and most current I2C-compatible devices are designed to the Fast mode specification and the figures used in Fig. 12.17 relate to this 400 kHz clocking rate. Of particular note is the requirement that the clock

SCL should be held high not less than 0.6 µs (tHD;STA) after the active \ of SDA to signal a Start condition. Similarly, a Stop condition requires

that the clock be set up high at least 0.6 µs (tSU;STO) before the active / of SDA. A minimum of 1.3 µs is required with the bus free (tBUF) in the Idle state between a Stop and a following Start condition. These requirements

allow time for the Slave devices to detect these synchronizing events without ambiguity.

During a data byte transmission the clock should be low no less than

1.3 µs (tLOW) and high no less than 0.6 µs within the 2.5 µs overall duration limitation imposed by the 400 kHz. Data changes only when the clock is

low, and any change should be complete no less than 100 ns (tSU;DAT) before the clock goes high.

Not shown in the diagram is the maximum rise and fall times which should not exceed 300 ns with a maximum bus capacitance of 400 pF. To keep within this transition restriction the pull-up resistors of Fig. 12.14 should not be more than 1.8 kΩ with this value of capacitance. With short


330 The Quintessential PIC Microcontroller

bus runs and few Slave devices this value of resistance can be increased by up to a factor of ten to reduce energy dissipation when an output pin is low.

In implementing the I2C timings, a PIC with a crystal above 3.2 MHz, with an execution time of less than 1.25 µs, may need to insert short delays between actions. For example, a 20 MHz crystal driven PIC implementing the instruction pair:

bcf

TRISA,SCL

;

Drag Clock low by making pin an output to logic 0

bsf

TRISA,SCL

;

Float clock high by making pin an input

would give high and low durations of only 0.2 µs. Short delays are conveniently implemented using nop (No OPeration) instructions; each taking one instruction cycle (Fosc/4). For example, to give a nominally 400 kHz clock at 20 MHz we have:

bcf

PORTA,SCL

; Clock low

nop

; 0.2us

nop

; 0.4us

nop

; 0.6us

nop

; 0.82us

nop

; 1.0us

nop

; 1.2us

bsf

PORTA,SCL

; Clock high

nop

; 1.6us

nop

; 1.8us

nop

; 2.0us

nop

; 2.2us

nop

; 2.4us

nop

; 2.6us

Of course slower clock speeds require less nops but rather than tailor our subroutines for one particular crystal we will use the assembler macro called Delay_600, coded in Program 12.6, that will expand to the appropriate number of nops to give a nominal 600 ns (0.6 µs) delay, depending on the value of the constant XTAL defined by the programmer at the head of the source file.

For example to alter the coding of Program 12.7 to suit a 12 MHz crystal system then the one line #define XTAL 20 should be altered to #define XTAL 12 and the program reassembled.

The coding of Program 12.6 makes use of the conditional assembly directive if – endif. This is similar to the C language statement if(true){do this;} of page 249 in that all instructions down to the following endif are implemented if the argument of the if directive is true. For example, if((XTAL>6)&&(XTAL<=13)) states that if the constant XTAL is greater than 6 AND less than or equal to 13 then insert


12. One Bit at a Time 331

Program 12.6 A crystal frequency-independent short delay macro.

Delay_600 macro

; Delays by nominally 0.6us

if (XTAL <= 6)

nop

; One nop if XTAL is less than 6MHz

endif

if ((XTAL > 6) && (XTAL <= 13))

nop

; Two nops delays if

nop

; XTAL is between 6 & 13MHz

endif

if (XTAL > 13)

nop

; Three nop delays if

nop

; XTAL is above 13MHz

nop

endif

endm

two nop instructions. At 13 MHz this will be approximately 600 ns. In practice, extra delays will be introduced by instructions toggling the bus lines and executing housekeeping tasks. Thus some fine tuning can be undertaken if maximum speed is a criterion.

Based on the macro of Program 12.6 and the following initialization code:

include

"p16f84a.inc"

#define

XTAL 20

SCL

equ

0

SDA

equ

1

MAIN

movlw

TRISA

; Set up the File Select Register

movwf

FSR

; to point to TRISA

bcf

PORTA,SCL

; Preset Clock & Data pins to 0

bcf

PORTA,SDA

; so that line can be dragged low

bsf

INDF,SCL

; Float Clock line high

bsf

INDF,SDA

; and the Data line to Idle state

which assumes that we are using Port A bits 0 and 1 of a 20 MHz PIC16F84A to implement our SCL and SDA lines, we can code the three subroutines outlined in Program 12.7 to allow us to communicate with the I2C MAX518.

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 µs tBUF. Bringing SDA low gives the characteristic Start \ , which is fol-

lowed by a 0.6 µs delay to implement tHD;STA (see Fig. 12.17) before the subroutine exits with both SCL and SDA low.


332 The Quintessential PIC Microcontroller

Program 12.7 Low-level I2C subroutines.

; *************************************************************

; *

FUNCTION:

Outputs the Start

condition

*

;

*

ENTRY

:

FSR points to the

I2C port’s

TRIS

register

*

;

*

EXIT

:

Start condition and SCL, SDA

pins

low

*

; *************************************************************

START

bsf

INDF,SDA

; Ensure that we start with the

bsf

INDF,SCL

; Data and Clock lines pulled hi

Delay_600

; 1.3us delay in Idle state

Delay_600

bcf

INDF,SDA

; Low-going edge on Data line

Delay_600

; Wait for Slave to detect this

bcf

INDF,SCL

; Exit with the Clock line low

return

; *************************************************************

; *

FUNCTION:

Outputs the Stop condition

*

;

*

ENTRY

:

FSR points to the I2C port’s TRIS register

*

;

*

EXIT

:

Stop condition and SCL, SDA pins high (Idle)

*

; *************************************************************

STOP

bcf

INDF,SCL

; Make sure that Clock line is low

bcf

INDF,SDA

; and the Data line is low

bsf

INDF,SCL

; Bring Clock line high

Delay_600

; for a minimum of 0.6us

bsf

INDF,SDA

; Rising edge on Data signals Stop

return

; including the return time

;*************************************************************

;* FUNCTION: Transmits byte to Slave and monitors Acknowledge*

; *

ENTRY

:

8-bit data

to be TXed is in DATA_OUT

*

; *

RESOURCE:

START and STOP subroutines

*

;

*

EXIT

:

Byte

transmitted. ERROR

is 01 IF no Ack received*

;

*

EXIT

:

from

Slave

ELSE 00. SCL

low

*

; *************************************************************

I2C_OUT bcf

INDF,SCL

; Make sure that Clock line is low

clrf

ERR

; Start with no error

movlw

8

; Loop counter = 8

movwf

COUNT

I2C_OUT_LOOP

bcf

INDF,SDA

; Data bit low?

rlf

DATA_OUT,f

; Shift data left once into Carry

btfsc

STATUS,C

; Is C 0 or 1

bsf

INDF,SDA

; IF the latter THEN make Data hi

Delay_600

; Delay plus xtra instructions OK

Delay_600

bsf

INDF,SCL

; Bring Clock pin high

Delay_600

; for at least 0.6us

bcf

INDF,SCL

; Bring Clock low

decfsz

COUNT,f

; Decrement loop count

goto

I2C_OUT_LOOP

; and repeat eight times

; Now check Acknowledge from Slave

bsf

INDF,SDA

; Release Data line

Delay_600

; Keep Clock line low

Delay_600

; long enough for Slave to respond

bsf

INDF,SCL

; Bring Clock line high

btfsc

INDF,SDA

; Check if Data is low from Slave

incf

ERR,f

; IF not THEN ERROR1

bcf

INDF,SCL

; Now finish ACK by bringing Ck lo

return


12. One Bit at a Time 333

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.6 µs

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 = 01h; 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 Channel 0 and then the contents of File 21h 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 21h 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: 01011000b

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: 00000XX1b

No ReSeT, no Power Down, Channel 1.

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

7.Stop condition.