天天看點

AT89S8253片内EEPROM位元組讀、位元組寫、頁讀、頁寫驅動代碼、注意事項及注釋

在編寫AT89S8253片内EEPROM讀寫驅動程式時,要特别注意資料讀寫指令MOVX;

當EECON寄存器的EEMEN位置位時,MOVX通路EEPROM;

當EECON寄存器的EEMEN位清零時,MOVX通路外部RAM;

一般情況下,我們定義的用來寫入EEPROM的資料或儲存EEPROM讀取的資料都用外部RAM;代碼具體分析如下:

C語言頁寫入代碼:

unsigned char W_EEPROM_PAGE(unsigned int paddr, unsigned char *pdat)

{

unsigned char temp;

EECON |= EEMEN;

EECON |= EEMWE;

...

For(temp = 0; temp < 32; temp++)

XBYTE[paddr+temp] = pdat[temp];

...

EECON &= ~EEMEN;

EECON &= ~EEMWE;

}

此代碼邏輯清晰,容易了解,可是編譯器沒有那麼智能;編譯器知道pdat指針指向的資料在外部RAM中,用MOVX指令可以讀取;編譯器也知道paddr表示的是要寫入EEPROM的位址,頁用MOVX指令通路;于是,編譯器就将代碼翻譯成如下彙編指令:

ORL   EECON,#08H

ORL   EECON,#010H

...

?C0045:

;  XBYTE[paddr+temp]= pdat[temp]; //将前31位元組寫入頁寫緩沖區

; SOURCE LINE # 242

MOV  DPTR,#pdat?663

MOVX A,@DPTR

MOV  R3,A

INC  DPTR

MOVX A,@DPTR

MOV  R2,A

INC  DPTR

MOVX A,@DPTR

MOV  R1,A

MOV  DPL,R7

MOV  DPH,#00H

LCALL?C?CLDOPTR

MOV  R6,A

MOV  A,R7

MOV  R5,A

MOV  DPTR,#paddr?662+01H

MOVX A,@DPTR

ADD  A,R5

MOV  R5,A

MOV  DPTR,#paddr?662

MOVX A,@DPTR

ADDC A,#00H

MOV  DPL,R5

MOV  DPH,A

MOV  A,R6

MOVX @DPTR,A

INC   R7

MOV   A,R7

CJNE  A,#01FH,?C0045

...

ANL   EECON,#0E7H

紅色部分代碼是讀取pdat數組裡的資料,存入R6中,藍色部分代碼是将R6中的資料寫入paddr表示的EEPROM的位址中去;乍一看,完全符合邏輯,可是MOVX指令的通路目标沒有考慮,在EEPROM使能情況下,MOVX通路的一直是EEPROM,在上面的代碼中,EEPROM始終保持使能狀态,而我們的待寫入資料,是儲存在外部RAM中的,始終沒有被讀取;這樣的代碼,其實是将EEPROM中的某頁資料複制另一頁,而沒有将按照我們的意願将外部RAM中的資料寫入EEPROM;是以,編譯器曲解了我們的C語言代碼。

到目前為止,直接編寫彙編成了唯一可以解決此BUG的方法,于是乎,我們可以修改編譯器彙編好的代碼,在要讀取外部RAM資料時,關閉EEPROM使能,擷取資料,在準備寫入EEPROM時,再打開EEPROM使能;于是乎,我們在頻繁的打開關閉EEPROM使能;于是乎,EEPROM就不正常工作了,寫入失敗;

我們可以參考ATMEL官方給出的例程,編寫彙編代碼;例程中,寫入資料是從寶貴的DATA段擷取的,使用MOV指令就可以輕松得到,不用考慮MOVX通路區域的限制。

至于此,我們隻有拿出32位元組(EEPROM一頁資料大小)寶貴的DATA段空間,用于緩存待寫入資料和讀出資料,才能實作正确的資料讀寫,實作代碼如下:

;定義全局共享資料讀寫緩沖區(32位元組)

RSEG  ?DT?AT89S8253_EEPROM_drv

           buff:   DS   32

RSEG  ?C_INITSEG

DB020H

DB020H

DBbuff

DB000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H

...

; unsigned char W_EEPROM_PAGE(unsigned int paddr, unsigned char * pdat)

RSEG  ?PR?_W_EEPROM_PAGE?AT89S8253_EEPROM_drv

_W_EEPROM_PAGE:

USING0

;将待寫入資料從XDATA段轉儲到DATA段緩沖區

MOV  R4, #0H

MOV  DPH, R2

MOV  DPL, R1

w_p_dat_read:

MOV  A,#LOW(buff)

ADD  A, R4

MOV  R0, A

MOVX A, @DPTR

MOV  @R0, A

INC  DPTR

INC  R4

CJNE R4, #020H, w_p_dat_read 

;使能EEPROM

ORL   EECON,#018H

;檢查電壓是否達到寫EEPROM要求

MOV  A,EECON

ANL  A,#02H

MOV  r0,A

jzw_p_ERROR

;等待EEPROM狀态轉為閑

w_p_rdy1:

MOV  A,EECON

ANL  A,#02H

MOV  r0,A

jzw_p_rdy1

;打開頁寫緩沖區

ORL  EECON,#020H

;向頁寫緩沖區中寫入一頁前31位元組

MOVR4, #0H

MOV  DPL,R7

MOV  DPH,R6

w_p_buff:

MOVA,#LOW(buff)

ADDA, R4

MOVR0, A

MOVA, @R0

MOVX @DPTR,A

INCDPTR

INCR4

CJNER4, #01FH,w_p_buff 

;關閉頁寫緩沖區

ANL  EECON,#0DFH

;寫入一頁的最後一個資料,啟動頁寫周期

MOVA,#LOW(buff)

ADDA, R4

MOVR0, A

MOVA, @R0

MOVX @DPTR,A

;等待硬體響應頁寫

w_p_busy:

MOV  A,EECON

ANL  A,#02H

MOV  r5,A

jnzw_p_busy

;等待寫入完成

w_p_rdy2:

MOV  A,EECON

ANL  A,#02H

MOV  r5,A

jzw_p_rdy2

;從DATA緩沖區讀取寫入的最後一個位元組,存于R5中

MOVA, @R0

MOVR5, A

;将寫入EEPROM的最後一個位元組從EEPROM中讀取出來,暫存于累加器A中

MOVX A, @DPTR

;用相減後零标志位來判斷寫入是否正确

SUBBA, R5

JNZw_p_ERROR

;寫入成功,準備傳回1,表示成功

MOV  R7,#01H

JMPw_p_complete

;寫入失敗,準備傳回0,表示失敗

w_p_ERROR:

MOVR7, #0H

;頁寫完成,關閉EEPROM使能

w_p_complete:

ANL  EECON,#0E7H

; } ; SOURCE LINE # 66

?C0004:

RET  

; END OF _W_EEPROM_PAGE

以下為完整代碼,包括位元組讀、位元組寫、頁讀、頁寫四個部分

$NOMOD51

NAME AT89S8253_EEPROM_drv

EA BIT 0A8H.7

EECON  DATA  96H  ; watchdog and memory control register 

EEMEN  EQU  00001000B  ; EEPROM access enable bit 

EEMWE  EQU  00010000B  ; EEPROM write enable bit 

EELD  EQU  00100000B  ; EEPROM page load enable bit 

WRTINH  EQU  00000001B  ; EEPROM WRTINHbit 

RDY EQU 00000010B ; EEPROM RDY/BSYbit

?PR?_R_EEPROM_BYTE?AT89S8253_EEPROM_drv      SEGMENT CODE 

?XD?_R_EEPROM_BYTE?AT89S8253_EEPROM_drv      SEGMENT XDATA OVERLAYABLE 

?PR?_R_EEPROM_PAGE?AT89S8253_EEPROM_drv      SEGMENT CODE 

?XD?_R_EEPROM_PAGE?AT89S8253_EEPROM_drv      SEGMENT XDATA OVERLAYABLE 

?PR?_W_EEPROM_BYTE?AT89S8253_EEPROM_drv      SEGMENT CODE 

?XD?_W_EEPROM_BYTE?AT89S8253_EEPROM_drv      SEGMENT XDATA OVERLAYABLE 

?PR?_W_EEPROM_PAGE?AT89S8253_EEPROM_drv      SEGMENT CODE 

?XD?_W_EEPROM_PAGE?AT89S8253_EEPROM_drv      SEGMENT XDATA OVERLAYABLE 

?C_INITSEG           SEGMENT CODE 

?DT?AT89S8253_EEPROM_drv SEGMENT DATA 

PUBLIC buff

PUBLIC _W_EEPROM_PAGE

PUBLIC _W_EEPROM_BYTE

PUBLIC _R_EEPROM_PAGE

PUBLIC _R_EEPROM_BYTE

RSEG  ?XD?_W_EEPROM_PAGE?AT89S8253_EEPROM_drv

?_W_EEPROM_PAGE?BYTE:

      paddr?345:   DS   2

ORG  2

       pdat?346:   DS   3

RSEG  ?XD?_R_EEPROM_BYTE?AT89S8253_EEPROM_drv

?_R_EEPROM_BYTE?BYTE:

       addr?040:   DS   2

RSEG  ?XD?_W_EEPROM_BYTE?AT89S8253_EEPROM_drv

?_W_EEPROM_BYTE?BYTE:

       addr?243:   DS   2

ORG  2

        dat?244:   DS   1

RSEG  ?XD?_R_EEPROM_PAGE?AT89S8253_EEPROM_drv

?_R_EEPROM_PAGE?BYTE:

      paddr?141:   DS   2

ORG  2

       pdat?142:   DS   3

RSEG  ?DT?AT89S8253_EEPROM_drv

           buff:   DS   32

RSEG  ?C_INITSEG

DB 020H

DB 020H

DB buff

DB 000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H,000H,000H,000H,000H,000H,000H,000H,000H,000H

DB  000H

;

; unsigned char data buff[32] = {0};

;

; unsigned char R_EEPROM_BYTE(unsigned int addr)//讀一位址,傳回所讀值 

RSEG  ?PR?_R_EEPROM_BYTE?AT89S8253_EEPROM_drv

_R_EEPROM_BYTE:

USING 0

; SOURCE LINE # 21

; MOV   DPTR,#addr?040

; MOV   A,R6

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R7

; MOVX @DPTR,A

; {

; SOURCE LINE # 22

orl  EECON, #EEMEN ; enable EEPROM accesses  ]

r_b_rdy:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz r_b_rdy

mov  DPH, R6

mov  DPL, R7

movx  A, @dptr  ; read EEPROM 

xrl  EECON, #EEMEN ; disable EEPROM accesses

; SOURCE LINE # 23

MOV   R7,A

; }

; SOURCE LINE # 24

?C0001:

RET  

; END OF _R_EEPROM_BYTE

;

; void R_EEPROM_PAGE(unsigned int paddr, unsigned char * pdat)

RSEG  ?PR?_R_EEPROM_PAGE?AT89S8253_EEPROM_drv

_R_EEPROM_PAGE:

; SOURCE LINE # 34

; MOV   DPTR,#paddr?141

; MOV   A,R6

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R7

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R3

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R2

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R1

; MOVX @DPTR,A

; {

orl  EECON, #EEMEN

r_p_rdy:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz r_p_rdy

mov r4, #0h

mov  DPH, R6

mov  DPL, R7

r_p_next:

movx  A, @dptr  ; read EEPROM

mov  r5, A

MOV  A,#LOW (buff)

ADD  A, R4

MOV  R0, A

MOV  @R0, AR5

INC  DPTR

INC  R4

CJNE R4, #020H, r_p_next

ANL  EECON,#0F7H

MOV  R4, #0H

MOV  DPH, R2

MOV  DPL, R1

r_p_save:

MOV  A,#LOW(buff)

ADD  A, R4

MOV  R0, A

MOV  A, @R0

MOVX @DPTR, A

INC  DPTR

INC  R4

CJNE R4, #020H, r_p_save

; }

; SOURCE LINE # 37

RET  

; END OF _R_EEPROM_PAGE

;

; unsigned char W_EEPROM_BYTE(unsigned int addr ,unsigned char dat)

RSEG  ?PR?_W_EEPROM_BYTE?AT89S8253_EEPROM_drv

_W_EEPROM_BYTE:

USING 0

; SOURCE LINE # 48

; MOV   DPTR,#addr?243

; MOV   A,R6

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R7

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R5

; MOVX @DPTR,A

; {

ORL   EECON,#018H

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz w_b_ERROR

w_b_rdy1:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz w_b_rdy1

MOV   DPL,R7

MOV   DPH,R6

MOV   A,R5

MOVX @DPTR,A

w_b_busy:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jnz w_b_busy

w_b_rdy2:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz w_b_rdy2

MOVX A, @DPTR

SUBB A, R5

JNZ w_b_ERROR

MOV   R7,#01H

JMP w_b_complete

w_b_ERROR:

MOV R7, #0H

w_b_complete:

ANL  EECON,#0E7H

; }

; SOURCE LINE # 51

?C0003:

RET  

; END OF _W_EEPROM_BYTE

;

; unsigned char W_EEPROM_PAGE(unsigned int paddr, unsigned char * pdat)

RSEG  ?PR?_W_EEPROM_PAGE?AT89S8253_EEPROM_drv

_W_EEPROM_PAGE:

USING 0

; SOURCE LINE # 63

; MOV   DPTR,#paddr?345

; MOV   A,R6

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R7

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R3

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R2

; MOVX @DPTR,A

; INC   DPTR

; MOV   A,R1

; MOVX @DPTR,A

; {

MOV  R4, #0H

MOV  DPH, R2

MOV  DPL, R1

w_p_dat_read:

MOV  A,#LOW(buff)

ADD  A, R4

MOV  R0, A

MOVX A, @DPTR

MOV  @R0, A

INC  DPTR

INC  R4

CJNE R4, #020H, w_p_dat_read

ORL   EECON,#018H

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz w_p_ERROR

w_p_rdy1:

MOV   A,EECON

ANL   A,#02H

MOV   r0,A

jz w_p_rdy1

ORL   EECON,#020H

MOV R4, #0H

MOV   DPL,R7

MOV   DPH,R6

w_p_buff:

MOV A,#LOW(buff)

ADD A, R4

MOV R0, A

MOV A, @R0

MOVX @DPTR,A

INC DPTR

INC R4

CJNE R4, #01FH,w_p_buff 

ANL   EECON,#0DFH

MOV A,#LOW(buff)

ADD A, R4

MOV R0, A

MOV A, @R0

MOVX @DPTR,A

w_p_busy:

MOV   A,EECON

ANL   A,#02H

MOV   r5,A

jnz w_p_busy

w_p_rdy2:

MOV   A,EECON

ANL   A,#02H

MOV   r5,A

jz w_p_rdy2

MOV A, @R0

MOV R5, A

MOVX A, @DPTR

SUBB A, R5

JNZ w_p_ERROR

MOV   R7,#01H

JMP w_p_complete

w_p_ERROR:

MOV R7, #0H

w_p_complete:

ANL  EECON,#0E7H

; } ; SOURCE LINE # 66

?C0004:

RET  

; END OF _W_EEPROM_PAGE

END

繼續閱讀