У Атмела есть AN "Interfacing AT24CXX Serial EEPROMs with AT89CX051 Microcontrollers". Их сайт вдруг скис, кидаю сюда АСМ с CD - надеюсь, форматирование не шибко пострадает
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено BLACKEAGLE 20 марта 2003 г. 02:08
В ответ на: 24сХХ могут работать на произвольных скоростях? отправлено vaja 20 марта 2003 г. 00:40



NAME Control_AT24Cxx

; This collection of routines allows an AT89C2051 microcontroller to read
; and write the AT24Cxx family of serial CMOS EEPROMS. This version of the
; code is compatible only with the AT89C2051 due to the location of the
; data buffer and stack in RAM. The code may be modified to work with the
; AT89C1051 by relocating or resizing the buffer and stack to fit into the
; smaller amount of RAM available in the AT89C1051. Note that the minimum
; size of the buffer is determined by the page size of the AT24Cxx.
;
; All five AT24Cxx device operations are supported. Byte Write, Current
; Address Read and Random Read are implemented by the functions WRITE_BYTE,
; READ_CURRENT and READ_RANDOM, respectively. Page Write and Sequential Read
; are special cases of functions WRITE_BLOCK and READ_BLOCK, respectively.
; WRITE_BLOCK and READ_BLOCK process from one byte to the number of bytes
; in a page and transfer data between the AT24Cxx and the RAM buffer.
;
; The code supports multiple AT24Cxx devices per bus, each with a unique
; address determined by the wiring of the address pins (A0, A1, A2). The
; three-bit programmable address is passed to the WRITE_BYTE, READ_CURRENT,
; READ_RANDOM, WRITE_BLOCK and READ_BLOCK functions, where it is combined
; with the AT24Cxx fixed address (FADDR) and used to address a device on the
; bus. Refer to the AT24Cxx family data sheets for additional information on
; device addressing.
;
; Functions BYTE_FILL, VERIFY_BYTE_FILL, PAGE_FILL and VERIFY_PAGE_FILL are
; artifacts from the debug process and serve to illustrate the use of the
; device read and write functions with an AT24C64. To modify the code for a
; different member of the AT24Cxx family, simply redefine the values of SIZE
; (the number of bytes per device) and PSIZE (the number of bytes per page).
; To change the fill value, redefine FILL. To change the programmable portion
; of the device address, redefine PADDR to a value from zero to seven.
;
; The code meets all AT24Cxx family timing requirements when executed by an
; AT89Cx051 microcontroller with a 12 MHz clock. Code modifications may be
; required if a faster clock is substituted.


FADDR EQU 0a0h ; fixed address for AT24Cxx EEPROMs
PADDR EQU 0 ; programmable address (0..7)
SIZE EQU 2000h ; bytes per AT24C64
PSIZE EQU 32 ; bytes per page for AT24C64
FILL EQU 55h ; example fill value

; Register definitions.

index EQU r0 ; buffer pointer
kount EQU r1 ; byte count register
zdata EQU r1 ; data register
addr_lo EQU r2 ; 2-byte address register
addr_hi EQU r3 ;

; Microcontroller connections to AT24Cxx serial bus lines.

SCL BIT p1.2 ; serial clock
SDA BIT p1.3 ; serial data


DSEG AT 20H

ORG 40H
buffer: DS PSIZE ; storage for read/write data

ORG 60H ; stack origin
stack: DS 20H ; stack depth


CSEG

ORG 0000H ; power on/reset vector
jmp on_reset

ORG 0003H ; external interrupt 0 vector
reti ; undefined

ORG 000BH ; timer 0 overflow vector
reti ; undefined

ORG 0013H ; external interrupt 1 vector
reti ; undefined

ORG 001BH ; timer 1 overflow vector
reti ; undefined

ORG 0023H ; serial I/O interrupt vector
reti ; undefined

ORG 0080H ; begin code space
USING 0 ; register bank zero
on_reset:
mov sp, #(stack-1) ; initialize stack pointer

; Initialize AT24Cxx serial bus lines.

setb SDA ; high
setb SCL ; high


call byte_fill
jc fault

call verify_byte_fill
jc fault

call page_fill
jc fault

call verify_page_fill
jc fault

fault:
jmp $


byte_fill:

; Fill every byte in an AT24Cxx with the same value.
; Writes one address at a time (page mode is not used).
; Returns CY set to indicate write timeout.
; Destroys A, B, DPTR, XDATA, ADDR_HI:ADDR_LO.

mov zdata, #FILL ; set up fill data
mov dptr, #0 ; initialize address pointer
x51:
mov addr_lo, dpl ; set up address
mov addr_hi, dph ;

mov b, #120 ; retry counter
x52:
mov a, #PADDR ; programmable address
call write_byte ; try to write
jnc x53 ; jump if write OK

djnz b, x52 ; try again
setb c ; set timeout error flag
jmp x54 ; exit
x53:
inc dptr ; advance address pointer
; mov a, dpl ; check low byte
; cjne a, #(LOW SIZE), x51 ; jump if not last
mov a, dph ; check high byte
cjne a, #(HIGH SIZE), x51 ; jump if not last
clr c ; clear error flag
x54:
ret


verify_byte_fill:

; Verify that all bytes in an AT24Cxx match a fill value.
; Reads and verifies one byte at a time (page mode is not used).
; Performs a Random Read function to initialize the internal
; address counter and checks the contents of the first address.
; Then performs multiple Current Address Read functions to step
; through the remaining addressess.
; Returns CY set to indicate read timeout or compare fail.
; Destroys A, B, DPTR.

mov dptr, #0 ; initialize address pointer/counter
mov addr_lo, dpl ; set up address
mov addr_hi, dph ;

mov b, #120 ; retry counter
x81:
mov a, #PADDR ; programmable address
call read_random ; try to read
jnc x82 ; jump if read OK

djnz b, x81 ; try again
jmp x86 ; set error flag and exit
x82:
cjne a, #FILL, x86 ; jump if compare error
jmp x85 ; do remaining addresses
x83:
mov a, #PADDR
call read_current
jc x87 ; jump if read fails

cjne a, #FILL, x86 ; jump if compare error
x85:
inc dptr ; advance address pointer
mov a, dph ; check high byte
cjne a, #(HIGH SIZE), x83 ; jump if not last
clr c ; clear error flag
jmp x87 ; exit
x86:
setb c ; set error flag
x87:
ret


page_fill:

; Fill every byte in an AT24Cxx with the same value.
; Writes one page at a time.
; Returns CY set to indicate write timeout.
; Destroys A, B, DPTR, KOUNT, INDEX, ADDR_HI:ADDR_LO.

; First fill buffer.

mov b, #PSIZE ; bytes per page
mov index, #buffer ; point to buffer
x61:
mov @index, #FILL ; put fill value in buffer
inc index ; advance pointer
djnz b, x61 ; next byte

; Copy buffer to device, one page at a time.

mov dptr, #0 ; initialize address pointer
x62:
mov addr_lo, dpl ; set up address
mov addr_hi, dph ;
mov kount, #PSIZE ; bytes per page

mov b, #120 ; retry counter
x63:
mov a, #PADDR ; programmable address
call write_block ; try to write
jnc x64 ; jump if write OK

djnz b, x63 ; try again
setb c ; set timeout error flag
jmp x66 ; exit
x64:
; Add page size to address pointer.

mov a, dpl ; get low byte
add a, #PSIZE ; add page size
mov dpl, a ; save low byte
jnc x65 ; jump if high byte not affected
inc dph ; increment high byte
x65:
; cjne a, #(LOW SIZE), x62 ; jump if low byte not last
mov a, dph ; check high byte
cjne a, #(HIGH SIZE), x62 ; jump if not last
clr c ; clear error flag
x66:
ret


verify_page_fill:

; Verify that all bytes in an AT24Cxx match a fill value.
; Reads and verifies one page at a time.
; Returns CY set to indicate read timeout or compare fail.
; Destroys A, B, DPTR, KOUNT, INDEX, ADDR_HI:ADDR_LO.

; Copy device page to buffer.

mov dptr, #0 ; initialize address pointer
x71:
mov addr_lo, dpl ; set up address
mov addr_hi, dph ;
mov kount, #PSIZE ; bytes per page

mov b, #120 ; retry counter
x72:
mov a, #PADDR ; programmable address
call read_block ; try to read
jnc x74 ; jump if read OK

djnz b, x72 ; try again
x73:
setb c ; set error flag
jmp x77 ; exit
x74:
; Verify buffer contents.

mov b, #PSIZE ; bytes per page
mov index, #buffer ; point to buffer
x75:
cjne @index, #FILL, x73 ; jump if compare fails
inc index ; advance pointer
djnz b, x75 ; next byte

; Add page size to address pointer.

mov a, dpl ; get low byte
add a, #PSIZE ; add page size
mov dpl, a ; save low byte
jnc x76 ; jump if high byte not affected
inc dph ; increment high byte
x76:
; cjne a, #(LOW SIZE), x71 ; jump if low byte not last
mov a, dph ; check high byte
cjne a, #(HIGH SIZE), x71 ; jump if not last
clr c ; clear error flag
x77:
ret


write_block:

; Write from one byte to one page of data to an AT24Cxx.
; Called with programmable address in A, address of first byte
; in register pair ADDR_HI:ADDR_LO, data in BUFFER, byte count
; in register KOUNT.
; 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, KOUNT, INDEX.

call start
jc x38 ; abort if bus not available

rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
clr acc.0 ; specify write operation
call shout ; send device address
jc x37 ; abort if no acknowledge

mov a, addr_hi ; send high byte of address
call shout ;
jc x37 ; abort if no acknowledge

mov a, addr_lo ; send low byte of address
call shout ;
jc x37 ; abort if no acknowledge

mov index, #buffer ; point to buffer
x36:
mov a, @index ; get data
call shout ; send data
jc x37 ; abort if no acknowledge

inc index ; advance buffer pointer
djnz kount, x36 ; next byte
clr c ; clear error flag
x37:
call stop
x38:
ret


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 ADDR_HI:ADDR_LO,
; byte count in register KOUNT.
; 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, KOUNT, INDEX.

; 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, #FADDR ; add fixed address
mov index, 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, index ; get device address
setb acc.0 ; specify read operation
call shout ; send device address
jc x34 ; abort if no acknowledge

mov index, #buffer ; point to buffer
x31:
call shin ; receive data byte
mov @index, a ; save data

cjne kount, #1, x32 ; jump if not last byte
call NAK ; do not acknowledge last byte
jmp x33 ; done
x32:
call ACK ; acknowledge byte
inc index ; advance buffer pointer
djnz kount, x31 ; next byte
x33:
clr c ; clear error flag
x34:
call stop
x35:
ret


write_byte:

; AT24Cxx Byte Write function.
; Called with programmable address in A, byte address in
; register pair ADDR_HI:ADDR_LO, data in register XDATA.
; 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, #FADDR ; 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, zdata ; get data
call shout ; send data
jc x48 ; abort if no acknowledge

clr c ; clear error flag
x48:
call stop
x49:
ret


read_current:

; AT24Cxx Current Address Read function.
; Called with programmable address in A. Returns data in A.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.

call start
jc x45 ; abort if bus not available

rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
setb acc.0 ; specify read operation
call shout ; send device address
jc x44 ; abort if no acknowledge

call shin ; receive data byte
call NAK ; do not acknowledge byte
clr c ; clear error flag
x44:
call stop
x45:
ret


read_random:

; AT24Cxx Random Read function.
; Called with programmable address in A, byte address in
; register pair ADDR_HI:ADDR_LO. Returns data in A.
; Returns CY set to indicate that the bus is not available
; or that the addressed device failed to acknowledge.

push b
mov b, a ; save copy of programmable address

; Send dummy write command to set internal address.

call start
jc x47 ; abort if bus not available

rl a ; programmable address to bits 3:1
orl a, #FADDR ; add fixed address
clr acc.0 ; specify write operation
call shout ; send device address
jc x46 ; abort if no acknowledge

mov a, addr_hi ; send high byte of address
call shout ;
jc x46 ; abort if no acknowledge

mov a, addr_lo ; send low byte of address
call shout ;
jc x46 ; abort if no acknowledge

; Call Current Address Read function.

mov a, b ; get programmable address
call read_current
jmp x47 ; exit
x46:
call stop
x47:
pop b
ret


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
setb SCL

; Verify bus available.

jnb SDA, x40 ; jump if not high
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


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


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


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


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


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


END


Составить ответ  |||  Конференция  |||  Архив

Ответы



Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru