|
|
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
|