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.

External Eeprom

Status
Not open for further replies.
My datasheet says just to wait after the data is sent. at the end of every byte sent it will send back a ACK then when finished sending just send the stop bit
 
ok i think i confused myself can someone look at this im now using RB2 and RB3:
Code:
	list	p=18F1320
	include	<p18F1320.inc>
	CONFIG	OSC=INTIO2,WDT=OFF,MCLRE=ON,LVP=OFF

	cblock	0x00
	datatmp
	d1
	d2
	d3
	endc

SDA2	Equ 3
SCL2	Equ 2

	org	0x0000
init 
	bsf 	OSCCON,IRCF2	;set to 8MHz clock
	bsf 	OSCCON,IRCF1
	bsf 	OSCCON,IRCF0
	call 	I2C_TestWrite
main

	goto	main

I2C_TestWrite
	call 	I2C_Start
	call	Delay5us

	movlw	0xA0
	call 	I2C_SendByte
	call	Delay5us

	movlw	0x00
	call 	I2C_SendByte
	call	Delay5us

	movlw	0x0F
	call 	I2C_SendByte
	call	Delay5us

	call	I2C_Stop
	call	Delay5us

	return

I2C_Start
	clrf	TRISB 
	clrf	PORTB

	BSF 	PORTB, SDA2
	BSF 	PORTB, SCL2
	call	Delay5us

	BCF 	PORTB, SDA2
	call	Delay5us

	BCF 	PORTB, SCL2
	call	Delay5us

	BSF 	TRISB, SDA2
	return

I2C_Stop
	BSF 	TRISB, SDA2

	BCF 	PORTB, SDA2
	call	Delay5us

	BSF 	PORTB, SCL2
	call	Delay5us

	BSF 	PORTB, SDA2
	call	Delay5us

	BCF		TRISB, SDA2
	return

I2C_SendByte
	movwf	datatmp
	movlw	0x08
Loop_X
	btfss 	datatmp, 0
	call	I2C_Send0
	btfsc	datatmp, 0
	call	I2C_Send1
	
	RLNCF	datatmp
	DECFSZ	W
	goto 	Loop_X
	return

I2C_Send1
	bcf 	TRISB, SDA2

	bsf 	PORTB, SDA2	
	call 	Delay5us

	bsf 	PORTB, SCL2
	call	Delay5us

	bcf 	PORTB, SCL2
	call	Delay5us

	bsf 	TRISB, SDA2
	return

I2C_Send0
	bcf 	TRISB, SDA2

	bcf 	PORTB, SDA2	
	call 	Delay5us

	bsf 	PORTB, SCL2
	call	Delay5us

	bcf 	PORTB, SCL2
	call	Delay5us

	bsf 	TRISB, SDA2
	return
 
Delay5us
	bra 	$+2
	bra 	$+2
	return
	end
 
im trying to use the sourceC sample code and when i try to compile it i get tons of errors

C:\PicCode\eeprom\main.c(104:12): error: failed to parse template arguments
C:\PicCode\eeprom\main.c(111:2): error: failed to generate expression

and others but those are most common. The code is attached.
 

Attachments

  • main.c
    6.4 KB · Views: 188
im trying to use the sourceC sample code and when i try to compile it i get tons of errors

C:\PicCode\eeprom\main.c(104:12): error: failed to parse template arguments
C:\PicCode\eeprom\main.c(111:2): error: failed to generate expression

and others but those are most common. The code is attached.

OK, I have some time to spend on it.
I first tried building the project in the SB IDE, and all was fine, however when I tried to build it under MPLab, I saw all the errors. Must be a lib which needs to be included. Just a minute...
 
Sorry,
I didn't really look at that before I recommended it!
This will be the problem:
// Copyright(C) 2004-2006 Andrew Smallridge
// Copyright(C) 2004-2008 Pavel Baranov
// Copyright(C) 2004-2008 David Hobday
// Existing constants predefined for i2c hardware driver and i2s software
// emulation for the PIC 18F2xx and 18F4xx processors. For hardware support
// on other PICs the constants must be mapped to the corresponding register
// map of the target device
...
// variables cannot be passed as template arguments. The following constants map to
// the PIC registers and software emalated i2c RAM locations. These constants are
// then used by the templated functions. When changing the address of an emulated
// register the corresponding constant mapping must also be changed.

There is no port C on the 18f1320... everything must be remapped to use for this chip.

NOT an example you want for the first time!
 
This is a tough piece of code!

As far as I can tell the i2c args must be changed from PORTC to PORTB, and this could be all that needs to be done.

No, tried that and got 'wrong target type.' I'm out of time and have to take my friend's kid to church. (uhg!) but I'll get back to it this evening.

Anyone else care to comment?

#if defined use_i2c_SW
////////////////////////////////////////////////////////////////////////////
// i2c software implementation template arguments and variables
////////////////////////////////////////////////////////////////////////////
#define i2c_ARGS 3, PORTC, TRISC, 4, PORTC, TRISC, e_SSPCON1, e_SSPCON2, \
e_SSPSTAT, e_SSPBUF, e_SSPIF_BIT, e_SSPIF_PIR, \
e_BCLIF_BIT, e_BCLIF_PIR, 7, e_SSPADD, (i2c_reset_wdt | i2c_SMP)

// RAM used by the software i2c driver to emulate the equivalent i2c hardware registers
unsigned short swi2c_SSPCON1@0x40; // define location for the emulated SSPCON1
unsigned short swi2c_SSPCON2@0x41; // define location for the emulated SSPCON2
unsigned short swi2c_SSPSTAT@0x42; // define location for the emulated SSPSTAT
unsigned short swi2c_SSPBUF@0x43; // define location for the emulated SSPBUF
unsigned short swi2c_SSPIF_PIR@0x44;// define location for the emulated SSPIF_PIR
unsigned short swi2c_BCLIF_PIR@0x45;// define location for the emulated BCLIF_PIR
unsigned short swi2c_SSPADD@0x46; // define location for the emulated SSPADD

// variables cannot be passed as template arguments. The following constants map to
// the PIC registers and software emalated i2c RAM locations. These constants are
// then used by the templated functions. When changing the address of an emulated
// register the corresponding constant mapping must also be changed.
#define e_SSPCON1 0x40
#define e_SSPCON2 0x41
#define e_SSPSTAT 0x42
#define e_SSPADD 0x43
#define e_SSPBUF 0x44
#define e_SSPIF_PIR 0x45
#define e_BCLIF_PIR 0x46
#define e_SSPIF_BIT 3
#define e_BCLIF_BIT 3
 
Last edited:
OK, I got it to build by changing
Code:
#define i2c_ARGS 3, PORTC, TRISC, 4, PORTC, TRISC, e_SSPCON1, e_SSPCON2, \
e_SSPSTAT, e_SSPBUF, e_SSPIF_BIT, e_SSPIF_PIR, \
e_BCLIF_BIT, e_BCLIF_PIR, 7, e_SSPADD, (i2c_reset_wdt | i2c_SMP)
to
Code:
#define i2c_ARGS	3, PORTB, TRISB, 4, PORTB, TRISB, e_SSPCON1, e_SSPCON2, \
					e_SSPSTAT, e_SSPBUF, e_SSPIF_BIT, e_SSPIF_PIR,			\
					e_BCLIF_BIT, e_BCLIF_PIR, 7, e_SSPADD, (i2c_reset_wdt | i2c_SMP)

That doesn't mean it will work, and I'm not sure I have an 18f1320 here, but if I have one I'll check it out.
 
Hi again,

I think find one error in your ASM code. You must make one more clock impulse :

Code:
I2C_TestWrite
	call 	I2C_Start
	call	Delay5us

	movlw	0xA0
	call 	I2C_SendByte
        > ----- ACK - ninth clock mpulse
	call	Delay5us
	

	movlw	0x00
	call 	I2C_SendByte
	call	Delay5us
	> ----- ACK - ninth clock mpulse

	movlw	0x0F
	call 	I2C_SendByte
	call	Delay5us
	> ----- ACK - ninth clock mpulse

	call	I2C_Stop
	call	Delay5us

	return


===========
ASK check
	{
	SDA > INPUT 
	SCL=1
	ASK check (one SCL clock mpulse where you must check SDA line for ASK)
	SCL=0
	SDA > OUTPUT
	}



and there is one (no my) more extensive C code :

Code:
void i2c_init( void ) 
{ 
/* Initialize processor I/O pins (SDA and SCL) involved in I2C operation */ 

I2C_Status = 0; 

/* Declare both signals output, making sure 
they apply a HIGH level */ 
SET_SDA(); 
SET_SCL(); 
SET_SDA_TO_OUTPUT(); 
SET_SCL_TO_OUTPUT(); 

/* Check the signal levels */ 
if( !SCL_SET() ) I2C_Status |= I2C_SCL_STUCK_LOW; 
if( !SDA_SET() ) I2C_Status |= I2C_SDA_STUCK_LOW; 
} 

/* ------------------------------------------------------------------------ */ 

#define MUS_DELAY 5 

void i2c_delay( void ) 
{ 
/* To match the maximum bitrate we need to add some delay in places, 
done here with a simple busy-wait loop; minimum delay is 3 mus; 
measured for an ATmega103 running at 4 MHz */ 
BYTE i; 
for( i=0; i<(MUS_DELAY-3); ++i ); 
} 

/* ------------------------------------------------------------------------ */ 

void i2c_start( void ) 
{ 
/* Generate I2C START condition */ 
SET_SDA(); 
SET_SCL(); 
i2c_delay(); 
CLEAR_SDA(); 
i2c_delay(); 
CLEAR_SCL(); 
i2c_delay(); 
} 

/* ------------------------------------------------------------------------ */ 

void i2c_stop( void ) 
{ 
/* Generate I2C STOP condition */ 
CLEAR_SDA(); 
SET_SCL(); 
i2c_delay(); 
SET_SDA(); 
i2c_delay(); 
} 

/* ------------------------------------------------------------------------ */ 

void i2c_write( BYTE byt ) 
{ 
/* Write a byte to the I2C bus; errors are stored in I2C_Status 
and can be inspected by calling i2c_status() */ 

BYTE i; 

/* Set SDA back to output */ 
SET_SDA_TO_OUTPUT(); 

/* Send BYTE, MSB first */ 
for( i=0; i<8; ++i ) 
{ 
if( byt & 0x80 ) 
SET_SDA(); 
else 
CLEAR_SDA(); 

/* Get ready for next bit */ 
byt <<= 1; 

SET_SCL(); 
i2c_delay(); 
CLEAR_SCL(); 
i2c_delay(); 
} 
/* To receive the acknowledge, set SDA to input (without pull-up) */ 
SET_SDA_TO_INPUT(); 
CLEAR_SDA(); 

/* Get the acknowledge */ 
SET_SCL(); 
i2c_delay(); 

CLEAR_SCL(); 
i2c_delay(); 

/* Set SDA back to output */ 
SET_SDA_TO_OUTPUT(); 
} 

/* ------------------------------------------------------------------------ */ 

BYTE i2c_read( BOOLEAN last ) 
{ 
/* Read a byte from the I2C bus; byte value is returned; 
errors are stored in I2C_Status and 
can be inspected by calling i2c_status(); */ 

BYTE i, byt; 

/* Set SDA to input, without pull-up */ 
SET_SDA_TO_INPUT(); 
CLEAR_SDA(); 

/* Initialize byte value */ 
byt = 0; 

/* Receive BYTE, MSB first */ 
for( i=0; i<8; ++i ) 
{ 
SET_SCL(); 
i2c_delay(); 
byt <<= 1; 
if( SDA_SET() ) ++byt; 

CLEAR_SCL(); 
i2c_delay(); 
} 

/* Get ready for acknowledge: is it the last byte to read ? */ 
if( last ) 
SET_SDA(); 
else 
CLEAR_SDA(); 

/* Set SDA to output */ 
SET_SDA_TO_OUTPUT(); 

SET_SCL(); 
i2c_delay(); 
CLEAR_SCL(); 
i2c_delay(); 

return byt; 
} 

/* ------------------------------------------------------------------------ */ 

BYTE i2c_status( void ) 
{ 
/* Return the status byte and reset it to zero */ 
BYTE stat; 
stat = I2C_Status; 
I2C_Status = 0; 
return stat; 
} 

void write_eeprom(unsigned int adr) 
{ 
i2c_start(); 
i2c_write(0xA0); 
temp=adr/0xff; 
i2c_write(temp); 
temp=adr; 
i2c_write(temp); 
i2c_write(0x36); 
i2c_write(0x37); 
i2c_write(0x38); 
i2c_stop(); 
delay_ms(10); 

} 
void read_eeprom(unsigned int adr) 
{ 
i2c_start(); 
i2c_write(0xA0); 
temp=adr/0xff; 
i2c_write(temp); 
temp=adr; 
i2c_write(temp); 
i2c_start(); 
i2c_write(0xA1); 
temp= i2c_read(1); 
i2c_stop(); 
delay_ms(1); 
}
 
ex_i2c.c confirmed working

Hey Jason, (that is right, isn't it?)
I can confirm that the example ex_i2c.c works on the 18F1320 with a 24LC04B i2c serial EEPROM. :)

Just change PortC to PortB as above.

Sorry it took so long. My development board has one 18 pin socket, which is mapped to a 16F628, but the pin out is different than the 18F1320, so for a while, I was trying to figure out why I couldn't even get an LED to blink! LOL

Have you got the assembler to work? There is example code on Microchips site, listed with the data sheet for the serial EEPROM I'm using.

Regards
 
I tried to do this on a 16F627A just for fun but i think its slow. I guess it works but takes like 5 seconds lol will try on the 1320 now

Code:
	LIST	p=16F627A		;tell assembler what chip we are using
	include "P16F627A.inc"		;include the defaults for the chip
	__config 0x3D18			;sets the configuration settings (oscillator type etc.)

;***** VARIABLE DEFINITIONS
w_temp        EQU     0x7E        ; variable used for context saving 
status_temp   EQU     0x7F        ; variable used for context saving
mybyte		  EQU	  0x80
eec			  EQU	  2
eed			  EQU	  3

;**********************************************************************
	ORG     0x000             ; processor reset vector
	goto    main              ; go to beginning of program
	

	ORG     0x004             ; interrupt vector location
	movwf   w_temp            ; save off current W register contents
	movf	STATUS,w          ; move status register into W register
	movwf	status_temp       ; save off contents of STATUS register

; isr code can go here or be located as a call subroutine elsewhere


	movf    status_temp,w     ; retrieve copy of STATUS register
	movwf	STATUS            ; restore pre-isr STATUS register contents
	swapf   w_temp,f
	swapf   w_temp,w          ; restore pre-isr W register contents
	retfie                    ; return from interrupt


main
	movlw	0x07
	movwf	CMCON

   	bsf 	STATUS,	RP0
	clrf	TRISB
	clrf	TRISA
	bcf		STATUS, RP0

	clrf	PORTB
	clrf	PORTA
	
	;bsf		PORTB, 4
	
	;call	writeit
	call	readit

	;movf	mybyte,0
	;movwf	PORTA
	btfsc	mybyte,3
	bsf		PORTA,3
main2
	goto	main2		  ;loop forever, remove this instruction, for test only

readit
	bsf		PORTB,eed  ;1 Start
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit
	
	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit

;Device Address
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit
; End of device address

	bcf		PORTB,eed  ;0 I want to write to it
	call	clockit

	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0
	call	clockit

ack_04
	btfsc	PORTB, eed  
	goto	ack_04

	bsf		STATUS, RP0
	bcf		TRISB,eed
	bcf		STATUS, RP0
	


;//////////////////////////// WORD ADDRESS
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
;//////////////////////////// 

	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0
	call	clockit

ack_05
	btfsc	PORTB, eed  
	goto	ack_05
	
	bsf		STATUS, RP0
	bcf		TRISB,eed
	bcf		STATUS, RP0

;/////////////////////////// Random Read

	bsf		PORTB,eed  ;1 Start
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit
	
	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit

;Device Address
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit
; End of device address

	bsf		PORTB,eed  ;1 I want to read from it
	call	clockit

	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0

ack_06
	btfsc	PORTB, eed  
	goto	ack_06
	call	clockit


	movlw	0x08
	movwf	w_temp
getbits
	decfsz	w_temp, f
	goto	gotit
	goto	sendstop

gotit
	btfsc	PORTB, eed
	bsf		mybyte,w_temp
	bcf		mybyte,w_temp
	call	clockit
	goto	getbits

sendstop

	bcf		PORTB,eed  ;0 Just in case last bit was high
	call	Delay5us

	bsf		PORTB,eec	
	call	Delay5us

	bcf		PORTB,eed  ;0
	call	Delay5us

	bsf		PORTB,eed  ;1
	call	Delay5us

	bcf		PORTB,eec
	call	Delay5us

	bsf		PORTB, 4 ; Done!
	return
	return
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////
writeit
	bsf		PORTB,eed  ;1 Start
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit
	
	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit

;Device Address
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit
; End of device address

	bcf		PORTB,eed  ;0 I want to write to it
	call	clockit

	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0
	call	clockit

ack_01
	btfsc	PORTB, eed  
	goto	ack_01

	bsf		STATUS, RP0
	bcf		TRISB,eed
	bcf		STATUS, RP0
	


;//////////////////////////// WORD ADDRESS
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
;//////////////////////////// 

	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0
	call	clockit

ack_02
	btfsc	PORTB, eed  
	goto	ack_02
	
	bsf		STATUS, RP0
	bcf		TRISB,eed
	bcf		STATUS, RP0

;/////////////////////////// Data (0x08)
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bsf		PORTB,eed  ;1
	call	clockit
	
	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit

	bcf		PORTB,eed  ;0
	call	clockit
;/////////////////////////////
	bsf		STATUS, RP0
	bsf		TRISB,eed
	bcf		STATUS, RP0
	call	clockit

ack_03
	btfsc	PORTB, eed  
	goto	ack_03
	
	bsf		STATUS, RP0
	bcf		TRISB,eed
	bcf		STATUS, RP0
;///////////////////////////// STOP

	bcf		PORTB,eed  ;0 Just in case last bit was high
	call	Delay5us
	
	bsf		PORTB,eec	
	call	Delay5us

	bcf		PORTB,eed  ;0
	call	Delay5us

	bsf		PORTB,eed  ;1
	call	Delay5us

	bcf		PORTB,eec
	call	Delay5us

	bsf		PORTB, 4 ; Done!
	return

clockit
	call	Delay5us
	bsf		PORTB,eec
	call	Delay5us
	bcf		PORTB,eec
	call	Delay5us
	return

Delay5us
	nop
	return


; initialize eeprom locations

	ORG	0x2100
	DE	0x00, 0x01, 0x02, 0x03


	END                       ; directive 'end of program'
 
ok i got some boost c code and it compiles ok but i get this wierd warning and nothing works like breakpoints. BTW this is on the Junebug with 18F1320.

Code:
Optimisation level:1
Caution: argument of 'delay_us' calls must have a value of 1 or more
Caution: Delay inaccurrate: 'delay_us', Delay overhead:0.0045ms, Unit delay:0.001ms, Delay resolution:2 units
Building CASM file

EDIT: This is my new main
Code:
void main(void)
{
    osccon=0x72;           //8 MHz

    clockt=0;
    datat=0;

    write_ee();
    delay_s(2);
    read_ee();
	while(1);
	
}

It skips all and goes to while(1); for some reason
 

Attachments

  • eeprom.zip
    987 bytes · Views: 134
Last edited:
Changed the stop function:
Code:
void stop_ee(void){
//////////////////////////
/// Send stop command ///
//////////////////////////
    data=0;
    clock=1;
    data=1;
    delay_us(5);
    //clock=0; [b]This was taken out[/b]
}
 
The first warning is nothing to worry about unless you need very accurate delays. For this, it should be OK.
The second problem is weird, though. I'll take a look and see if I can figure out why. May take a bit of time though, as I've got another PIC in my board right now.
 
and nothing works like breakpoints. BTW this is on the Junebug with 18F1320.


It skips all and goes to while(1); for some reason

Are you using the Pickit2 as a debugger, or simulating in MPLab?

I ran it in the MPLab simulator, and it breaks where I tell it to. It seems to be doing all you have asked, then sitting in the endless loop at the end of your code.
 
Nope i still cant use a breakpoint. What version of MPLab are you using?

EDIT:
I just noticed you said simulator... It works ok in simulator but when in debugging it wont work.
 
Last edited:
Nope i still cant use a breakpoint. What version of MPLab are you using?

EDIT:
I just noticed you said simulator... It works ok in simulator but when in debugging it wont work.

OK, that's what I wanted to know.

So the only way you have of verifying the EEPROM write is from reading it in the debugger, right?

I'll set up a chip in the morning and play with this... I don't have a PICkit2, YET. but can do it another way. :)

Edit:If we verify the code works, and it still doesn't give you a breakpoint, then it'll be something about the way you are using your debugger...
Wait, if you debug in source boost, you must set up your source... I'll be back.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top