leectura y escritura de eeprom 16f877a

Hola que tal companeros
Me gustaria saber su opinion sobre este programa.
ya lo leei lo entendi y lo simule, el problema que veo es que, escribe correctamente pero lee basura y caracteres incorrectos.

agradeceria de su ayuda.


Código:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;                                                                     
;                     Software License Agreement                      
;                                                                     
; The software supplied herewith by Microchip Technology Incorporated 
; (the "Company") for its PICmicro® Microcontroller is intended and   
; supplied to you, the Company’s customer, for use solely and         
; exclusively on Microchip PICmicro Microcontroller products.         
;                                                                     
; The software is owned by the Company and/or its supplier, and is     
; protected under applicable copyright laws. All rights are reserved.  
; Any use in violation of the foregoing restrictions may subject the  
; user to criminal sanctions under applicable laws, as well as to     
; civil liability for the breach of the terms and conditions of this  
; license.                                                             
;                                                                      
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,   
; WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED   
; TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A         
; PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,   
; IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR          
; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.                    
;                                                                     
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;   Filename:           AN976.asm
;   Date:               February 1, 2005
;   File Version:       1.0
;   Assembled using:    MPLAB IDE 7.00.00.0
;
;   Author:             Chris Parris
;   Company:            Microchip Technology, Inc.
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;   Files required:     p16f877a.inc
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;   Purpose:
;
;   This application note is intended to serve as a reference for
;   communicating with Microchip’s I2C serial EEPROM devices with the
;   use of the PICmicro MSSP module.
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
;   Program Description:
;
;   This program illustrates the following I2C operations:
;    - Byte Write
;    - Byte Read
;    - Page Write
;    - Sequential Read
;   For the byte operations, 1 data byte is read from/written to
;   the 24LC256 device. For the page write and sequential read, 16
;   data bytes are transferred. All operations start at address 0x5AA5.
;   All timings are set to meet the 100 kHz spec, and assume a 10 MHz
;   crystal oscillator is used.  If a different crystal frequency is
;   desired, the value of SSPADD (currently 0x18) must be updated in
;   Init. Also, note that no action is taken if the device does not
;   respond with an ACK bit when one is expected.
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  LIST P=16F877A
; Port C pin descriptions
; SCL                   bit = 3
; SDA                   bit = 4
;
; 10MHz crystal is being used, thus each instruction cycle = 400 ns
;
;*******************RAM register definitions**********************
datai       equ     20h         ; Data input byte buffer
datao       equ     21h         ; Data output byte buffer
bytecount   equ     22h         ; Counter for byte loops
pollcnt     equ     23h         ; Counter for polling loops
loops       equ     24h         ; Delay loop counter
loops2      equ     25h         ; Delay loop counter
;*******************Macro definitions*****************************
WRITE_ADDR  equ     b'10100000' ; Control byte for write operations
READ_ADDR   equ     b'10100001' ; Control byte for read operations
;*******************Include file**********************************
    include "p16f877a.inc"      ; Include file for a PIC16F877A
    errorlevel  -302            ; Suppress message 302 from list file
;*****************************************************************
    org     0x000               ; Set the reset vector
    goto    start               ; Go to the beginning of main
;*******************Begin Main Program****************************
start
    call    Init                ; Initialize device
    call    ByteWrite           ; Byte Write operation 
    call    ByteRead            ; Byte Read operation
    call    PageWrite           ; Page Write operation
    call    SequentialRead      ; Sequential Read operation

    nop
    goto    $-1                 ; Loop here forever

;*******************Initialization subroutine*********************
;           This routine initializes the MSSP module
;           for I2C Master mode, with a 100 kHz clock.
;*****************************************************************
Init
    bcf     STATUS,RP1          ; Select Bank 01
    bsf     STATUS,RP0
    movlw   b'11111111'
    movwf   TRISC               ; Set PORTC to all inputs
    clrf    SSPSTAT             ; Disable SMBus inputs
    bsf     SSPSTAT,SMP         ; Disable slew rate control
    movlw   0x18                ; Load 0x18 into WREG
    movwf   SSPADD              ; Setup 100 kHz I2C clock
    clrf    SSPCON2             ; Clear control bits
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   b'00101000'
    movwf   SSPCON              ; Enable SSP, select I2C Master mode
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bcf     PIR2,BCLIF          ; Clear Bit Collision flag
    retlw   0

;*******************Start bit subroutine**************************
;           This routine generates a Start condition
;           (high-to-low transition of SDA while SCL
;           is still high.
;*****************************************************************
BSTART
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,SEN         ; Generate Start condition
    bcf     STATUS,RP0          ; Select Bank 00
bstart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    bstart_wait         ; If not, keep checking

    retlw   0

;*******************Restart bit subroutine**************************
;           This routine generates a Repeated Start
;           condition (high-to-low transition of SDA
;           while SCL is still high.
;*****************************************************************
BRESTART
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RSEN        ; Generate Restart condition
    bcf     STATUS,RP0          ; Select Bank 00
brestart_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    brestart_wait       ; If not, keep checking

    retlw   0

;*******************Stop bit subroutine***************************
;           This routine generates a Stop condition
;           (low-to-high transition of SDA while SCL
;           is still high.
;*****************************************************************
BSTOP
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,PEN         ; Generate Stop condition
    bcf     STATUS,RP0          ; Select Bank 00
bstop_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    bstop_wait          ; If not, keep checking

    retlw   0

;*******************Data transmit subroutine**********************
;           This routine transmits the byte of data
;           stored in 'datao' to the serial EEPROM
;           device. Instructions are also in place
;           to check for an ACK bit, if desired.
;           Just replace the 'goto' instruction,
;           or create an 'ackfailed' label, to provide
;           the functionality.
;*****************************************************************
TX
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    movf    datao,W             ; Copy datao to WREG
    movwf   SSPBUF              ; Write byte out to device
tx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    tx_wait             ; If not, keep checking
;   bsf     STATUS,RP0          ; Select Bank 01
;   btfsc   SSPCON2,ACKSTAT     ; Check if ACK bit was received
;   goto    ackfailed           ; This executes if no ACK received    

    retlw   0

;*******************Data receive subroutine***********************
;           This routine reads in one byte of data from
;           the serial EEPROM device, and stores it in
;           'datai'.  It then responds with either an
;           ACK or a NO ACK bit, depending on the value
;           of 'ACKDT' in 'SSPCON2'.
;*****************************************************************
RX
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,RCEN        ; Initiate reception of byte
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait             ; If not, keep checking
    movf    SSPBUF,W            ; Copy byte to WREG
    movwf   datai               ; Copy WREG to datai
    bcf     PIR1,SSPIF          ; Clear SSP interrupt flag
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKEN       ; Generate ACK/NO ACK bit    
    bcf     STATUS,RP0          ; Select Bank 00
rx_wait2
    btfss   PIR1,SSPIF          ; Check if operation completed
    goto    rx_wait2            ; If not, keep checking

    retlw   0

;*******************Byte write test subroutine********************
;           This routine tests the byte write feature
;           of the serial EEPROM device.  It will write
;           1 byte of data to the device at address 0x5AA5.
;*****************************************************************
ByteWrite
    call    BSTART              ; Generate Start condition

                                ; Send control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR          ; Load control byte for write
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0x5A                ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    call    TX

                                ; Send word address low byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0xA5                ; Load 0xA5 for word address
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send word address to device

                                ; Send data byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0xAA                ; Load 0xAA for data byte
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send data byte to device

    call    BSTOP               ; Generate Stop condition

    call    Poll                ; Poll for write completion

    retlw   0

;*******************Page write test subroutine********************
;           This routine demonstrates the page write
;           feature of the serial EEPROM device.  It will
;           write 16 bytes of data to the device starting
;           at address 0x5AA5.  Since this is a page write,
;           all 16 bytes will be written to the device at
;           the same time.
;*****************************************************************
PageWrite
    bcf     STATUS,RP1
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   .16
    movwf   bytecount           ; Initialize counter to 16 bytes

    call    BSTART              ; Generate start bit
                                ; Now we send the control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR
    movwf   datao               ; Copy control byte to buffer
    call    TX                  ; Output control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0x5A                ; Use 0x5A for address to send
    movwf   datao               ; Copy address to buffer
    call    TX

                                ; Send word address low byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0xA5                ; Use 0xA5 for address to send
    movwf   datao               ; Copy address to buffer
    call    TX                  ; Output address to device

    bcf     STATUS,RP0          ; Select Bank 00
txbyte                          ; This loop transfers all 16 of
                                ; the data bytes to the device
    movf    bytecount,W         ; Use bytecount as data value
    movwf   datao               ; Copy data to buffer
    call    TX                  ; Output data to device

    bcf     STATUS,RP0          ; Select Bank 00
    decfsz  bytecount,F         ; Check if finished looping
    goto    txbyte              ; Continue looping

    call    BSTOP               ; Generate stop bit
    call    Poll                ; Poll for write completion
    retlw   0

;*******************Byte read test subroutine*********************
;           This routine tests the byte read feature
;           of the serial EEPROM device.  It will read
;           1 byte of data at address 0x5AA5 from the device.
;*****************************************************************
ByteRead
    call    BSTART              ; Generate Start condition

                                ; Send control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR          ; Load control byte for write
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0x5A                ; Load 0x5A for word address
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send high byte to device

                                ; Send word address low byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0xA5                ; Load 0xA5 for word address
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send word address to device

    call    BRESTART            ; Generate Restart condition

                                ; Send control byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   READ_ADDR           ; Load control byte for read
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send control byte to device

                                ; Read data byte
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT       ; Select to send NO ACK bit
    call    RX                  ; Read data byte from device

    call    BSTOP               ; Generate Stop condition

    retlw   0

;*******************Sequential read test subroutine***************
;           This routine tests the sequential read feature
;           of the serial EEPROM device.  It will read 16
;           bytes of data to the device starting at
;           address 0x50, one byte after another.
;*****************************************************************
SequentialRead
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   .16
    movwf   bytecount           ; Initialize counter to 16 bytes

    call    BSTART              ; Generate start bit
                                ; Now send the control byte
                                ; for a write, to set address
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR
    movwf   datao               ; Copy control byte to buffer
    call    TX                  ; Output control byte to device

                                ; Send word address high byte
    bcf     STATUS,RP0          ; Select Bank 00
    clrf    datao               ; Load 0x00 into datao
    call    TX                  ; Send high byte to device

                                ; Send word address low byte
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   0x50                ; Load 0x50 for word address
    movwf   datao               ; Copy to datao for output
    call    TX                  ; Send word address to device

    call    BRESTART            ; Generate another start bit
                                ; to switch to read mode
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   READ_ADDR
    movwf   datao               ; Copy control byte to buffer
    call    TX                  ; Output control byte to device

rxbyte
                                ; Finally, read the data byte
    bcf     STATUS,RP0          ; Select Bank 00
    decfsz  bytecount,F         ; Check if finished looping
    goto    continue            ; If not finished, keep going
    bsf     STATUS,RP0          ; Select Bank 01
    bsf     SSPCON2,ACKDT       ; Otherwise, select to send NO ACK bit
    call    RX                  ;   and input final byte from device

    call    BSTOP               ; Generate stop bit
    retlw   0

continue
    bsf     STATUS,RP0          ; Select Bank 01
    bcf     SSPCON2,ACKDT       ; Select to send ACK bit
    call    RX                  ; Input data from device
    goto    rxbyte              ; Continue looping

;*******************Acknowledge Polling subroutine****************
;           This subroutine polls the EEPROM device
;           for an ACK bit, which indicates that the
;           internal write cycle has completed. Code
;           is in place for a timeout routine, just
;           uncomment the 'goto TimedOut' line, and
;           provide a 'TimedOut' label.
;*****************************************************************
Poll
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   .40
    movwf   pollcnt             ; Set max polling times to 40
polling
    call    BRESTART            ; Generate start bit
    bcf     STATUS,RP0          ; Select Bank 00
    movlw   WRITE_ADDR          ; Now send the control byte
    movwf   datao               ; Copy control byte to buffer
    call    TX                  ; Output control byte to device
    bsf     STATUS,RP0          ; Select Bank 01
    btfss   SSPCON2,ACKSTAT     ; Was the ACK bit low?
    goto    exitpoll            ; If yes, stop polling
                                ; If no, check if polled 40 times
    bcf     STATUS,RP0          ; Select Bank 00
    decfsz  pollcnt,F           ; Is poll counter down to zero?
    goto    polling             ; If no, poll again
;   goto    TimedOut            ; If yes, part didn't respond
                                ; in time, so take action
exitpoll
    call    BSTOP               ; Generate stop bit
    retlw   0

    END
 
Atrás
Arriba