CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

[Resolved] Strange sw I2C behavior

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PICoHolic



Joined: 04 Jan 2005
Posts: 224

View user's profile Send private message

[Resolved] Strange sw I2C behavior
PostPosted: Sun Nov 22, 2009 5:03 am     Reply with quote

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 Shocked

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

View user's profile Send private message

PostPosted: Sun Nov 22, 2009 10:08 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 22, 2009 10:41 am     Reply with quote

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 Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Nov 22, 2009 10:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 22, 2009 11:08 am     Reply with quote

You're 100% right Smile
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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