| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| PICoHolic 
 
 
 Joined: 04 Jan 2005
 Posts: 224
 
 
 
			    
 
 | 
			
				| [Resolved] Strange sw I2C behavior |  
				|  Posted: Sun Nov 22, 2009 5:03 am |   |  
				| 
 |  
				| Hello, 
 I was trying to implement an EEPROM copier. (24C16B, page by page)
 The micro used is 12F675 with separate software I2C buses. Compiler 4.099
 Here's the code:
 
  	  | Code: |  	  | #include <12F675.h>
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
 #FUSES NOCPD                    //No EE protection
 #FUSES NOPROTECT                //Code not protected from reading
 #FUSES MCLR                     //Master Clear pin enabled
 #FUSES NOPUT                    //No Power Up Timer
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES BANDGAP_HIGH
 
 #use delay(clock=4000000)
 #use I2C(master, SLOW=100000, sda=PIN_A2, scl=PIN_A1, STREAM = SRC)
 #use I2C(master, SLOW=100000, sda=PIN_A5, scl=PIN_A4, STREAM = DST)
 
 #byte PORTA =  0x05
 #byte IOC   =  0x96
 
 ///////////////////////////////////////////////////////////////////////////////
 #bit  LED = PORTA.0
 #bit  PBT = PORTA.0
 ///////////////////////////////////////////////////////////////////////////////
 int1 temp_flag;
 int8 EEAddress,i,j,p, dummy8;
 ///////////////////////////////////////////////////////////////////////////////
 int1 SourceEEFound(int8 Address)
 {
 i2c_start(SRC);
 temp_flag = i2c_write(SRC, Address);
 i2c_stop(SRC);
 
 return (!temp_flag);
 }
 ///////////////////////////////////////////////////////////////////////////////
 int1 DestinationEEFound(int8 Address)
 {
 i2c_start(DST);
 temp_flag = i2c_write(DST, Address);
 i2c_stop(DST);
 
 return (!temp_flag);
 }
 ///////////////////////////////////////////////////////////////////////////////
 #int_RA
 void  RA_isr(void)
 {
 delay_ms(20);
 while(!PBT);
 delay_ms(20);
 
 set_tris_a(0xFE);
 
 if (SourceEEFound(0xA0))   //Source EEPROM found?
 {
 if (DestinationEEFound(0xA0))   //Destination EEPROM found?
 {
 for (i=0; i<8; i++)          //8 blocks of EE
 {
 PORTA ^= 0x01;                // toggle LED
 EEAddress = 0xA0 | (i<<1);    //Set source & destination EE address
 i2c_start(SRC);
 i2c_write(SRC, EEAddress);
 i2c_write(SRC, 0x00);   //point to address 0
 i2c_start(SRC);         //restart
 i2c_write(SRC, EEAddress+1);   //prepare reading
 for (j=0; j<16; j++)    //write one page at a time
 {
 i2c_start(DST);
 i2c_write(DST, EEAddress);
 i2c_write(DST, (j<<4));//point to start of page
 for (p=0; p<16; p++) //write 16 bytes (1 page)
 {
 dummy8 = i2c_read(SRC);
 i2c_write(DST, dummy8);
 }
 i2c_stop(DST);       //stop on destination
 delay_ms(10);         //page write cycle
 }
 i2c_stop(SRC);          //stop on source
 }
 }
 }
 else                       //Source not found
 {
 if (DestinationEEFound(0xA0))   //Destination EEPROM found?
 {
 //Adjust destination EEPROM
 }
 }
 
 set_tris_a(0xFF); //set port to input
 swap(PORTA);      //remove mismatch
 }
 ///////////////////////////////////////////////////////////////////////////////
 void main()
 {
 setup_adc_ports(NO_ANALOGS|VSS_VDD);
 //setup_adc(ADC_CLOCK_DIV_2);
 //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
 //setup_timer_1(T1_DISABLED);
 setup_comparator(NC_NC);
 setup_vref(FALSE);
 
 set_tris_a(0xFF);
 port_a_pullups(TRUE);
 IOC = 0x01;
 enable_interrupts(INT_RA);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 sleep();
 delay_cycles(1);
 }
 
 }
 
 | 
 
 The problem is inside the p loop:
 the statement: dummy8 = i2c_read(SRC); has no effect (the I2C bus remains low) unless I remove the following lines from the j loop:
 
  	  | Code: |  	  | i2c_start(DST);
 i2c_write(DST, EEAddress);
 i2c_write(DST, (j<<4));//point to start of page
 
 | 
 It seems that the compiler is mixing between the functions of the two sw i2c buses. It's reading from destination and writing to destination
   
 Any idea?
 Thanks
 
 Last edited by PICoHolic on Sun Nov 22, 2009 10:42 am; edited 1 time in total
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 22, 2009 10:08 am |   |  
				| 
 |  
				|  	  | Quote: |  	  | the statement: dummy8 = i2c_read(SRC); has no effect
 
 | 
 The CCS manual doesn't give that as a valid syntax.  It says that if
 a stream is specified for this function, then the ACK (or NACK) must
 also be specified.  If you  want to tell it to use a stream, you must
 use two parameters.   A single parameter is interpreted as ACK/NACK.
 Here's the section from the manual:
 
  	  | Quote: |  	  | I2C_read( )
 
 Syntax: data = i2c_read();
 data = i2c_read(ack);
 data = i2c_read(stream, ack);
 
 Parameters: ack -Optional, defaults to 1.
 0 indicates do not ack.
 1 indicates to ack.
 stream - specify the stream defined in #USE I2C
 
 | 
 |  |  
		|  |  
		| PICoHolic 
 
 
 Joined: 04 Jan 2005
 Posts: 224
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 22, 2009 10:41 am |   |  
				| 
 |  
				| Thanks PCM programmer. It seems working now.
 
 I had another solution: reading then writing (page by page), the 'i' loop becomes:
 
  	  | Code: |  	  | for (i=0; i<8; i++)          //8 blocks of EE
 {
 PORTA ^= 0x01;                // toggle LED
 EEAddress = 0xA0 | (i<<1);    //Set source & destination EE address
 for (j=0; j<16; j++)    //write one page at a time
 {
 dummy8 = j;    //prepare start of page
 
 //read page
 i2c_start(SRC);
 i2c_write(SRC, EEAddress);
 i2c_write(SRC, swap(dummy8));   //point to address (+=16)
 i2c_start(SRC);         //restart
 i2c_write(SRC, EEAddress+1);   //prepare reading
 for (p=0; p<16; p++) //write 16 bytes (1 page)
 {
 DataBuff[p] = i2c_read(SRC);
 }
 i2c_stop(SRC);          //stop on source
 
 //Write page
 i2c_start(DST);
 i2c_write(DST, EEAddress);
 i2c_write(DST, dummy8);//point to start of page
 for (p=0; p<16; p++) //write 16 bytes (1 page)
 {
 i2c_write(DST, DataBuff[p]);
 }
 i2c_stop(DST);       //stop on destination
 delay_ms(6);         //page write cycle 6+4=10ms
 }
 }
 
 | 
 It works even if [DataBuff[p] = i2c_read(SRC);]
 Without adding the ACK!
 
 Thanks anyway
  |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 22, 2009 10:46 am |   |  
				| 
 |  
				| That may be, but it's pure luck due to quirks in the way the compiler handles functions which don't have a stream specified, when the library
 is specified with a stream.
 
 It's a violation of the syntax, and regarding it as a "solution" will burn
 you either in this code or in future programs.
 |  |  
		|  |  
		| PICoHolic 
 
 
 Joined: 04 Jan 2005
 Posts: 224
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Nov 22, 2009 11:08 am |   |  
				| 
 |  
				| You're 100% right  |  |  
		|  |  
		|  |  
  
	| 
 
 | You cannot post new topics in this forum You cannot reply to topics in this forum
 You cannot edit your posts in this forum
 You cannot delete your posts in this forum
 You cannot vote in polls in this forum
 
 |  
 Powered by phpBB © 2001, 2005 phpBB Group
 
 |