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

I2C Master & Slave with 2 PIC's SOLVED
Goto page Previous  1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Mon Sep 30, 2019 2:04 am     Reply with quote

What you post, requires an External Clock Module, not a crystal (ECM).

Crystal. A simple(!) piece of electromagnetic resonant material.
ECM a 'crystal', with the electronics to drive it.

The PIC is capable of directly driving a 'crystal' (using two pins), but
'ECM_IO' is saying that you are adding a complete external module,
which already has the oscillator in it, and using just one pin to receive the
clock signal from this.

On 'what happens' with the interrupt, in general, unless interrupts are
explicitly disabled, an interrupt will be responded to immediately.
The actual I2C here is being generated in hardware. The setup involves
a handful of instructions/ So what will happen if (for example) an INT_RDA
arrives is that between these instructions, the chip will respond and
handle the interrupt. If the I2C transaction has not actually been
triggered, it'll happen after the interrupt. If it has been started, the
hardware will handle the transaction while the interrupt handling is
happening.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 30, 2019 5:14 am     Reply with quote

Thank you for the explanation Ttelmah.

Best wishes
Joe
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 08, 2020 1:26 am     Reply with quote

Hi

CCS PCH C Compiler, Version 5.062, xxxxx

After getting my new boards and assemble them with two PIC18F26K22 and a 24C512 EEPROM and adapting the I2C programs to the PIC18F26K22 I started testings to be sure that everything works OK.
On the I2C lines I have 2K7 pull-up resistors (on SCL and SDA lines).
For the testing, each time the PC sends a byte, the Master increments data0 & data1 by 1, send it by I2C to the slave and gets back slaverpt0 and slaverpt1.
Then the master sends message to the PC.
But I have a problem:
If I increment data0 or both data0 & data1, up to data value of 0x3F everything OK. At 0x40, the slave stops working, including the flash led (once a second)
If I keep data0 at 0x00 and increment just data1, everything OK
Same procedure with 24C512 have no any problem
Tried to add data2 and slaverpt2, increments OK all the way to 0xFF and overflow just if data0 & data1 are 0x00 and data2 increments.

Master code:
Code:
/////////////////////////////////////////////////////////////////////
//I2C26K22MX0 new project based on Ttelmah program
//the program is for Master I2C PIC18F26K22 connecting to 24C512 & Slave PIC18F26K22
//I2C26K22MV0.c
//Program last update,January 7, 2020
/////////////////////////////////////////////////////////////////////
//PC sends message to I2C26K22M to write/read 24C512; 0x00
//rpt; 0x00,24C512 address high;24C512 address low;I2C24C512readdata0
//PC sends message to I2C26K22M to read 24C512; 0x01
//rpt; 0x01,24C512 address high;24C512 address low;I2C24C512readdata0
//PC sends message to I2C26K22M to write/read I2C26K22S; 0x02
//rpt; 0x02,slaverpt0;slaverpt1,0x00
//PC sends message to I2C26K22M to read I2C26K22S;0x03
//rpt; 0x03,slaverpt0;slaverpt1,0x00
/////////////////////////////////////////////////////////////////////
#include <18F26K22.h>
#device ADC=10
#FUSES NOWDT,NOPBADEN,PUT,BROWNOUT,BORV29,HSH,PLLEN,NOIESO,NOFCMEN,NOHFOFST                                       
#FUSES MCLR,STVREN,NOLVP,NOXINST,NODEBUG,NOPROTECT,NOCPD,NOWRT,NOWRTC,NOWRTD
#use delay(clock=64MHz,crystal=16MHz)
#use rs232(baud=9600, UART1, stream=PORT1, errors)
#use I2C(MASTER, Fast=400000, I2C1, STREAM=I2CPORT)//I2C1 hardware used
/////////////////////////////////////////////////////////////////////
//PIN_A6 crystal 16MHz;PIN_A7 crystal 16MHz;PIN_B6 PGC;PIN_B7 PGD
//PIN_C3 I2C Master SCL1;PIN_C4 I2C Master SDA1;PIN_C6 TX1 to PC;PIN_C7 RX1 from PC
#define flashled PIN_B5//flashes ones a second
//general variables
int flashledcnt=0;
int scomtx1words,scomtx1w0,scomtx1w1,scomtx1w2,scomtx1w3;
short scomrx1newdataF;
int scomrx1words,scomrx1w0;
//24C512 I2C variables
short I2C24C512writeF,I2C24C512readF,I2C24C512newdataF,I2C24C512readdoneF;
int I2C24C512addresshigh,I2C24C512addresslow;
int I2C24C512writedata0,I2C24C512writedata1,I2C24C512writedata2,I2C24C512writedata3;
int I2C24C512writedata4,I2C24C512writedata5,I2C24C512writedata6,I2C24C512writedata7;
int I2C24C512writedata8,I2C24C512writedata9,I2C24C512writedataA,I2C24C512writedataB;
int I2C24C512writedataC,I2C24C512writedataD,I2C24C512writedataE,I2C24C512writedataF;
int I2C24C512readdata0,I2C24C512readdata1,I2C24C512readdata2,I2C24C512readdata3;
int I2C24C512readdata4,I2C24C512readdata5,I2C24C512readdata6,I2C24C512readdata7;
int I2C24C512readdata8,I2C24C512readdata9,I2C24C512readdataA,I2C24C512readdataB;
int I2C24C512readdataC,I2C24C512readdataD,I2C24C512readdataE,I2C24C512readdataF;
//PIC18F26K22 Slave I2C variables
short I2C26K22SwriteF,I2C26K22SreadF,I2C26K22SnewdataF,I2C26K22SreaddoneF;
int data0,data1;
int slaverpt0,slaverpt1;
/////////////////////////////////////////////////////////////////////
//Timer0 increments every 20ms
#int_TIMER0
void TIMER0_isr(void)
{
   flashledcnt++;
   if(flashledcnt>=25)
   {
      flashledcnt=0;
      output_toggle(flashled);
   }   
   set_timer0(45536);
}
#int_TBE//TX1 to PC; Baud rate 9600 BPS
void TBE_isr(void)
{
   switch(scomtx1words)
   {
      case 0:
      {
         fputc(scomtx1w0,PORT1);   
         scomtx1words++;   
      }
      break;
      case 1:
      {
         fputc(scomtx1w1,PORT1);
         scomtx1words++;         
      }
      break;
      case 2:
      {
         fputc(scomtx1w2,PORT1);   
         scomtx1words++;         
      }
      break;
      case 3:
      {
         fputc(scomtx1w3,PORT1);
         disable_interrupts(INT_TBE);
         scomtx1words=0;      
      }
      break;
   }   
}
#int_RDA//RX1 from PC; boud rate 9600 BPS
void RDA_isr(void)
{
   switch(scomrx1words)
   {
      case 0:
      {
         scomrx1w0=fgetc(PORT1);   
         scomrx1newdataF=1;
         scomrx1words=0;   
      }
      break;
   }
}
//DIGITAL FUNCTIONS
void DG(void)
{
   if(scomrx1newdataF==1)//rx1 new message
   {
      scomrx1newdataF=0;
      if(scomrx1w0==0)//starts I2C24C512 write/read
      {
         I2C24C512writedata0++;//increment data0 for write/read testing
         I2C24C512addresshigh++;//24C512 address high++ for testing address change
         I2C24C512addresslow++;//24C512 address low++ for testing address change
         I2C24C512writeF=1;
      }
      else if(scomrx1w0==1)//starts I2C24C512 read
      {
         I2C24C512readF=1;
      }
      else if(scomrx1w0==2)//starts I2C26K22S write/read
      {
         data0=0x00;//constant or increment data0 for write/read testing
         data1++;//constant or increment data1 for write/read testing      
         I2C26K22SwriteF=1;
      }
      else if(scomrx1w0==3)//starts I2C26K22S read
      {
         I2C26K22SreadF=1;
      }
   }
   if(I2C26K22SnewdataF==1)//Updating data after I2C26K22S write/read and starts tx1
   {
      I2C26K22SnewdataF=0;
      scomtx1w0=scomrx1w0;
      scomtx1w1=slaverpt0;
      scomtx1w2=slaverpt1;
      scomtx1w3=0x00;
      enable_interrupts(INT_TBE);
   }
   else if(I2C26K22SreaddoneF==1)//Updating data after I2C26K22S read and starts tx1
   {
      I2C26K22SreaddoneF=0;
      scomtx1w0=scomrx1w0;
      scomtx1w1=slaverpt0;
      scomtx1w2=slaverpt1;
      scomtx1w3=0x00;
      enable_interrupts(INT_TBE);
   }
   else if(I2C24C512newdataF==1)//Updating data after I2C24C512 write/read and starts tx1
   {
      I2C24C512newdataF=0;
      scomtx1w0=scomrx1w0;
      scomtx1w1=I2C24C512addresshigh;
      scomtx1w2=I2C24C512addresslow;
      scomtx1w3=I2C24C512readdata0;
      enable_interrupts(INT_TBE);
   }
   else if(I2C24C512readdoneF==1)//Updating data after I2C24C512 read and starts tx1
   {
      I2C24C512readdoneF=0;
      scomtx1w0=scomrx1w0;
      scomtx1w1=I2C24C512addresshigh;
      scomtx1w2=I2C24C512addresslow;
      scomtx1w3=I2C24C512readdata0;
      enable_interrupts(INT_TBE);
   }
}
void I2C24C512 (void)
{
   if(I2C24C512writeF==1)//write/read data from 24C512 will start if rx1 message 0x00
    {
      I2C24C512writeF=0;
         i2c_start();
        i2c_write(0xA0);//24C512 address with write
      i2c_write(I2C24C512addresshigh);//24C512 address high
       i2c_write(I2C24C512addresslow);//24C512 address low
        i2c_write(I2C24C512writedata0);   
        i2c_write(I2C24C512writedata1);   
        i2c_write(I2C24C512writedata2);   
        i2c_write(I2C24C512writedata3);   
        i2c_write(I2C24C512writedata4);   
        i2c_write(I2C24C512writedata5);   
        i2c_write(I2C24C512writedata6);   
        i2c_write(I2C24C512writedata7);   
        i2c_write(I2C24C512writedata8);   
        i2c_write(I2C24C512writedata9);   
        i2c_write(I2C24C512writedataA);   
        i2c_write(I2C24C512writedataB);   
        i2c_write(I2C24C512writedataC);   
        i2c_write(I2C24C512writedataD);   
        i2c_write(I2C24C512writedataE);   
        i2c_write(I2C24C512writedataF);
        i2c_stop();   
         delay_ms(10); //ensure the 24C512 has had time to complete the write
         i2c_start();
        i2c_write(0xA0);//24C512 address with write
      i2c_write(I2C24C512addresshigh);//address high
       i2c_write(I2C24C512addresslow);//address low
         i2c_start();//restart for read
         i2c_write(0xA1);//24C512 address with read
         I2C24C512readdata0 = i2c_read();
         I2C24C512readdata1 = i2c_read();
         I2C24C512readdata2 = i2c_read();
         I2C24C512readdata3 = i2c_read();
         I2C24C512readdata4 = i2c_read();
         I2C24C512readdata5 = i2c_read();
         I2C24C512readdata6 = i2c_read();
         I2C24C512readdata7 = i2c_read();
         I2C24C512readdata8 = i2c_read();
         I2C24C512readdata9 = i2c_read();
         I2C24C512readdataA = i2c_read();
         I2C24C512readdataB = i2c_read();
         I2C24C512readdataC = i2c_read();
         I2C24C512readdataD = i2c_read();
         I2C24C512readdataE = i2c_read();
         I2C24C512readdataF = i2c_read(0);//last read with NACK
         i2c_stop();
      I2C24C512newdataF=1;   
   }
   else if(I2C24C512readF==1)//read data from 24C512 will start if rx1 message 0x01
   {
      I2C24C512readF=0;
         i2c_start();
        i2c_write(0xA0);//24C512 address with write
      i2c_write(I2C24C512addresshigh);//address high
       i2c_write(I2C24C512addresslow);//address low
         i2c_start();//restart for read
         i2c_write(0xA1);//24C512 address with read~
         I2C24C512readdata0 = i2c_read();
         I2C24C512readdata1 = i2c_read();
         I2C24C512readdata2 = i2c_read();
         I2C24C512readdata3 = i2c_read();
         I2C24C512readdata4 = i2c_read();
         I2C24C512readdata5 = i2c_read();
         I2C24C512readdata6 = i2c_read();
         I2C24C512readdata7 = i2c_read();
         I2C24C512readdata8 = i2c_read();
         I2C24C512readdata9 = i2c_read();
         I2C24C512readdataA = i2c_read();
         I2C24C512readdataB = i2c_read();
         I2C24C512readdataC = i2c_read();
         I2C24C512readdataD = i2c_read();
         I2C24C512readdataE = i2c_read();
         I2C24C512readdataF = i2c_read(0);//last read with NACK
         i2c_stop();
      I2C24C512readdoneF=1;            
   }
}
///////////////////////////////////////////////////////////////////
void I2C26K22S (void)//I2C26K22M master & I2C26K22S Slave write/read starts if rx1 message 0x02
{
    if(I2C26K22SwriteF==1)
    {
         I2C26K22SwriteF=0;
//write data to Slave PIC
        i2c_start();
        i2c_write(0xB0);//Slave address with write
        i2c_write(data0);
        i2c_write(data1);
        i2c_stop();
//read back data from the Slave PIC
        delay_us(1000); //ensure the Slave has had time to complete the write
        i2c_start();
        i2c_write(0xB1);//Slave address with read
        slaverpt0 = i2c_read();
        slaverpt1 = i2c_read(0);
        i2c_stop();
      I2C26K22SnewdataF=1; 
   }
   else if(I2C26K22SreadF==1)//I2C26K22M master & I2C26K22S Slave read starts if rx1 message 0x03
   {
      I2C26K22SreadF=0;
          i2c_start();
        i2c_write(0xB1);//Slave address with read
        slaverpt0 = i2c_read();
        slaverpt1 = i2c_read(0);
        i2c_stop();
      I2C26K22SreaddoneF=1;
   }
}
///////////////////////////////////////////////////////////////////

#ZERO_RAM

void main()
{
   setup_adc_ports(NO_ANALOGS);   
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.536 ms overflow
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_RDA);
   disable_interrupts(INT_TBE);
   enable_interrupts(GLOBAL);
   while(TRUE)
   {
      DG();
      I2C24C512();
      I2C26K22S();
   }
}
/////////////////////////////////////////////////////////////////////

Slave code
Code:
/////////////////////////////////////////////////////////////////////
//I2C26K22SX0 new project based on Ttelmah program
//the program is for Slave I2C PIC18F26K22
//Program last update,January 7, 2020
/////////////////////////////////////////////////////////////////////
#include <18F26K22.h>
#device ADC=10
#FUSES NOWDT,NOPBADEN,PUT,BROWNOUT,BORV29,HSH,PLLEN,NOIESO,NOFCMEN,NOHFOFST                                       
#FUSES MCLR,STVREN,NOLVP,NOXINST,NODEBUG,NOPROTECT,NOCPD,NOWRT,NOWRTC,NOWRTD
#use delay(clock=64MHz,crystal=16MHz)
#use i2c(Slave,Address=0xB0,I2C1)//I2C1 module, automatically hardware
/////////////////////////////////////////////////////////////////////
//PIN_A6 crystal 16MHz;PIN_A7 crystal 16MHz;PIN_B6 PGC;PIN_B7 PGD
//PIN_C3 I2C Slave SCL1;PIN_C4 I2C Slave SDA1
#define flashled PIN_C5//flashes ones a second
//variables
int flashledcnt=0;
int state,value;
int data0,data1;
#int_TIMER0
void TIMER0_isr(void)
{
   flashledcnt++;
   if(flashledcnt>=25)//500ms
   {
      flashledcnt=0;
      output_toggle(flashled);
   }
   set_timer0(45536);
}
/////////////////////////////////////////////////////////////////////
//The core I2C slave code.   
//Now states < 0x80, are read states. The master is sending us data
//However state 0x0, is where the master sends up the address itself
//so we need to use state-1 as the array index to write data
//State 0x80 is where the master sends the address for the write. On this
//we must read, and then write the byte for the reply.
/////////////////////////////////////////////////////////////////////
#INT_SSP
void I2C_isr (void)
{
   state=i2c_isr_state();
   if (state<=0x80)
   {
      switch(state)
      {
           case 0x80:     
            value=i2c_read(0x02);//here we need to read, and not release the clock
         break;   
           case 0:
            value=i2c_read();//throw away address read
         break; 
           case 1:
            data0=i2c_read();
         break;
           case 2:
            data1=i2c_read();
         break;
      }
   }
   switch(state) 
   {
      case 0x80:
         i2c_write(data0);
      break;
      case 0x81:
         i2c_write(data1);
      break;               
   }
}
/////////////////////////////////////////////////////////////////////

#ZERO_RAM

void main()
{
   setup_adc_ports(NO_ANALOGS);   
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.536 ms overflow
   enable_interrupts(INT_TIMER0);
    enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
      delay_us(1);
   }
}
/////////////////////////////////////////////////////////////////////

I am sure I am making some big mistake, didn't succeed to find it yet
Any suggestion will be much appreciated
Using I2C to communicate between master and slave simplified my program and also releasing me two additional rs232 communications that I really need.

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Wed Jan 08, 2020 3:41 am     Reply with quote

I don't see you anywhere programming the slew rate control on either chip.
These chips default to starting with the pin output slew rate limited. May
well cause issues. Possibly what is happening is 0x40, is slewing off so
slowly that the bit is stretching into another bit of the packet and resulting
in the I2C slave peripheral getting hung.

Code:

#byte GETENV("SFR:SLRCON")

//Then at the start of your code for both chips
    SLRCON=0; //Turn off slew rate limit.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 08, 2020 8:05 pm     Reply with quote

Hi Ttelmah

Thank you for the prompt answer.

I inserted the GETENV like that:
Code:
int data0,data1;
int slaverpt0,slaverpt1;
#byte SLRCON = GETENV("SFR:SLRCON")


and SLRCON=0; like that:
Code:
void main()
{
   SLRCON=0; //Turn off slew rate limit.
   setup_adc_ports(NO_ANALOGS);   
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);//65.536 ms overflow
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_RDA);
   disable_interrupts(INT_TBE);
   enable_interrupts(GLOBAL);
   while(TRUE)
   {
      DG();
      I2C24C512();
      I2C26K22S();
   }
}


I inserted also same in the slave.
But the result is same, the slave stuck at 0x40 or if I put a constant bigger than 0x3F the slave stuck also.

Maybe I insert #byte SLRCON = GETENV("SFR:SLRCON") & SLRCON=0; in wrong places?

Best wishes
Joe
newguy



Joined: 24 Jun 2004
Posts: 1899

View user's profile Send private message

PostPosted: Wed Jan 08, 2020 8:19 pm     Reply with quote

Does your code for the slew rate actually compile? There should be one SLRCONx per port, for example SLRCONA for port A, SLRCONB for port B, etc.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Wed Jan 08, 2020 11:36 pm     Reply with quote

Thank you for posting Newguy

I check the data sheet and PIC18F26K22 have just one SLRCON
when each port have one bit to enable/disable limited slew rate.
By making SLRCON=0; as Ttelmah wrote, all the ports slew rates are at the standard rate, not limited.
In the .lst
Quote:
.................... SLRCON=0; //Turn off slew rate limit.
0056C: CLRF F60

so I suppose it takes effect. The slave .lst shows the same.

Thank you again
Best wishes
Joe
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 10, 2020 12:43 am     Reply with quote

Hi

I tried a few things but with no success.
I simplified the master and slave to send and receive just one byte and is working correct with numbers from 0x00 to 0xFF.
Master:
Code:
void I2C26K22S (void)//I2C26K22M master & I2C26K22S Slave write/read starts if rx1 message 0x02
{
    if(I2C26K22SwriteF==1)
    {
         I2C26K22SwriteF=0;
//write data to Slave PIC
        i2c_start();
        i2c_write(0xB0);//Slave address with write
        i2c_write(data0);
//        i2c_write(data1);
        i2c_stop();
//read back data from the Slave PIC
        delay_us(1000); //ensure the Slave has had time to complete the write
        i2c_start();
        i2c_write(0xB1);//Slave address with read
        slaverpt0 = i2c_read(0);
//        slaverpt1 = i2c_read(0);
        i2c_stop();
      I2C26K22SnewdataF=1; 
   }
   else if(I2C26K22SreadF==1)//I2C26K22M master & I2C26K22S Slave read starts if rx1 message 0x03
   {
      I2C26K22SreadF=0;
          i2c_start();
        i2c_write(0xB1);//Slave address with read
        slaverpt0 = i2c_read(0);
//        slaverpt1 = i2c_read(0);
        i2c_stop();
      I2C26K22SreaddoneF=1;
   }
}

Slave:
Code:
#INT_SSP
void I2C_isr (void)
{
   state=i2c_isr_state();
   if (state<=0x80)
   {
      switch(state)
      {
           case 0x80:     
            value=i2c_read(0x02);//here we need to read, and not release the clock
         break;   
           case 0:
            value=i2c_read();//throw away address read
         break; 
           case 1:
            data0=i2c_read();
         break;
/*
           case 2:
            data1=i2c_read();
         break;
*/
      }
   }
   switch(state) 
   {
      case 0x80:
         i2c_write(data0);
      break;
/*
      case 0x81:
         i2c_write(data1);
      break;   
*/             
   }
}

If I will not find a solution, I will just send the 9 bytes I need one by one and get them back the same
I know is more complex program, I will try to see how I can get forward from here.

Best wishes
Joe
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 10, 2020 1:41 am     Reply with quote

Hi

I get one step forward.
Master sends one byte to the slave and get back 4 bytes from the slave with no problems.

What I need in my program is:
Master writes 9 bytes to the slave from time to time. It will be a hassle to do it byte by byte, but can be done.
If someone have some idea how to solve this problem please let me know
Master reads 20 bytes from the slave 5 times per second, I suppose if 4 bytes read is OK, 20 bytes read will be fine also.
I will test forward to read 20 bytes

Best wishes
Joe
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jan 10, 2020 3:45 am     Reply with quote

For testing, I would simplify both programs.

1. Don't run both programs at 64 MHz. Run the master at 4 MHz
and the slave at 16 MHz. Run the slave faster than the master.
Use crystals for both. Disable the PLL.

2. Don't run any interrupts except #int_ssp.

3. You have all this incredibly complicated serial port stuff, with else-ifs
and switch cases. I would just cut all that stuff out. Don't try to send
data during the test. Save the test results in a RAM array and send them
to the PC at the end of the test.

4. Don't run i2c FAST mode. Run it at 100 KHz.



Questions:
1. Why are using a 24C512 eeprom ? For years, the standard is 24LC512.
What manufacturer are you using ? Can you guarantee the chip is not
counterfeit ?

Comments:
1. You have incredibly long variable names that differ by only one
character. I would shorten them, and use underscores to make it
easier to read them quickly and accurately. Example:
Quote:
I2C24C512writedata0

could be shortened to:
Quote:
eeprom_wrt_data0


Another example:
Quote:
I2C24C512addresshigh

Instead, you could use this:
Quote:
eeprom_addr_high
or this:
Quote:
eeprom_addr_hi


2. Here, you are incrementing both the lsb and msb of the address.
Quote:
I2C24C512addresshigh++;
I2C24C512addresslow++;

This is unusual. I have to wonder if somewhere you have a problem
with crossing a page boundary in the eeprom. But your program is
so complicated and your variable names so long and so similar, that
it's difficult to follow what the code is doing in every detail.
I would remove the incrementing of the MSB.

Also, your program doesn't tell me, just how high up do these two values
increment ? Where do they stop ? It's not stated.
Quote:
I2C24C512addresshigh++;
I2C24C512addresslow++;
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 10, 2020 6:41 am     Reply with quote

Thank you for posting PCM programmer

I will answer first to your questions and then I will go to implement your advice.

Quote:
1. Why are using a 24C512 eeprom

I am using 24FC512 (DIP) manufactured by Microchip. Bought them from Element 14 Singapore. They are working together with Newark Electronics in the US and Farnell in the UK, same stock. I suppose they don't have counterfeit products in they stock.
The reason in the program is 24C512 is because I copy/past the program written 14 years ago with some modifications. We were using them back then in the company I worked.
Comments:
Quote:
1. You have incredibly long variable names

You are right. The names like:
Quote:

I2C24C512writedata0
I2C24C512writedata1.....

I am using and not like:
Quote:
eeprom_wrt_data0

is not to mix variables with instructions like:
Quote:

setup_adc_ports(NO_ANALOGS);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);


Quote:
2. Here, you are incrementing both the lsb and msb of the address.

I am writing/reading blocks of 16 bytes so you are right, have problem
with crossing a page boundaries because I am incrementing address low by 1. I will change the increment to 16 as it should be in the program.

The reason to increment like:
Quote:

I2C24C512addresshigh++;
I2C24C512addresslow++;

is just to test that the boundaries will go from 0x00 to 0xFFF0
Each command from the PC increment them by 1 until overflow back to 0x00
As I wrote before, is just for testing and the data used is stored in groups of 16 bytes. I will change the increment of address low as I wrote before to 16.

Thank you again, will post again after implementing your advice.
Best wishes
Joe


Last edited by gjs_rsdi on Fri Jan 10, 2020 6:50 am; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jan 10, 2020 6:47 am     Reply with quote

I also suggest slowing down the PICs,especially for design/testing. I recall 2-3 yeras ago, one project would fail ( get hung up) at 64MHz so I went down to 16MHz...problem 'magically' went away, so I carried on, finished the project. I was going to go back and figure out WHY it failed at 64 but never did.
Long variable names good in theory but will cause you trouble. Being 'old' I prefer 3 letter groups..... XEP_ADR_HIB means eXternal Eeprom Address High Byte. Having shorter names also reduces mistyping them and eventually you'll have a common list. 'RTC' in my variables refers to a Real Time Clock like the DS1307.
Multiple writes/reads from I2C devices is common. Accessing the DS1307 RTC does this (yr,mth,day,dow,hrs,min,sec) so you should be able to as well.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 10, 2020 6:56 am     Reply with quote

Thank you Temtronic for posting.

I will implement PCM programmer's advice, and your suggestion, and will post the results.

Best wishes
Joe
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Fri Jan 10, 2020 7:25 am     Reply with quote

With the addresshigh/low thing you'd normally want something like:
Code:

if (I2C24C512addresslow==255)
   I2C24C512addresshigh++;
I2C24C512addresslow++;

Which would then give you a 16bit increment. If the LSB is going to wrap,
it increments the MSB.

Honestly though much safer and simpler, to implement both addresses into
a union:
Code:

struct LSBMSB {
    uint8_t LSB;
    uint8_t MSB;
}

union {
   struct LSBMSB parts;
   uint16_t whole;
} address;

//Then initialise with
address.whole=0; //whatever you want

//Increment with
address.whole++;

//Access LSB with
address.parts.LSB

//and  MSB with
address.parts.MSB


Obviously you can read or write to these 'parts'.
gjs_rsdi



Joined: 06 Feb 2006
Posts: 468
Location: Bali

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 10, 2020 3:36 pm     Reply with quote

Thank you Ttelmah

I am going to implement the advice one by one and will post the results.

Best wishes
Joe
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Page 3 of 6

 
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