Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Pic16f684 and 24lcxx eeproms using i2c

Status
Not open for further replies.

Steve311

Member
hi all ; im stuck with receiving acks with a pic16f628 and 24lc16 eeprom. Ive used i2c before so i know my routines are ok.. Does anyone know any tricks, tips or advice with communication with these two chips? anytging special with delays, clock pulses etc? im unable to post my code until tomorrow night as i dont have my computer...

Any quick advice?

Thanks!
 
Well...since you're using a 16F628....which does not have a MSSP (Master Synchronous Serial Port...which does both SPI/I2C), this tells me that you're using some sort of a software I2C routine to communicate with the 24LC16. Without your code, there's not much help we can give you unfortunately.

Can you post up your code so we can take a look? A schematic of your circuit would be an immense help as well.
 
Thanks for the response. I can post my code later on tonite when I get home. I was considering using a pic16f1824 which does have MSSP. Is this hardware module difficult to use? I read the datasheet on it and it does seem a little tricky...

In my end product, I will have the EEPROM as well as an accelerometer using i2c. This shouldnt be a problem if I tie the SDA and SCL lines all together as each chip has a different address, correct?
 
Thanks for the response. I can post my code later on tonite when I get home. I was considering using a pic16f1824 which does have MSSP. Is this hardware module difficult to use? I read the datasheet on it and it does seem a little tricky...

In my end product, I will have the EEPROM as well as an accelerometer using i2c. This shouldnt be a problem if I tie the SDA and SCL lines all together as each chip has a different address, correct?

Correct you can connect it to same bus.
 
Jon - Here is my software i2c routines.... I can talk to an accelerometer just fine using these same routines...So I feel it might have something to do with delays...

Code:
;.......................................................................................................................
;.......................................................................................................................
;Define Global Deifnitions:	
I2C_PORT	equ		PORTC
I2C_TRIS	equ		TRISC
#define		SDA	 	2
#define		SCL 	3
 
;.......................................................................................................................
;.......................................................................................................................
START_PROGRAM
;Initialize Inputs/Outputs, and Registers on the PIC16F684.
;Initialize TRISA and TRISB registers. 
 	bsf 	STATUS, RP0			;Bank 1
 	movlw 	b'00001100'		 
 	movwf 	TRISC				;Assigns SDA and SCL Inputs.
 	movlw	b'00000000'		
	movwf	TRISA				;Assigns all TRISA as outputs. 
	movlw	0x03
	movwf	OSCCON				;Loads internal 31.25kHz clock
	bcf		STATUS, RP0			;Bank 0
	clrf	CCP1CON
;......................................................................................................................
;.......................................................................................................................
 
 
 
 
 
Start_Loop
	clrf	TEST1
	clrf	TEST2
	clrf	TEST3
;Write to Bank 0, Word 0 (Control Byte: 10100000)
 
 
	movlw	0x0A
	movwf	Write_Delay
Write_Delay_Loop
	call	Clock_Pulse_Delay
	decfsz	Write_Delay
	goto	Write_Delay_Loop
 
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	0xA0
	call	Send_i2c_Byte
	call	ACK
 
 
	movlw	0x58
	call	Transmit_RS_232
 
	movlw	0x01
	call	Send_i2c_Byte
	call	ACK
	movlw	0x56
	call	Send_i2c_Byte
	call	ACK
	call	Stop_Command
;;TEST TO WRITE TO JUST ONE REGISTER
 
	goto	Read_EEPROM
 
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	0xA4
	call	Send_i2c_Byte
	call	ACK
	movlw	0x55
	call	Send_i2c_Byte
	call	ACK
	movlw	0x57
	call	Send_i2c_Byte
	call	ACK
	call	Stop_Command
 
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	b'10101110'
	call	Send_i2c_Byte
	call	ACK
	movlw	0xff
	call	Send_i2c_Byte
	call	ACK
	movlw	0x58
	call	Send_i2c_Byte
	call	ACK
	call	Stop_Command
 
;Read from Bank 0, Word 0 (Control Byte: 10100001)
Read_EEPROM
	movlw	0x0A
	movwf	Read_Delay
Read_Delay_Loop1
	call	Clock_Pulse_Delay
	decfsz	Read_Delay
	goto	Read_Delay_Loop1
 
	call	Start_Command
	movlw	b'10100000'
	call	Send_i2c_Byte
	call	ACK
	movlw	b'00000001'
	call	Send_i2c_Byte
	call	ACK
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	b'10100001'
	call	Send_i2c_Byte	
	call	ACK
	call	Receive_i2c_Byte
	movf	Received_I2C_Byte, w
	movwf	TEST1
	call	NACK
	call	Stop_Command
 
 
	goto	Send_Output
 
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay	
	call	Start_Command
	movlw	b'10100100'
	call	Send_i2c_Byte
	call	ACK
	movlw	b'01010101'
	call	Send_i2c_Byte
	call	ACK
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	b'10100101'
	call	Send_i2c_Byte
	call	ACK
	call	Receive_i2c_Byte
	movf	Received_I2C_Byte, w
	movwf	TEST2
	call	NACK
	call	Stop_Command
 
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay	
	call	Start_Command		;Start
	movlw	b'10101110'
	call	Send_i2c_Byte		;
	call	ACK
	movlw	b'11111111'
	call	Send_i2c_Byte
	call	ACK
	call	Clock_Pulse_Delay
	call	Start_Command
	movlw	b'10101111'
	call	Send_i2c_Byte
	call	ACK
	call	Receive_i2c_Byte
	movf	Received_I2C_Byte, w
	movwf	TEST1
	call	NACK
	call	Stop_Command
 
Send_Output
	movf	TEST1, w
	call	Transmit_RS_232
;;	movf	TEST2, w
;	call	Transmit_RS_232
;	movf	TEST3, w
;	call	Transmit_RS_232
 
done
	goto	Start_Loop
 
 
 
 
 
 
 
;---------------------------------------------------------------------------------------
;Sub Routines for PIC
;---------------------------------------------------------------------------------------
;i2c Routines
;----------------------------------
Start_Command	
	call	Set_SCL_High				;Release SCL
	call	Set_SDA_High				;Release SDA
	call	Clock_Pulse_Delay			;Delay
	call	Set_SDA_Low					;Set SDA Low
	call	Clock_Pulse_Delay			;Delay
	return
;----------------------------------
SAD_W
	movlw	0x1E
	call	Send_i2c_Byte				;(SAD+W)Slave Address plus write.
	return
;----------------------------------
SAD_R
	movlw	0x1F
	call	Send_i2c_Byte				;(SAD+R)Slave Address plus read.
	return
;----------------------------------
ACK
	call	Set_SCL_High				;Release SCL
	call	Set_SDA_High				;Release SDA
	call	Clock_Pulse_Delay			;Delay
Clock_Stretch
	btfss	I2C_PORT, SCL				
	goto	Clock_Stretch				;Wait for slave to release clock line (if "stretching")
	call	Clock_Pulse_Delay			;Delay
	bcf		STATUS, C					;Initally clears the carry bit
	btfsc	I2C_PORT, SDA				;Checks if slave is pulling SDA low (giving its ACK)
;	goto	_Error						;Clear carry for NACK
	bsf		STATUS, C					;Set carry for ACK
	btfss	STATUS, C					;Check carry bit to ensure ACK
	goto	START_PROGRAM					;Start over if NACK
	call	Set_SCL_Low
	return								;If ACK received, continue 
;----------------------------------
 
SEND_ACK
	call	Clock_Pulse_Delay
	call	Set_SCL_Low
Get_ACK_SDA
	btfss	I2C_PORT, SDA				;Wait to see if the SDA line is released.
	goto	Get_ACK_SDA					;Loop
	call	Set_SDA_Low
;	call	Set_SDA_High				;Ensure SDA is released.
	call	Set_SCL_High				;Trigger SCL
	call	Clock_Pulse_Delay			;Delay
	call	Set_SCL_Low
;	call	Set_SCL_High				;Trigger Clock
	call	Set_SDA_High				;Release SDA
	call	Clock_Pulse_Delay			;Delay
;	call	Clock_Pulse_Delay			;Delay
;	call	Set_SDA_High				;Release SDA
;	call	Set_SCL_Low
	return								
 
NACK
	call	Set_SDA_High				;Release SCL
	call	Clock_Pulse_Delay			;Delay
	call	Set_SCL_High				;Set SCL Low
;	call	Set_SDA_High				;Release SDA
	call	Clock_Pulse_Delay			;Delay
	call	Set_SCL_Low
	return
;----------------------------------
Stop_Command
	call	Set_SCL_High				;Release SCL
	call	Clock_Pulse_Delay			;Delay
	call	Set_SDA_High				;Release SDA
	call	Clock_Pulse_Delay			;Delay
	call	Clock_Pulse_Delay			;Delay
	return
;----------------------------------
Send_i2c_Byte
	movwf	i2c_transmit_byte			;Moves whatever value is in the working register into i2c_transmit_byte
	movlw	0x08	
	movwf	i2c_bit_counter				;Sets 8 bits to be sent out
Send_i2c_Bit
	call	Set_SCL_Low					;Ensure SCL is low initially
	call	Clock_Pulse_Delay			;Delay
	rlf		i2c_transmit_byte, f		;MSB is now in carry (MSB is sent first)
	btfsc	STATUS, C					
	call	Set_SDA_High
	btfss	STATUS, C
	call	Set_SDA_Low					;Sets either 0 or 1 to be sent out. (Checks carry bit)
	call	Clock_Pulse_Delay			;Delay
	call	Set_SCL_High				;Trigger Clock; set SCL high
 	call	Clock_Pulse_Delay			;Delay
	decfsz	i2c_bit_counter, f			;Checks if 8 bits have been sent out
	goto	Send_i2c_Bit				;No
	call	Set_SCL_Low					;Yes; Set SCL Low
	call	Clock_Pulse_Delay			;Delay
	return
;-------------------------------------	
Receive_i2c_Byte
	clrf	Received_I2C_Byte			;Clears previous received byte
	bsf		Received_I2C_Byte, 0
;	call	Set_SDA_High
	call	Clock_Pulse_Delay
Get_i2c_Bit
	call	Set_SCL_Low
	call	Set_SDA_High				;Set SCL Low
	call	Clock_Pulse_Delay			;Delay
	bcf		STATUS, C					;Defaults to incoming bit = 0 (sets carry = 0)
	call	Set_SCL_High				;Release SCL
	call	Clock_Pulse_Delay
	btfsc	I2C_PORT, SDA				;Read port, skip if clear
	bsf		STATUS, C					;If incoming bit = 1, set carry flag to 1
	rlf		Received_I2C_Byte, f		;move carry into data (MSB first)
	call	Clock_Pulse_Delay
	btfss	STATUS, C
	goto	Get_i2c_Bit					;No
 
;Test to ensure hypertermianl works correctly. 
;	movlw	0x55
;	movwf	Received_I2C_Byte
 
;	call	Set_SCL_Low
 
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay
	call	Clock_Pulse_Delay
	return								;Yes, return
 
 
 
 
;Routines to Set SDA and SCL High/Low
 
Set_SCL_High
	bsf		STATUS, RP0				;Bank 1
	bsf		I2C_TRIS, SCL			;Sets SCL as an input
	clrf	ANSEL
	bcf		STATUS, RP0				;Bank 0	
	movlw	0x07
	movwf	CMCON0
	return
 
Set_SCL_Low
	bcf		I2C_PORT, SCL			;Sets SCL port pin low
	bsf		STATUS, RP0				;Bank 1
	bcf		I2C_TRIS, SCL			;Sets SCL as an output
	clrf	ANSEL
	bcf		STATUS, RP0				;Bank 0
	movlw	0x07
	movwf	CMCON0
	return	
 
Set_SDA_High
	bsf		STATUS, RP0				;Bank 1
	bsf		I2C_TRIS, SDA			;Sets SDA as an input (high impedance)
	clrf	ANSEL
	bcf		STATUS, RP0				;Bank 0
	movlw	0x07
	movwf	CMCON0
	return
 
Set_SDA_Low
	bcf		I2C_PORT, SDA			;Sets SDA port pin low
	bsf		STATUS, RP0				;Bank 1
	bcf		I2C_TRIS, SDA			;Sets SDA as an output
	clrf	ANSEL
	bcf		STATUS, RP0				;Bank 0
	movlw	0x07
	movwf	CMCON0
	return	
 
;---------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
;Delays
Clock_Pulse_Delay
	movlw	0x03
	movwf	pw_counter
Clock_Pulse_Delay_Wait
	nop
	movlw	0x01
	movwf	pw_counter1
Clock_Pulse_Delay_Wait1
	decfsz	pw_counter1, f
	goto	Clock_Pulse_Delay_Wait1
	decfsz	pw_counter, f
	goto	Clock_Pulse_Delay_Wait
	return
 
Read/write eeprom from pic mcu using i2c (mssp module)

HI Steve311,

You can use the Microchip Tutorial on i2c. I have attached the pdf document. It is in asm and uses Polling method (so, no worry about timing problem of eeprom). I can't able to remember the url that I downloaded. It may looks big file. You can directly refer the coding (Write & Read to/from EEPROM) that provided on the page number: 57. Hope this help.
 

Attachments

  • i2c.pdf
    658.2 KB · Views: 195
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top