Frank01
Newbie
- Joined
- Mar 23, 2014
- Messages
- 3
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,281
- Activity points
- 1,336
With all the great information on this web site and others, and the plethora of tutorials and application notes, I thought that sending data from a PIC 16F877A to an external EEPROM using I2C protocol would be a piece of cake. I was wrong!!
I have researched I2C on this site and others, and have downloaded a fair amount of information (AN735 Using the PICmicro MSSP Module for Master I2C Communications, I2C Master Mode Overview and Use of the PICmicro MSSP I2C Interface with a 24xx01x EEPROM - Tutorial, AN974 Interfacing I2C Serial EEPROMs to PICmicro Microcontrollers,
24C32 32K 5.0V I2C Smart Serial EEPROM Data Sheet, AN578 Use of the SSP Module in the I2C Multi-Master Environment, PICmicro Mid-Range MCU Family Reference Manual - DS33023A - Section 17. Master Synchronous Serial Port (MSSP), AN976 Using the MSSP Module to Interface I2C Serial EEPROMs with PIC16 Devices), so I am not trying to get someone to write the code for me. I finally decided to show the code to folks who actually know what they are doing.
I don't know if the Oshon PIC Simulator IDE package is at fault, or it is in the program. Based on the many postings on I2C problems, I suspect it is my program. I don't even see PIR1,SSPIF being set at any point. To make the program simpler, I reduced it to trying to transmit a single data byte.
Thanks in advance for taking a look at it and I'd appreciate any help.
I have researched I2C on this site and others, and have downloaded a fair amount of information (AN735 Using the PICmicro MSSP Module for Master I2C Communications, I2C Master Mode Overview and Use of the PICmicro MSSP I2C Interface with a 24xx01x EEPROM - Tutorial, AN974 Interfacing I2C Serial EEPROMs to PICmicro Microcontrollers,
24C32 32K 5.0V I2C Smart Serial EEPROM Data Sheet, AN578 Use of the SSP Module in the I2C Multi-Master Environment, PICmicro Mid-Range MCU Family Reference Manual - DS33023A - Section 17. Master Synchronous Serial Port (MSSP), AN976 Using the MSSP Module to Interface I2C Serial EEPROMs with PIC16 Devices), so I am not trying to get someone to write the code for me. I finally decided to show the code to folks who actually know what they are doing.
I don't know if the Oshon PIC Simulator IDE package is at fault, or it is in the program. Based on the many postings on I2C problems, I suspect it is my program. I don't even see PIR1,SSPIF being set at any point. To make the program simpler, I reduced it to trying to transmit a single data byte.
Thanks in advance for taking a look at it and I'd appreciate any help.
Code:
;INITIALLY WRITTEN 2014 03 20
;LAST UPDATE 2014 03 22
;USING OSHON PIC SIMULATOR IDE VERSION 6.98
;4 MHZ CRYSTAL
;16F877A PIC MICROCONTROLLER
;100 KBS SPEED
;EXTERNAL EEPROM - 24C32
;PROGRAM IS LIMITED TO SENDING A SINGLE BYTE TO THE EXTERNAL EEPROM AND MAKING SURE ALL THE CONTROL CODES ARE GOOD
;AND THAT START/STOP/ACK/NACK ETC ARE WORKING
;SIMULATOR TESTING HAS BEEN PERFORMED AND DOES NOT WORK, ACTUAL HARDWARE HAS NOT BEEN BUILT
;CONFIGURATION, SPEED, AND MICROCONTROLLER CHOICE USED THE PIC SIMULATOR IDE OPTIONS COMMAND
;THE PIC SIMULATOR IDE ASSEMBLER STRIPPED OUT THE INCLUDE STATEMENT AND THE CONFIGURATION STATEMENT
;========================================================================================================================
LC01CTRLIN EQU 0xA0 ; CONTROL BYTE SENT TO 24C32 WHEN INPUTTING DATA TO THE 24C32 - 1010 0000 - LAST BIT SETS I2C TO WRITE
LCO1ADDRH EQU 0x00 ; HIGH ORDER ADDRESS BYTE TO BE SENT TO 24C32 EEPROM
LC01ADDRL EQU 0x12 ; LOW ORDER ADDRESS BYTE TO BE SENT TO 24C32 EEPROM
LC01DATA EQU 0x34 ; DATA BYTE TO BE SENT TO 24C32 EEPROM
OUTERCOUNT EQU 0x021 ; ADDRESS OF LOOP OUTER COUNT
INNERCOUNT EQU 0x020 ; ADDRESS OF LOOP INNER COUNT
;
#INCLUDE <P16f877A.INC>
ORG 0x0 ; START OF PROGRAM
; *** SETUP I/O ***
START
BANKSEL PORTB ; BANK 0
CLRF PORTB ; PORTB CLEARED
CLRF PORTC ; PORTC CLEARED
BCF PIR1,SSPIF ; CLEAR SSP INTERRUPT FLAG
BCF PIR2,BCLIF ; CLEAR BUS COLLISION INTERRUPT FLAG
BANKSEL TRISC ; BANK 1
MOVLW 0x18 ; LOAD ACCUMULATOR WITH 0xFF
MOVWF TRISC ; PINS 3 & 4 ARE INPUTS ON PORTC - 0001 1000 - ALL OTHERS ARE OUTPUTS
CLRF TRISB ; ALL PORTB PINS SET TO OUTPUT - 0000 0000
; CONFIGURE THE MSSP IN I2C MASTER MODE
BANKSEL SSPCON ; BANK 0
BSF SSPCON,SSPEN ; ENABLE SERIAL PORT, CONFIGURE SDA & SCL AS SERIAL PORT PINS
BSF SSPCON,SSPM3 ; CONFIGURES MSSP IN I2C MASTER MODE
BANKSEL SSPADD ; BANK 1
MOVLW 0x09 ; LOAD ACCUMULATOR WITH 0x09
MOVWF SSPADD ; SSPADD MUST EQUAL 9 TO SET SPEED TO 100 KBS WITH A 4000 KHZ OSC
BSF SSPSTAT,SMP ; SLEW RATE DISABLED, SETS 100 KBS SPEED
BCF SSPSTAT,CKE ; INPUT LEVELS CONFIGURED FOR I2C OPERATION
BSF SSPCON2,SEN ; GENERATE START
CALL WAITMSSP ; WAIT FOR ACK
MOVLW LC01CTRLIN ; CONTROL BYTE TO BE SENT TO SSBUF - 1010 0000 - 1010 IS THE CONTROL CODE FOR THE 24C32 EEPROM
; THE FIRST THREE ZEROS IN THE SECOND NIBBLE ARE THE ADDRESS OF THE 24C32 EEPROM
; THE FOURTH & FINAL ZERO INDICATES WRITE
CALL SEND_I2C_BYTE ; SEND THE ACCUMULATOR VALUE TO SSBUF
CALL WAITMSSP ; WAIT FOR ACK
BTFSC SSPCON2,ACKSTAT ; TEST ACK STATUS BIT - IF CLEAR, SKIP THIS INSTRUCTION
CALL I2CFAIL ; ACK STATUS BIT WAS SET, ACK FAILED. IF ACK SUCCESSFUL, SKIP THIS LINE
MOVLW LCO1ADDRH ; HIGH ORDER BYTE WHERE DATA WILL BE STORED IN 24C32 EEPROM
CALL SEND_I2C_BYTE ; SEND THE ACCUMULATOR VALUE TO SSBUF
CALL WAITMSSP ; WAIT FOR ACK
BANKSEL SSPCON2
BTFSC SSPCON2,ACKSTAT ; TEST ACK STATUS BIT - IF CLEAR, SKIP THIS INSTRUCTION
CALL I2CFAIL ; FAILED
MOVLW LC01ADDRL ; LOW ORDER BYTE WHERE DATA WILL BE STORED IN 24C32 EEPROM
CALL SEND_I2C_BYTE ; SEND THE ACCUMULATOR VALUE TO SSBUF
CALL WAITMSSP ; WAIT FOR ACK
BANKSEL SSPCON2
BTFSC SSPCON2,ACKSTAT ; TEST ACK STATUS BIT - IF CLEAR, SKIP THIS INSTRUCTION
CALL I2CFAIL ; FAILED
MOVLW LC01DATA ; LOAD DATA BYTE INTO ACCUMULATOR
CALL SEND_I2C_BYTE ; SEND THE ACCUMULATOR VALUE TO SSBUF
CALL WAITMSSP ; WAIT UNTIL THE SSPIF BIT IS SET INDICATING RECEIPT OF AN "ACK"
BANKSEL SSPCON2
BTFSC SSPCON2,ACKSTAT ; TEST ACK STATUS BIT - IF CLEAR, SKIP THIS INSTRUCTION
CALL I2CFAIL ; FAILED
BSF SSPCON2,PEN ; SEND STOP
END
;========================================================================================================================
;HOLD LOOP
HOLD CALL HOLD ; LOOP
SEND_I2C_BYTE
BANKSEL SSPBUF ; BANK 0
MOVWF SSPBUF ; MOVE ACCUMULATOR VALUE TO SSBUF
RETLW 0 ; RETURN
I2CFAIL
BANKSEL SSPCON2
BSF SSPCON2,PEN ; SEND STOP
CALL WAITMSSP ; WAIT FOR ACK
CALL HOLD ; LOOP
;DELAY LOOP
WAITMSSP
BANKSEL PORTC
MOVLW 0x02
MOVWF OUTERCOUNT
HERE2 MOVLW 0xFF
MOVWF INNERCOUNT
HERE DECFSZ INNERCOUNT,F
CALL HERE
DECFSZ OUTERCOUNT,F
CALL HERE2
RETLW 0