Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] I2c + 16f877a + 24lc16b

Status
Not open for further replies.

Frank01

Newbie
Joined
Mar 23, 2014
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,335
Here we go again with I2C and trying to get a 16F877A to send a data byte to a specific memory location on a 24LC16 EEPROM and read the data byte back to the 16F877A. The code generally follows the Microchip I2C Master Mode Tutorial. When the attached code is run using the Pickit3, the 16F877A shows 0xFF on PORTD at the end of the program. I am curious where the 0xFF came from. PORTD should show 0x34 at the conclusion. Hopefully, someday IÂ’ll actually be able to pull data from a real time clock. First, I have to be able to send and receive eight bits.

I rewrote this program several times and put routines in to look at various bytes/bits using leds on PORTD. The program appears to be sending & receiving the correct control, address, and data bytes. It just continues to put 0xFF on PORTD at the end of the program instead of the data byte sent to the EEPROM.

IÂ’m sure the error is trivial, but like many others, learning I2C on your own can be tedious. The last time I felt this frustrated was in college when I was attempting to program a PDP-8. The PDP-8 used individual toggle switches to set each bit, then you pressed a spring loaded toggle switch to transfer the byte, then entered the rest of the program. As you can imagine, entering a long program was brutal. If there were problems when the program ran, there were no diagnostics, the PDP-8 just sat there.

Thanks in advance for any ideas on how to tame the beast.
==================================================================
Code:
;============================================
; I2C connected to 24LC16B - only one address byte, no upper byte
; Write to location 0x12, data 0x34 and read it back. 
; I2C MASTER mode is in use.
;
LC01CTRLIN     equ    0xA0     ; I2C value for CONTROL BYTE when INputing data to the EEPROM -                     ; 1010 0000 - master to slave transfer
LC01CTRLOUT     equ    0xA1     ; I2C value for CONTROL BYTE when requesting OUTput from EEPROM -                     ; 1010 0001 - slave to master transfer
LC01ADDR     equ    0x12     ; Sample value for ADDRESS BYTE - 0001 0012 - 0x12
LC01DATA     equ    0x34     ; Sample data to write to EEPROM - 0011 0100 - 0x34
;
;=====================================================
;
 #include <p16F877.inc>     ; Processor Include file
 __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
;
    ORG 0             ; Start of code
; *** Setup I/O ***
    banksel    TRISD        ; go to bank1
    clrf    TRISD        ; sets all PORTD pins to outputs - using portd instead of portb
;
    banksel     TRISC         ; go to bank1
    movlw     0x18        ; RC3, RC4 are inputs for PORTC - 0001 1000
    movwf     TRISC         ; Remaining PORTC pins are output
;
; *** Setup Registers for I2C ***
;
; Configure MSSP module for Master Mode
    banksel SSPCON    ; go to bank0
    movlw     0x28        ; Enables MSSP and uses PORTC pins for I2C mode(SSPEN set)& enables                     ; I2C Master Mode (SSPMx bits = 1000)
    movwf     SSPCON    ; move 0x28 to the file SSPCON
;
; Input Levels and slew rate set to I2C
    banksel    SSPSTAT
    movlw     0x80         ; Slew Rate control (SMP) 100kHz mode and input levels are I2C
    movwf     SSPSTAT     ; move 0x80 to SSPSTAT
;
; Configure Baud Rate - (FOSC/(4*BAUD))-1 = (4000/(4*100))-1 = (4000/400)-1 = 10-1 = 9 - Calculates 
; SSPADD for desired Baud rate and sets up SSPADD
    banksel SSPADD
    movlw     0x09
    movwf     SSPADD
;
;========================================================
;
; *** Begin I2C Data Transfer Sequences ***
I2CWrite
; Enable START and wait for it to complete
    banksel SSPCON2     ; BANK 1
    bsf     SSPCON2,SEN     ; Enable START
    call     WaitMSSP    ; Wait for I2C to finish
;    
; Transfer CONTROL BYTE, wait for it to complete
    movlw     LC01CTRLIN     ; Load CONTROL BYTE (input to eeprom mode) - 1010 0000 - 0xA0
    call     Xfer_I2C_Byte     ; Send Byte    
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CFail         ; failed, skip this instruction if ack or nack received
;    
; Transfer ADDRESS BYTE, wait for it to complete
    movlw     LC01ADDR    ; Load Address Byte - 0001 0010 - 0x12
    call     Xfer_I2C_Byte     ; Send Byte
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CFail         ; failed, skip this instruction if ack or nack received
;
; Transfer DATA BYTE, wait for it to complete
;
    movlw     LC01DATA    ; Load Data Byte - 0011 0100 - 0x34
    call     Xfer_I2C_Byte     ; Send Byte
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CFail         ; failed, skip this instruction if ack or nack received
;
; Transfer the STOP condition, wait for it to complete
    banksel SSPCON2
    bsf     SSPCON2,PEN     ; Send STOP condition
    call     WaitMSSP     ; Wait for I2C to finish. no need to check for ack or nack.
;
; The WRITE has now completed successfully.
;
;===================================================
;
; Begin the Read Sequence
I2CRead
;
; Enable RESTART and wait for it to complete
    banksel SSPCON2
    bsf     SSPCON2,RSEN     ; Enable RESTART
    call     WaitMSSP     ; Wait for I2C to finish
;
; Transfer CONTROL BYTE, wait for it to complete
    movlw     LC01CTRLIN     ; Load CONTROL BYTE (input to eeprom)- 0xA0 - 1010 0000
    call     Xfer_I2C_Byte     ; Send Byte
    call     WaitMSSP     ; Wait for I2C to finish
;    
; Check to see if I2C EEPROM is ready
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CRead     ; ACK Poll waiting for EEPROM write to complete
;
; Transfer ADDRESS BYTE, wait for it to complete
    movlw     LC01ADDR     ; Load ADDRESS BYTE
    call     Xfer_I2C_Byte     ; Send Byte
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CFail         ; failed, skip this instruction if ack or nack received
;
; Transfer REPEATED START condition and wait for it to complete
    banksel    SSPCON2
    bsf     SSPCON2,RSEN     ; Generate RESTART Condition
    call     WaitMSSP     ; Wait for I2C to finish
;
; Transfer CONTROL BYTE (slave to master), wait for it to complete
    movlw     LC01CTRLOUT     ; Load CONTROL BYTE (output)
    call     Xfer_I2C_Byte     ; Send Byte
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel SSPCON2
    btfsc     SSPCON2,ACKSTAT ; Check ACK Status bit
    goto     I2CFail         ; failed, skip this instruction if ack or nack received
;
; Switch MSSP module to I2C Receive mode
    bsf     SSPCON2,RCEN     ; Enable Receive Mode (I2C)
    call     WaitMSSP     ; Wait for I2C to finish
    
; Get the DATA BYTE and wait for it to complete. Data is in SSPBUF when completed.
; The receive mode is disabled at end automatically by the MSSP module.
; Transfer NACK bit for Acknowledge Sequence
    banksel    SSPCON2
    bsf     SSPCON2,ACKDT ; setting the ackdt bit to nack
    bsf     SSPCON2,ACKEN ; enable ackstat check
; Once ACK or NACK is enabled, ACKDT is automatically cleared
;
;========================================================
;
; Transfer the STOP condition and wait for it to complete
    banksel    SSPCON2
    bsf     SSPCON2,PEN     ; Send STOP condition
    call    WaitMSSP    ; Wait for I2C to finish
;
;===================================================
;
; I2C Write and Read have both finished, move DATA from file SSPBUF to PORTD
    banksel    SSPBUF
    movf     SSPBUF,W     ; Transfer data from SSPBUF into W
    movwf    PORTD        ; Move the value in SSPBUF to PORTD
;
    goto     $         ; Loop forever
; Program has finished and completed successfully.
;
; *** SUBROUTINES & ERROR HANDLERS ***
;========================================================
;
; Transfer the value in the accumulator to SSPBUF. The SSPIF flag is checked to ensure the byte has been ; sent. On completion, the routine exits.
Xfer_I2C_Byte
    banksel SSPBUF     ; BANK 0
    movwf     SSPBUF     ; Put value to transfer in SSPBUF
    retlw    0
;
;========================================================
; I2C sequence failed - This will normally not happen, but if it does, a STOP is sent, the program loops, and the entire code must be tried again.
I2CFail
    banksel SSPCON2
    bsf     SSPCON2,PEN     ; Send STOP condition
    call     WaitMSSP     ; Wait for I2C to finish
;
    banksel PORTD         ; BANK 0
    clrf    PORTD        ; clear portd
    movlw    0xfe
    movwf    PORTD
;
    goto     $         ; Loop forever
;
;=========================================================
; This routine waits for I2C to finish. It does this by polling the SSPIF flag in PIR1.
WaitMSSP
    banksel PIR1         ; BANK 0
    btfss     PIR1,SSPIF     ; Check if I2C is completed (SSPIF set)
    goto     $-1         ; SSP, keep testing SSPIF
    bcf     PIR1,SSPIF     ; SSPIF was set, I2C ready, clear SSPIF        
    retlw    0
;
END                 ;End of Program 
====================================================================
 
Last edited by a moderator:

I wonder if someone is motivated to review assembly code in detail?

Personally, I'm not. I see however that you are starting EEPROM read immediately after write. Review a 2416 datasheet to understand why this can't work. You either wait for the maximal expectable write time or perform ACK polling for actual finish of write action.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top