;a 93CS46 serial EEPROM connected to port 1 ;when done accessing, cs and di should be left low ;and sk should be left high. pe and pre should be ;left low, but that really isn't as important ;when data is output on the do pin, di must be low .equ cs, 0x90 ; p1.0 - CS - Chip Select .equ sk, 0x91 ; p1.1 - SK - Clock .equ di, 0x92 ; p1.2 - DI - Data Input .equ do, 0x93 ; p1.3 - DO - Data Output .equ pe, 0x94 ; p1.4 - PE - Program Enable .equ pre, 0x95 ; p1.5 - PRE - Protect Reg. En. ;******************************************************** ; some initial setup ;******************************************************** .equ stack, 0x30 .equ baud_const, 253 ;19200 baud w/ 11.0592 MHz cyrstal setb pe setb pre clr di setb do clr cs setb sk ;******************************************************** ; The user interface ;******************************************************** main: mov dptr, #menu_mesg lcall pstr sjmp main_loop menu_mesg: .db 13,10 .db " r = read eeprom",13,10 .db " e = edit eeprom memory",13,10 .db 13,10,0 main_loop: lcall cin cjne a, #'r', main2 mov dptr, #readmesg lcall pstr ljmp readit readmesg:.db "read eeprom",13,10,0 main2: cjne a, #'e', main3 mov dptr, #editmesg lcall pstr ljmp editit editmesg:.db "edit eeprom memory",13,10,0 main3: sjmp main_loop readit: mov r0, #0 readback: mov a, r0 anl a, #00000111b jnz readbk2 lcall newline mov a, r0 lcall phex mov a, #':' lcall cout mov a, #' ' lcall cout readbk2: lcall read mov a, r2 lcall phex mov a, r3 lcall phex mov a, #' ' lcall cout inc r0 cjne r0, #64, readback lcall newline lcall wen lcall pren mov r0, #0 lcall prwrite lcall wds ljmp main_loop editit: mov dptr, #locmesg lcall pstr lcall ghex8 anl a, #00111111b push acc lcall newline mov dptr, #valmesg lcall pstr lcall ghex16 mov a, r3 push acc mov a, r2 push acc lcall newline lcall wen ;turn on write enable mode lcall pren ;enable the protect register lcall prclear ;turn off write protection pop acc mov r3, a pop acc mov r2, a pop acc mov r0, a lcall write ;write test two bytes lcall wds mov dptr, #wrote1 lcall pstr mov a, r2 lcall phex mov a, r3 lcall phex mov dptr, #wrote2 lcall pstr mov a, r0 lcall phex lcall newline ljmp main_loop wrote1: .db "wrote ", 0 wrote2: .db " to ",0 locmesg:.db "Word location (0-63): ",0 valmesg:.db "16 bit value to write: ",0 ;******************************************************** ; built-in UART subroutines ;******************************************************** cin: jnb ri, cin clr ri mov a, sbuf ret cout: jnb ti, cout mov sbuf, a clr ti ret newline:push acc mov a, #13 acall cout mov a, #10 acall cout pop acc ret phex: phex8: push acc swap a anl a, #15 add a, #246 jnc phex_b add a, #7 phex_b: add a, #58 acall cout pop acc phex1: push acc anl a, #15 add a, #246 jnc phex_c add a, #7 phex_c: add a, #58 acall cout pop acc ret space: mov a, #' ' acall cout ret PSTR: ;print string PUSH ACC PSTR1: CLR A MOVC A,@A+DPTR JZ PSTR2 mov c, acc.7 anl a, #01111111b acall cout Jc pstr2 inc dptr SJMP PSTR1 PSTR2: POP ACC RET ;carry set if esc pressed ;psw.5 set if return pressed w/ no input ghex16: mov r2, #0 ;start out with 0 mov r3, #0 mov r4, #4 ;number of digits left clr psw.5 ghex16c: lcall cin lcall upper cjne a, #27, ghex16d setb c ;handle esc key ret ghex16d:cjne a, #8, ghex16f sjmp ghex16k ghex16f:cjne a, #127, ghex16g ;handle backspace ghex16k:cjne r4, #4, ghex16e ;have they entered anything yet? sjmp ghex16c ghex16e:lcall cout acall ghex16y inc r4 sjmp ghex16c ghex16g:cjne a, #13, ghex16i ;return key cjne r4, #4, ghex16h setb psw.5 ghex16h:clr c ret ghex16i:mov r5, a ;keep copy of original keystroke acall asc2hex jc ghex16c xch a, r5 lcall cout mov a, r5 push acc acall ghex16x pop acc add a, r2 mov r2, a clr a addc a, r3 mov r3, a djnz r4, ghex16c clr c ret ghex16x: ;multiply r3-r2 by 16 (shift left by 4) mov a, r3 swap a anl a, #11110000b mov r3, a mov a, r2 swap a anl a, #00001111b orl a, r3 mov r3, a mov a, r2 swap a anl a, #11110000b mov r2, a ret ghex16y: ;divide r3-r2 by 16 (shift right by 4) mov a, r2 swap a anl a, #00001111b mov r2, a mov a, r3 swap a anl a, #11110000b orl a, r2 mov r2, a mov a, r3 swap a anl a, #00001111b mov r3, a ret asc2hex: ;carry set if invalid input clr c push b subb a, #'0' mov b, a subb a, #10 jc a2h1 mov a, b subb a, #7 mov b, a a2h1: mov a, b clr c anl a, #11110000b ;just in case jz a2h2 setb c a2h2: mov a, b pop b ret ;get 2 digit hex number from serial port ; c = set if ESC pressed, clear otherwise ; psw.5 = set if return w/ no input, clear otherwise ghex: ghex8: clr psw.5 ghex8c: acall cin ;get first digit acall upper cjne a, #27, ghex8f ghex8d: setb c clr a ret ghex8f: cjne a, #13, ghex8h setb psw.5 clr c clr a ret ghex8h: mov r2, a acall asc2hex jc ghex8c xch a, r2 ;r2 will hold hex value of 1st digit acall cout ghex8j: acall cin ;get second digit acall upper cjne a, #27, ghex8k sjmp ghex8d ghex8k: cjne a, #13, ghex8m mov a, r2 clr c ret ghex8m: cjne a, #8, ghex8p ghex8n: acall cout sjmp ghex8c ghex8p: cjne a, #21, ghex8q sjmp ghex8n ghex8q: mov r3, a acall asc2hex jc ghex8j xch a, r3 acall cout mov a, r2 swap a orl a, r3 clr c ret upper: ;converts the ascii code in Acc to uppercase, if it is lowercase push acc clr c subb a, #97 jc upper2 ;is it a lowercase character subb a, #26 jnc upper2 pop acc add a, #224 ;convert to uppercase ret upper2: pop acc ;don't change anything ret poweron: MOV SP, #stack clr psw.3 clr psw.4 mov th1, #baud_const orl PCON,#10000000b ; set double baud rate MOV TMOD,#00100001b ; T0=16 bit, T1=8 bit auto reload ; both are timers, software control MOV SCON,#01010010b ; Set Serial for mode 1 & ; Enable reception, ti=1, ri=0 ORL TCON,#01010101b ; Start both timers, both int are ; falling edge trigger mov dptr, #welcome acall pstr ajmp main welcome:.db "Serial EEPROM tester",13,10,13,10,0 ;******************************************************** ; and here's where all the dirty work is done ;******************************************************** read: ;r0 is word address to read, data is returned in ;r2 (lsb) and r3 (msb) clr pre setb cs nop clr sk setb di ;the start bit setb sk clr sk nop setb sk ;another '1' clr sk clr di ;and a '0' setb sk mov r4, #6 mov a, r0 rl a rl a read2: rlc a clr sk mov di, c ;and do each address bit setb sk djnz r4, read2 clr di mov r4, #8 clr a read3: clr sk nop setb sk mov c, do rlc a djnz r4, read3 mov r3, a mov r4, #8 clr a read4: clr sk setb sk mov c, do rlc a djnz r4, read4 mov r2, a clr cs clr di ret ;******************************************************** write: ;r0 is word address to write, r2 (lsb) and r3 (msb) clr pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk setb di ;a '1' setb sk mov r4, #6 mov a, r0 rl a rl a write2: rlc a clr sk mov di, c ;and do each address bit setb sk djnz r4, write2 mov a, r3 mov r4, #8 write3: clr sk rlc a mov di, c setb sk djnz r4, write3 mov a, r2 mov r4, #8 write4: clr sk rlc a mov di, c setb sk djnz r4, write4 clr di clr cs nop setb cs nop nop write5: mov c, do jnc write5 nop clr cs ret ;******************************************************** pren: ;enable the protection register (for next cycle) setb pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr cs clr pre ret ;******************************************************** prclear: setb pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr di clr cs clr pre nop setb cs nop nop prclr5: mov c, do jnc prclr5 nop clr cs ret ;******************************************************** prds: ;permantly fix protect register!!! setb pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr cs clr pre nop setb cs nop nop prds5: mov c, do jnc prds5 nop clr cs ret ;******************************************************** prwrite: ;r0 is address to write into protect register setb pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk setb di ;a '1' setb sk mov r4, #6 mov a, r0 rl a rl a prwrt2: rlc a clr sk mov di, c ;and do each address bit setb sk djnz r4, prwrt2 clr di clr cs clr pre nop setb cs nop nop prwrt5: mov c, do jnc prwrt5 nop clr cs ret ;******************************************************** wen: ;enable writing clr pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr cs clr pre ret ;******************************************************** wds: ;disable writing clr pre setb pe setb cs nop clr sk setb di ;the start bit setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk setb di ;a '1' setb sk clr sk setb di ;a '1' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr sk clr di ;a '0' setb sk clr cs clr pre ret