I tried to use above code with 24C32 and PIC16F887 but it does not works. It stuck on this loop: while SSPCON2.0 = 1 : wend
Here's complete code:
Code:
'****************************************************************
'* Name : I2C EEPROM *
'* Author : Daniel T. Barber *
'* Notice : Copyright (c) 2018 *
'****************************************************************
@ ERRORLEVEL -306 ' turn off crossing page boundary message
'************ Config Settings for 16F877A *************
#CONFIG
cfg1 = _INTRC_OSC_NOCLKOUT ; INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN
cfg1&= _WDT_ON ; WDT enabled
cfg1&= _PWRTE_OFF ; PWRT disabled
cfg1&= _MCLRE_OFF ; RE3/MCLR pin function is digital input, MCLR internally tied to VDD
cfg1&= _CP_OFF ; Program memory code protection is disabled
cfg1&= _CPD_OFF ; Data memory code protection is disabled
cfg1&= _BOR_OFF ; BOR disabled
cfg1&= _IESO_ON ; Internal/External Switchover mode is enabled
cfg1&= _FCMEN_ON ; Fail-Safe Clock Monitor is enabled
cfg1&= _LVP_OFF ; RB3 pin has digital I/O, HV on MCLR must be used for programming
cfg1&= _DEBUG_OFF ; In-Circuit Debugger disabled, RB6/ICSPCLK and RB7/ICSPDAT are general purpose I/O pins
__CONFIG _CONFIG1, cfg1
cfg2 = _BOR40V ; Brown-out Reset set to 4.0V
cfg2&= _WRT_OFF ; Write protection off
__CONFIG _CONFIG2, cfg2
#ENDCONFIG
TRISA=%00000000 'SET A TO OUTPUT 1=input
TRISC=%00011000 'set C 3 4 input
TRISB=%00000000 'set PortB to output
ANSELH=%00000000 ' ADC OFF B
ANSEL=%00000000 'configure PortA as digital except first 2
ADCON1=%10000000 'adc justify
OSCCON=%01110101 'SET FREQUENCY TO 8MHZ
WPUB=%00000000 'turn off Pullups
CM1CON0=0 'DISABLE COMPARATORS
CM2CON0=0 'SAME HERE
Define OSC 8 'Adjust consistent with oscillator speed being used
ADCON1 = 7 ' Set PORTA and PORTE to digital
DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 2
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 3
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1500
DEFINE LCD_DATAUS 44
'clear
I2CBufferSize con 64
Reg_Pointer Var Byte ; Address register
I2CDATA Var Byte ; data to read/write
I2CAddr Var Byte ; Device address
I2C_Wait var byte
countI2C var byte
I2CWRBuff var byte (I2CBufferSize)
I2CWRsize Var Byte
I2CRDBuff var byte (I2CBufferSize)
I2CRDsize Var Byte
I2CErrCode Var Byte
I2CErrCode = 0
x var byte 'temp var
SSPSTAT.7 = 0 ; SMP<7> - Slew rate control Enabled (400kHz)
SSPCON = %00101000
; | ''''-- SSPM<3:0> - I2C Master mode, clock = FOSC / (4 * (SSPADD+1))
; '-------- SSPEN<5> - Synchronous Serial Port Enable bit
SSPADD = $0E ; set I2C clock rate to 400kHz
'SSPADD = $59 ; set I2C clock rate to 100kHz
for x=0 to 255
lcdout $fe, $2, "wait..."
I2CAddr=x
gosub read1byte
lcdout $fe, $2, "data=", dec i2cdata
pause 1000
next
stop
;-----------------------------------------------------------
; Main Routines
;-----------------------------------------------------------
Write1Byte:
I2CErrCode.1 = 0
I2CAddr.0 = 0 ;Set Write Bit
Gosub StartI2C ;Send Start, Addr, Wait for Ack
if I2CErrCode.1 = 1 then RETURN
I2CDATA = I2CWRBuff(0)
gosub I2CWRByte ;Send I2CDATA Byte
Gosub SendStopBit ;Send Stop Bit
Return
;-----------------------------------------------------------
WriteXBytes:
I2CErrCode.1 = 0
I2CAddr.0 = 0 ;Set Write Bit
Gosub StartI2C ;Send Start, Addr, Wait for Ack
if I2CErrCode.1 = 1 then RETURN
For countI2C = 0 to I2CWRsize-1
I2CDATA = I2CWRBuff(countI2C)
; hserout [dec countI2C,"-",ihex2 I2CDATA," ",13,10]
gosub I2CWRByte ;Send I2CDATA Byte
next countI2C
Gosub SendStopBit ;Send Stop Bit
Return
;-----------------------------------------------------------
Read1Byte:
I2CErrCode.1 = 0
I2CAddr.0 = 1 ;Set Read Bit
Gosub StartI2C ;Send Start, Addr, Wait for Ack
if I2CErrCode.1 = 1 then RETURN
gosub I2CRDByte
I2CRDBuff(0) = I2CDATA
gosub Send_NO_Ack
Gosub SendStopBit
Return
;-----------------------------------------------------------
ReadXBytes:
I2CErrCode.1 = 0
I2CAddr.0 = 1 ;Set Read Bit
Gosub StartI2C ;Send Start, Addr, Wait for Ack
if I2CErrCode.1 = 1 then RETURN
for countI2C = 0 to I2CRDsize-2
gosub I2CRDByte
gosub Send_Ack
I2CRDBuff(countI2C) = I2CDATA
next countI2C
countI2C = I2CRDsize - 1
gosub I2CRDByte
gosub Send_NO_ACK
Gosub SendStopBit
I2CRDBuff(countI2C) = I2CDATA
Return
;-----------------------------------------------------------
; Process Routines
;-----------------------------------------------------------
StartI2C:
;Send Start Bit
SSPCON2.0 = 1 ; SEN<0> - Send start bit
while SSPCON2.0 = 1 : wend ; Wait for completion
;Send Slave Address
PIR1.3 = 0 ; SSPIF - Clear interrupt Flag
SSPBUF = I2CAddr ; move slave address to SSPBUF
While PIR1.3 = 0 : Wend ; SSPIF - Wait for SSP to complete sending slave address
;Wait for Acknowledge or Restart
i2c_wait = 0 ; Reset wait counter
While SSPCON2.6 = 1 ; Wait for Acknowledge from slave 1=NotAck
I2C_Wait = I2C_Wait + 1 ; Increment wait counter
if I2C_Wait = 0 then ; Wait for 256 counts
goto I2CResError ; Acknowledge "Time Out" - Report error and RETURN
else
; Send Repeated Start
SSPCON2.1 = 1 ; RSEN - Send Repeated Start
while SSPCON2.1 = 1 : wend ; Wait for completion
; Resend the Slave Address
PIR1.3 = 0 ; SSPIF - Clear interrupt Flag
SSPBUF = I2CAddr ; move slave address to SSPBUF
While PIR1.3 = 0 : Wend ; SSPIF - Wait to complete sending Slave Address
endif
wend
RETURN ; Acknowledge recieved
Return
;-----------------------------------------------------------
I2CWRByte:
PIR1.3 = 0 ; SSPIF - Clear interrupt Flag
SSPBUF = I2CDATA ; Move data to SSPBUF
While PIR1.3 = 0 : Wend ; SSPIF - Wait for SSP to complete sending
;Wait for Acknowledge or Abort
i2c_wait = 0 ; Reset wait counter
While SSPCON2.6 = 1 ; Wait for Acknowledge from slave 1=NotAck
I2C_Wait = I2C_Wait + 1 ; Increment wait counter
if I2C_Wait = 0 then ; Wait for 256 counts
goto I2CResError ; Acknowledge "Time Out" - Report error and RETURN
endif
wend
RETURN ; Acknowledge recieved
Return
;-----------------------------------------------------------
I2CRDByte:
PIR1.3 = 0 ; SSPIF - Clear interrupt Flag
SSPCON2.3 = 1 ; RCEN - Enable receive mode
While PIR1.3 = 0 : Wend ; SSPIF - Wait for SSP to complete receiving
I2CDATA = SSPBUF
Return
;-----------------------------------------------------------
SendStopBit
SSPCON2.2 = 1 ; PEN - send stop bit
While SSPCON2.2 = 1 : Wend ; Wait for SSP to complete
Return
;-----------------------------------------------------------
Send_NO_Ack:
SSPCON2.5 = 1 ; ACKDT - Set Ack bit to NotAck
SSPCON2.4 = 1 ; ACKEN - send ACKDT bit
While SSPCON2.4 = 1 : Wend ; Wait for SSP to complete
Return
;-----------------------------------------------------------
Send_Ack:
SSPCON2.5 = 0 ; ACKDT - Set Ack bit to Ack
SSPCON2.4 = 1 ; ACKEN - send ACKDT bit
While SSPCON2.4 = 1 : Wend ; Wait for SSP to complete
Return
;-----------------------------------------------------------
I2CResError:
I2CErrCode.1 = 1
lcdout $fe, $2, "I2C Error!!!"
Return
;-----------------------------------------------------------
Bookmarks