??? 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 |
Topic | Author | Date |
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 |