Wednesday, April 13, 2016

Interfacing AT24CXX Serial EEPROMs with AT89C51 Microcontrollers

Serial memory devices offer significant advantages over parallel devices in applications where lower data transfer rates are acceptable. In addition to requiring less board space, serial devices allow microcontroller I/O pins to be conserved. This is especially valuable when adding external memory to low pin count microcontrollers such as the Atmel AT89C1051 and AT89C2051. This application note presents a suite of
software routines which may be incorporated into a user’s application to allow an AT89C51 microcontroller to read and write AT24CXX serial EEPROMs. The software supports all members of the AT24CXX family, and may easily be modified for compatibility with any of the Atmel 8051-code compatible microcontrollers.

Hardware
A typical interconnection between an AT89CX051 microcontroller and an AT24CXX serial EEPROM is shown in Figure 1.

Figure 1:
89C51 interface with 24Cxx



As indicated in the figure, up to eight members of the AT24CXX family may share the bus, utilizing the same two microcontroller I/O pins. Each device on the bus must have its address inputs
(A0, A1, A2) hard-wired to a unique address. In the figure, the first device recognizes address zero (A0, A1, A2 tied low), whi le the eighth recognizes address seven (A0, A1, A2 tied high). Not all members of the AT24CXX family recognize all three address inputs, limiting the number of some devices which may be present to less than eight. The exact number of devices of each type which may share the bus is shown in
Table 1.

Table 1:



Assembly Language Program:



INCLUDE 89C51.MC
;-----------------------AT24CXXX ---------------------------
;24CXXX connections to microcontroller

SDA  EQU P0.0  ; serial data
SCL  EQU P0.1  ; serial clock
;-----------------------------------------------------------
; Register definitions.

DATA  EQU 01h  ; data
ADDR_HI EQU 03h  ; address higher
ADDR_LO EQU 02h  ; address lower
BUFFER EQU  04h  ; read data buffer
;-----------------------------------------------------------
on_reset:
  CLR C   ; clear error flag
  MOV A,#00H  ; device address
  MOV ADDR_HI,#00H ; address higher byte
  MOV ADDR_LO,#10H ; address lower byte
  MOV DATA,#45H ; data to be writen
  CALL write_byte
  
  
;-----------------------------------------------------------
;    I2C WRITING
;-----------------------------------------------------------
write_byte:
 ; AT24Cxx Byte Write function.
 ; Called with programmable address in A, byte address in
 ; register pair ADDR_HI:ADDR_LO(R3:R2), data in register R1.
 ; Does not wait for write cycle to complete.
 ; Returns CY set to indicate that the bus is not available
 ; or that the addressed device failed to acknowledge.
 ; Destroys A.
  call  start
  JC  x49  ; abort if bus not available

  RL  A  ; programmable address to bits 3:1
  ORL A,#A0H        ; add fixed address
  CLR  acc.0  ; specify write operation
  call  shout  ; send device address
  JC  x48  ; abort if no acknowledge

  MOV A,ADDR_HI   ; send high byte of address
  call shout  ;
  JC  x48  ; abort if no acknowledge

  MOV A,ADDR_LO ; send low byte of address
  call shout  ;
  JC  x48  ; abort if no acknowledge

  MOV A,DATA ; get data
  call  shout  ; send data
            call i2c_delay ; self write cycle
  JC  x48  ; abort if no acknowledge
  CLR  C  ; clear error flag
 x48:
  call STOP
  call i2c_delay
 x49:
RET
;-----------------------------------------------------------
;    I2C READING
;-----------------------------------------------------------
read_block:
 ; Read from one byte to one page of data from an AT24Cxx.
 ; Performs a Random Read which is extended into a Sequential Read
 ; when more than one byte is read. Called with programmable address
 ; in A, address of first byte in register pair R3:R2,
 ; Returns data in BUFFER. Returns CY set to indicate that the bus is
 ; not available or that the addressed device failed to acknowledge.
 ; Destroys A, R1, R0.

  ; Send dummy write command to address first byte.
  Call  start
  JC  x35  ; abort if bus not available

  RL A  ; programmable address to bits 3:1
  ORL A,#A0H  ; add fixed address
  MOV R0, A       ; save copy of device address
  CLR acc.0  ; specify write operation
  call  shout  ; send device address
  JC x34  ; abort if no acknowledge

  MOV A,ADDR_HI   ; send high byte of address
  call shout  ;
  JC x34  ; abort if no acknowledge

  MOV A,ADDR_LO ; send low byte of address
  call shout  ;
  JC x34  ; abort if no acknowledge

  ; Send read command and receive data.

  call start  ; second start for read
  JC  x34  ; abort if bus not available

  MOV  A, R0  ; get device address
  SETB  acc.0  ; specify read operation
  call  shout  ; send device address
  JC  x34  ; abort if no acknowledge

 x31:
  call shin  ; receive data byte
  call NAK  ; do not acknowledge last byte
  jmp x33  ; done
 x33:
  CLR C  ; clear error flag
  MOV BUFFER,A ; get data in buffer
 x34:
  call stop
 x35:
RET

;-----------------------------------------------------------
;    SHIFT OUT A BYTE TO I2C
;-----------------------------------------------------------
shout:

 ; Shift out a byte to the AT24Cxx, most significant bit first.
 ; SCL, SDA expected low on entry. Return with SCL low.
 ; Called with data to send in A.
 ; Returns CY set to indicate failure by slave to acknowledge.
 ; Destroys A.

  PUSH  B
  MOV  B, #8  ; bit counter
 x42:
  RLC  A  ; move bit into CY
  MOV  SDA, C  ; output bit
  NOP    ; enforce SCL low and data setup
  SETB  SCL  ; raise clock
  NOP    ; enforce SCL high
  NOP    ;
  NOP    ;
  NOP    ;
  CLR  SCL  ; drop clock
  DJNZ  B, x42  ; next bit

  SETB  SDA  ; release SDA for ACK
  NOP    ; enforce SCL low and tAA
  NOP    ;
  SETB  SCL  ; raise ACK clock
  NOP    ; enforce SCL high
  NOP    ;
  NOP    ;
  NOP    ;
  MOV  C, SDA  ; get ACK bit
  CLR  SCL  ; drop ACK clock

  POP  B
RET

;-----------------------------------------------------------
;    SHIFT IN A BYTE FROM I2C
;-----------------------------------------------------------
shin:

 ; Shift in a byte from the AT24Cxx, most significant bit first.
 ; SCL expected low on entry. Return with SCL low.
 ; Returns received data byte in A.

  SETB  SDA  ; make SDA an input

  PUSH  B
  MOV  B, #8  ; bit count
 x43:
  NOP    ; enforce SCL low and data setup
  NOP    ;
  NOP    ;
  SETB  SCL  ; raise clock
  NOP    ; enforce SCL high
  NOP    ;
  MOV  C, SDA ; input bit
  RLC  A  ; move bit into byte
  CLR  SCL  ; drop clock
  DJNZ B, x43 ; next bit

  POP  B
RET

;-----------------------------------------------------------
;    I2C ACKNOWLEDGE
;-----------------------------------------------------------
ACK:

 ; Clock out an acknowledge bit (low).
 ; SCL expected low on entry. Return with SCL, SDA low.

  CLR  SDA  ; ACK bit
  NOP    ; enforce SCL low and data setup
  NOP    ;
  SETB  SCL  ; raise clock
  NOP    ; enforce SCL high
  NOP    ;
  NOP    ;
  NOP    ;
  CLR  SCL  ; drop clock
RET

;-----------------------------------------------------------
;    I2C NO ACKNOWLEDGE
;-----------------------------------------------------------
NAK:

 ; Clock out a negative acknowledge bit (high).
 ; SCL expected low on entry. Return with SCL low, SDA high.

  SETB  SDA  ; NAK bit
  NOP    ; enforce SCL low and data setup
  NOP    ;
  SETB  SCL  ; raise clock
  NOP    ; enforce SCL high
  NOP    ;
  NOP    ;
  NOP    ;
  CLR  SCL  ; drop clock
RET

;-----------------------------------------------------------
;    I2C START PULSE
;-----------------------------------------------------------
start:

 ; Send START, defined as high-to-low SDA with SCL high.
 ; Return with SCL, SDA low.
 ; Returns CY set if bus is not available.

  SETB  SDA
  NOP
  NOP
  NOP
  SETB  SCL

  ; Verify bus available.
  CALL i2c_delay

  JNB  SDA, x40 ; jump if not high
  NOP
  NOP
  JNB  SCL, x40 ; jump if not high

  NOP    ; enforce setup delay and cycle delay
  CLR  SDA
  NOP    ; enforce hold delay
  NOP    ;
  NOP    ;
  NOP    ;
  NOP   ;
  CLR SCL

  CLR C  ; clear error flag
  JMP x41
 x40:
  SETB C  ; set error flag
 x41:
RET
;-----------------------------------------------------------
;    I2C STOP PULSE
;-----------------------------------------------------------
Stop:

 ; Send STOP, defined as low-to-high SDA with SCL high.
 ; SCL expected low on entry. Return with SCL, SDA high.

  CLR  SDA
  NOP    ; enforce SCL low and data setup
  nop 
  SETB  SCL
  NOP    ; enforce setup delay
  NOP    
  NOP    
  NOP    
  NOP    
  SETB  SDA
RET 
;----------------------------------------------------------
i2c_delay:
  MOV R7,#FFH
i2cloop: NOP
  NOP
  NOP
  DJNZ R7, i2cloop
RET
;----------------------------------------------------------

This code is written in ProgStudio. This code is tested

No comments:

Post a Comment