Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
???
09/04/08 16:25
Read: times


 
#157957 - Need help with SPI implementation code in AT89S52
Hi,

I am trying to interface a serial EEPROM (Microchip 25AA256) with a plain AT89S52 which does not have HW SPI.

I have pored over the data sheet and finally came up with some code. But as it usually happens with all my projects initially, it is not working.

Here, I am posting the code and maybe someone here can provide some clues or pointers if I am really doing anything wrong here.

Oh yes, the EEPROM is in fine condition because recently I interfaced it with my 'Arduino' board and it was able to read and write from it without any difficulty.

I have written the code so that it writes 'X' or 0x58 onto location 0000h into the EEPROM and then reads the same hex byte back. Then it echoes it back via the serial port. I have a small C program written over my PC which reads from the serial port and echoes the read character, formatted with %d.

The problem is, I am getting 255 when I read back the first location in the EEPROM. Either READ is not working, or WRITE is not working, or worst case neither are working.

Here goes the code. Any help would be greatly appreciated!

; EEPROM connecting lines
_cs   equ p2.0
so    equ p2.1
_wp   equ p2.2   
_hold equ p2.3   
sck   equ p2.4   
si    equ p2.5

; EEPROM Intructions
READ  equ 00000011b
WRITE equ 00000010b
WRDI  equ 00000100b
WREN  equ 00000110b
RDSR  equ 00000101b
WRSR  equ 00000001b


        org 0000h
        ljmp main ; bypassing the interrupt vectors


        org 0030h
main:
        lcall init_ser_port
        lcall init_eeprom

        mov a,#WRSR
        lcall shift_out
        mov a,#0h      ;0h for no protection
        lcall shift_out
        lcall delay_5ms

        lcall init_eeprom_write
        mov a,#'X'
        lcall eeprom_write_byte

        nop
        nop ;some delay

        lcall eeprom_read_byte
        sjmp $




; Establish default values for EEPROM bus lines
init_eeprom:
        setb _cs     ;_cs default as HIGH : to NOT select chip when not needed
        setb _wp     ;_wp default as HIGH : to allow writes
        clr _hold    ;_hold default as LOW : to select device always , unless overridden
        setb sck     ;sck default as HIGH : as idle condition
        setb so      ;so default as HIGH : as idle condition
        setb si      ;si default as HIGH : as idle condition
        ret
        



; WRITE Specific init routine
init_eeprom_write:
        clr _cs     ;setting _cs to low first
        mov a,#WREN
        lcall shift_out
        setb _cs  ;bringing up _cs to HIGH again to set write latch
        ret

eeprom_write_byte:
        clr _cs   ;selecting chip before writing
        push acc  ;saving byte to write to stack for the moment
        mov a,#WRITE
        lcall shift_out
        ;sending address to write as 0000h for writing
        mov a,#0h
        lcall shift_out
        lcall shift_out

        pop acc   ;recovering byte to write from stack
        lcall shift_out
        setb _cs  ;de-asserting _cs after writing is over
        ret

eeprom_read_byte:
        clr _cs   ;asserting _cs just before reading
        mov a,#READ
        lcall shift_out

        ;Sending address to read from first, 0000h
        mov a,#0h
        lcall shift_out
        lcall shift_out

        ;read the data byte now
        lcall shift_in
        setb _cs   ;de-asserting _cs after reading is over
        ret
        

shift_out:
        ;data to shift out is in A, and we have to shift it out, MSB first via si
        mov r0,#8
        clr C
_back:        
        rlc A
        mov si,C
        clr sck  ;lowering clock from idle level(HIGH)
        nop      ;some delay
        setb sck ;raising clock to latch bit
        nop      ;again some delay to allow EEPROM to digest what we just sent
        djnz r0,_back ;repeat for all bits in A
        ret
        
shift_in:
        ;data would be shifted in via so line
        mov r0,#8
        clr C
        mov a,#00h
        setb so
_back1:
        clr sck
        nop
        setb sck ;this will cause EEPROM to vomit out the bit onto so
        nop
        nop
        mov C,so
        rlc A    ;this rotation would pack the bits starting with MSB and then proceed to LSB
        nop      ;some delay
        djnz r0,_back1
        lcall send_one_char
        ret


init_ser_port:
        ;Initializing the serial baud rate generator
        mov ie,#10010100b      ;enabling the serial port interrupt and int1
        setb it1              ;to set interrupt 1 as edge triggered
        mov tmod, #20h        ;timer 1, mode 2(auto reload mode)
        mov th1,#-3           ;9600 baud rate 
        mov scon,#50h         ;8-bit, 1 stop bit, ren enabled 
        setb tr1              ;start timer 1
        ret


send_one_char:
        mov sbuf,a
        jnb ti,$
        clr ti
        ret

recv_one_char:
        jnb ri,$
        mov a,sbuf
        clr ri
        ret

 delay_5ms: 
         mov r1, #250   ; write cycle time 
 dly5ms1: 
         lcall dly20us       ; ~250 * 20us = 5msec 
         djnz r1, dly5ms1  
	     ret 


dly20us:
        mov r2, #38     ; 0.5 usec 
dly20:  
        djnz r2, dly20  ; 0.5 usec * 38 = 19 usecs  
	    ret                 ; 0.5 usec 

        

end






List of 3 messages in thread
TopicAuthorDate
Need help with SPI implementation code in AT89S52            01/01/70 00:00      
   one thing after other            01/01/70 00:00      
   Got the issue!            01/01/70 00:00      

Back to Subject List