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 CCS Technical Support

I2C SW working... I2C HW don´t?

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



Joined: 07 May 2004
Posts: 11

View user's profile Send private message

I2C SW working... I2C HW don´t?
PostPosted: Fri May 07, 2004 6:26 am     Reply with quote

Hi guys! I'm new to CCS C and I'm having some trouble getting the I2C HW working...

If I use #use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3) it works OK:

Program running
I2C init ok
Write: 00 02 04 06 08 0A 0C 0E
Read: 00 02 04 06 08 0A 0C 0E


but when I force HW I2C instead with #use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,force_hw) it gets stuck:

Program running
I2C init ok


Confused


Here's my sample code, I use routines from 2465.C with some changes to fit my needs:

Code:
#include <16F876.h>

#use delay(clock=4000000)
#fuses NOWDT,XT,NOPUT,NOPROTECT,BROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#define EEPROM_SCL   PIN_C3
#define EEPROM_SDA   PIN_C4
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)
//#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,FORCE_HW)

#define hi(x)  (*(&x+1))

void i2c_init (void)
{
   output_float(EEPROM_SCL);
   output_float(EEPROM_SDA);
}

int1 i2c_device_ready (int8 i2c_slave_address)
{
   int1 ack;
   i2c_start();         // Si se admite petición de escritura entonces
   ack = i2c_write(i2c_slave_address);  // el dispositivo está listo
   i2c_stop();
   return !ack;
}

void i2c_buffer_write_16 (int8 *i2c_buffer, int8 i2c_slave_address, int16 address0, int8 i2c_data_number)
{
   int8 i;
   while(!i2c_device_ready(i2c_slave_address));
   i2c_start();
   i2c_write(i2c_slave_address);    // controlbyte (write)
   i2c_write(hi(address0));
   i2c_write(address0);
   for(i=0;i<i2c_data_number;i++) i2c_write(i2c_buffer[i]);
   i2c_stop();
}

void i2c_buffer_read_16 (int8 *i2c_buffer, int8 i2c_slave_address, int16 address0, int8 i2c_data_number)
{
   int8 i;
   while(!i2c_device_ready(i2c_slave_address));
   i2c_start();
   i2c_write(i2c_slave_address);    // controlbyte (write)
   i2c_write(hi(address0));
   i2c_write(address0);
   i2c_start();
   i2c_write(i2c_slave_address+1);  //controlbyte (read)
   for(i=0;i<i2c_data_number-1;i++) i2c_buffer[i]=i2c_read();  //n-1 data->read+ack
   i2c_buffer[i2c_data_number-1]=i2c_read(0);   //last data->read+noack
   i2c_stop();
}


#define I2CREGS 8

void main()
{
   int8 i;
   int8 i2c_buffer[I2CREGS];

   for (i=0;i<I2CREGS;i++) i2c_buffer[i]=2*i; //0,2,4,6,8,10,12,14

   setup_adc_ports(RA0_ANALOG);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_spi(FALSE);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);

   printf("Program running\n\r");

   i2c_init();

   printf("I2C init ok\n\r");

   i2c_buffer_write_16(i2c_buffer,0xA0,0x00,I2CREGS);

   printf("Write: ");
   for(i=0;i<I2CREGS;i++) printf("%X ",i2c_buffer[i]);
   printf("\n\r");

   i2c_buffer_read_16(i2c_buffer,0xA0,0x00,I2CREGS);

   printf("Read:  ");
   for(i=0;i<I2CREGS;i++) printf("%X ",i2c_buffer[i]);
   printf("\n\r");

   while(1);
}


I'm using an 16F876 @ 4MHz, CCS v3.187 and I'm testing the I2C with a 24LC64 EEPROM...

Any idea??

Thanx in advance Wink
Haplo



Joined: 06 Sep 2003
Posts: 659
Location: Sydney, Australia

View user's profile Send private message

PostPosted: Fri May 07, 2004 6:47 am     Reply with quote

Make sure RC3 and RC4 are configured as inputs. Have you tried taking the 'fast' keyword out to see if it works? How big are your pull-ups?
Mc



Joined: 07 May 2004
Posts: 11

View user's profile Send private message

PostPosted: Fri May 07, 2004 7:24 am     Reply with quote

Thanx for the quick answer!

Manually setting PORTC as inputs with set_tris_c(0xFF); doesn't solve the problem, maybe RS232 routines are overwiting this setting??

My pull-ups are 2k2 each. In 'Slow' mode it doesn´t work either.

Also I think that I don't have to output float the i2c pins while using i2c hw, I tried to comment

output_float(EEPROM_SCL);
output_float(EEPROM_SDA);

but still no luck...

I guess there's no HW related problem since I've been working with I2C HW ASM routines in the same board not so long ago with no issues whatsoever...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 07, 2004 12:06 pm     Reply with quote

I would guess that you're probably using PCW.

If you don't use a peripheral module, PCW puts in code to
explicitly disable it. This isn't really necessary, because the
peripheral modules are disabled by default upon power-up.

The problem is caused by this line of code:
setup_spi(FALSE);

That line sets the SSPCON register to 0x00. So it affects
the entire SSP module, and not just "spi", as the function name
suggests. It writes a 0 to the SSPEN bit in that register.
According to the data sheet:

bit 5 SSPEN: Synchronous Serial Port Enable bit
0 = Disables serial port and configures these pins as I/O port pins

That's why it's not working. The solution is to delete that line.
kender_a
Guest







Same problem.
PostPosted: Fri May 07, 2004 2:22 pm     Reply with quote

Hello,

I have the same problem - I2C stops worling if is specify FORCE_HW. But I don't have a call to setup_spi() anywhere in my code. Here's my code:

Code:


#include <18F442.h>
#device ICD=TRUE
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT,WDT128,XT, NOPROTECT, NOOSCSEN, BROWNOUT, BORV20, NOPUT, STVREN, DEBUG, LVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(DEBUGGER)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,force_hw)


#include "i2ctest.h"


void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   
   
   while (1)
   {
      // single write to EEPROM
      i2c_start();
      i2c_write(0b10100000);  // command byte
      i2c_write(0x01);        // address
      i2c_write(0xAA);        // data     
      i2c_stop();
     
      // single read from EEPROM
      i2c_start();
      i2c_write(0b10100000);  // command byte
      i2c_write(0x01);        // read address
      i2c_start();
      i2c_write(0b10100001);  // command byte     
      printf("%4X\n\r", i2c_read(1));  // end of the read
      i2c_stop();
     
      // page write to EEPROM
      // page read from EEPROM
      // write to DAC
      // read RTC
   }
}



I'm running this with the debugger, and the execution halts at "setup_adc_ports(NO_ANALOGS);"

What am I doing wrong?

Nick
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 07, 2004 2:33 pm     Reply with quote

Quote:
I have the same problem - I2C stops working if I specify FORCE_HW


Quote:
I'm running this with the debugger, and the execution halts
at "setup_adc_ports(NO_ANALOGS);"


These are two separate complaints. I'll answer the one about
the i2c problem.

You have this line of code:
printf("%4X\n\r", i2c_read(1));

That's wrong. The last i2c read must do a "NAK".
It should be:
printf("%4X\n\r", i2c_read(0));
kender_a
Guest







NACK worked
PostPosted: Fri May 07, 2004 2:52 pm     Reply with quote

Thanks, switching to i2c_read(0) worked, and formware doesn't halt at setup_adc_ports(NO_ANALOGS) too.

I have another question though. I have to pause for about 5ms between the read and the write. Otherwise I read 0xFF. Can this pause be avoided? Here's my code again:

Code:

while (1)
   {
      // single write to EEPROM
      i2c_start();
      i2c_write(0b10100000);  // command byte
      i2c_write(0x01);        // address
      i2c_write(i);        // data     
      i2c_stop();
     
      delay_ms(5);
     
      // single read from EEPROM
      i2c_start();
      i2c_write(0b10100000);  // command byte
      i2c_write(0x01);        // read address
      i2c_start();
      i2c_write(0b10100001);  // command byte     
      printf("%4X\n\r", i2c_read(0));  // end of the read, NACK
      i2c_stop();
     
      // page write to EEPROM
      // page read from EEPROM
      // write to DAC
      // read RTC
     
      ++i;
      if (i == 255) i = 1;
   }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 07, 2004 3:21 pm     Reply with quote

Quote:
I have another question though. I have to pause for about 5ms
between the read and the write. Otherwise I read 0xFF. Can this pause
be avoided?


The EEPROM data sheet will tell you that it takes about 5 ms for
the write operation to be completed. Look at page 4 of the
data sheet, at Parameter No. 17:
http://ww1.microchip.com/downloads/en/DeviceDoc/21203l.pdf

The two common ways to handle this are:

1. Put a delay_ms(5) statement at the end of the write operation.
ie., put it after the i2c_stop() statement at the end of the routine.
(Or use a slightly larger delay, such as 6 ms, to be extra safe).

2. Do "ack polling". This method is discussed in the 24LC256 data
sheet. CCS does this in their sample EEPROM drivers.
The drivers are in this directory:
c:\Program Files\Picc\Drivers
If you have the demo, you probably don't get these files.
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

I2C Delay Required
PostPosted: Fri May 07, 2004 3:38 pm     Reply with quote

One way to eliminate the delay is to use FRAM which does not require a delay between the write and read....
Mc



Joined: 07 May 2004
Posts: 11

View user's profile Send private message

PostPosted: Fri May 07, 2004 9:46 pm     Reply with quote

PCM programmer wrote:
The problem is caused by this line of code:
setup_spi(FALSE);
.
.
.
That's why it's not working. The solution is to delete that line.


Yep, that was the problem! Smile

Thanx a lot!! Wink
hayri
Guest







PostPosted: Sat Mar 19, 2005 9:53 am     Reply with quote

very old topic to post. but i must!

thanks a lot PCM programmer Smile it solved my problem.
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