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 slave issue on PIC16F690

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



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

I2C slave issue on PIC16F690
PostPosted: Thu Feb 14, 2008 8:57 am     Reply with quote

Hello,
I am having issues with a circuti design where i use a PIC16F690 to be used as a i2c slave device. I am using the int_ssp routine that i have seen many times on the forum here and in the ccs examples. However, it appears that in my circuit it is not consistantly working. We have been able to capture periods where the device does not respond to a command or it appears to give back incorrect data. When we watch the data with a scope we have been able to catch times when the slave device does not give an Ack or it appears to give the ack too late. I am running out of ideas on what to try to resolve this. Does anyone have a clue what could be done to either fix this or test it further to see what is happening? My issue is that is is VERY random and might take hours worth of communication to catch. Compiler Vr 4.062
Code:

#include <16F690.h>
#device adc=10
//#priority ssp,rtcc,ext
#use delay(clock=8000000, RESTART_WDT)
#fuses WDT,INTRC_IO, PUT, MCLR, NOBROWNOUT, NOCPD, NOPROTECT
#use i2c(MASTER,slow,sda=PIN_C4,scl=PIN_C6)
#include <math.h>

#use fast_io(A)
#define  sw_in    PIN_A2            //interrupt pin
#define  LED4     PIN_A4            //60% led, green
#define  LED2     PIN_A5            //10-20% led, yellow

#use fast_io(B)
#define SMBD_E    PIN_B4            //smbus data external
#define LED1      PIN_B5            //100% led, green
#define SMBC_E    PIN_B6            //smbus clock external

#use fast_io(C)
#define LED5      PIN_C0            //80% led, green
#define SMBD_I    PIN_C4            //smbus data, internal
#define LED3      PIN_C5            //40% led, green
#define SMBC_I    PIN_C6            //smbus clock, internal
#define LED6      PIN_C7            //10% or less led, red


//#define INTS_PER_SECOND  30
#define INTS_PER_SECOND  122  //244
#BYTE   SSPCON1 = 0x14




////////////////////////////////////////////////////////////////////////////////

int   address,lsb_ch_crnt,lsb_percent,msb_status;
char  i,int_count,bus_free,fault,change_current,chg_term=0,set=0;
int   lsb_current,msb_current,count=0,msb,lsb_volt,lsb_status;
int   lsb_percent_send,lsb_temp_send,lsb_volt_send,lsb_ch_crnt_send;
int   lsb_status_send,msb_status_send;
long  time1,seconds,voltage,percent,status,ch_current;
long  time_cnt=0,value,loop;
int32  new_val;
signed long  current,temperature;
signed int   i2c_temp,lsb_temp,lsb;


////////////////////////////////////////////////////////////////////////////////
#int_rtcc
void clock_isr(void)
{
   if(--int_count==0)                     //decrement counter until 0
   {
      ++seconds;                          //count up seconds
      int_count=INTS_PER_SECOND;          //reset counter
      if (seconds>=65000)
         seconds=65000;
   }
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void read_sm_percent (void)
{
i2c_start();                        //read capacity
i2c_write(0x16);
i2c_write(0x0D);                    //relative state of charge
i2c_start();
i2c_write(0x17);                    //tell battery to write data
percent=i2c_read(0);                //read the data
i2c_stop();
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
lsb_percent=make8(percent,0);
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_temperature (void)
{
i2c_start();                        //read temperature
i2c_write(0x16);                    //battery address
i2c_write(0x08);                    //temperature register
i2c_start();
i2c_write(0x17);                    //tell battery to write data
lsb=i2c_read();                     //read in data bytes
msb=i2c_read(0);
i2c_stop();
temperature=make16(msb,lsb);           //make word
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
temperature=temperature-2740;         //change to celcius
i2c_temp=temperature/10;            //make degrees 1C
lsb_temp=make8(i2c_temp,0);
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_voltage (void)
{
i2c_start();                        //read capacity
i2c_write(0x16);                    //battery address
i2c_write(0x09);                    //voltage register
i2c_start();
i2c_write(0x17);                    //tell battery to write data
lsb=i2c_read();                     //read data bytes
msb=i2c_read(0);
i2c_stop();
voltage=make16(msb,lsb);               //make word
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
voltage=voltage/100;
lsb_volt=make8(voltage,0);
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_current (void)
{
i2c_start();                        //read capacity
i2c_write(0x16);                    //battery address
i2c_write(0x0A);                    //current register
i2c_start();
i2c_write(0x17);                    //tell battery to write data
lsb=i2c_read();                     //read bytes
msb=i2c_read(0);
i2c_stop();
current=make16(msb,lsb);               //combine into a word
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_charging_current (void)
{
i2c_start();                        //read status
i2c_write(0x16);                    //battery address
i2c_write(0x14);                    //current register
i2c_start();
i2c_write(0x17);                    //tell battery to write data
lsb=i2c_read();                     //read bytes
msb=i2c_read(0);
i2c_stop();
ch_current=make16(msb,lsb);               //combine into a word
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
ch_current=ch_current/64;
lsb_ch_crnt=make8(ch_current,0);
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_status (void)
{
i2c_start();                        //read status
i2c_write(0x16);                    //battery address
i2c_write(0x16);                    //status register
i2c_start();
i2c_write(0x17);                       //tell battery to write data
lsb=i2c_read();
msb=i2c_read(0);                   
i2c_stop();
status=make16(msb,lsb);
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
lsb_status=make8(status,0);
msb_status=make8(status,1);
}
////////////////////////////////////////////////////////////////////////////////
#int_ext
void rb0_isr(void)
{
   #use i2c(Master,slow,sda=PIN_C4,scl=PIN_C6)  //change to internal smbus
   delay_ms(20);
   while (!input(sw_in))                        //watch switch depression
   {
      if ((temperature>=400) || (temperature<=50) || (voltage<=180))
         fault=1;                               //look for fault condition
      else
         fault=0;
      if (fault==1)                             //fault is there
      {
         output_low(LED5);                      //flash led
         delay_ms(100);
         output_high(LED5);
         delay_ms(100);
      }
      if (fault==0)                             //if no fault, show capacity
      {
         if (percent<=129 && percent>=80)       //in different LED percentages
            output_low(LED1);
         else
            output_high(LED1);
         if (percent>=60)
            output_low(LED2);
         else
            output_high(LED2);
         if (percent>=40)
            output_low(LED3);
         else
            output_high(LED3);
         if (percent>=20)
            output_low(LED4);
         else
            output_high(LED4);
         if (percent<=19 && percent>=10)
            output_low(LED5);
         else
            output_high(LED5);
         if (percent<=9 && percent>=0)
            output_low(LED6);
         else
            output_high(LED6);
         delay_ms(100);
      }
   }
   fault=0;
   output_high(LED1);                     //turn led off
   output_high(LED2);                     //turn led off
   output_high(LED3);                     //turn led off
   output_high(LED4);                     //turn led off
   output_high(LED5);                     //turn led off
   output_high(LED6);                    //turn led off
   output_float(SMBC_I);                  //release data line
   output_float(SMBD_I);                  //release clock line
   output_float(SMBC_E);                  //release data line
   output_float(SMBD_E);                  //release clock line
   #use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B4,scl=PIN_B6,address=0x12,RESTART_WDT)
                                    //change back to external smbus
}
#use delay(clock=8000000, RESTART_WDT)
////////////////////////////////////////////////////////////////////////////////
#INT_SSP
void ssp_interupt (void)               //detect external smbus activity
{
   BYTE incoming, state;

   state = i2c_isr_state();
   #use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B4,scl=PIN_B6,address=0x12,RESTART_WDT)
   if(state < 0x80)                     //Master is sending data
   {     
      if(state == 1 )                     //First received byte is address
         {
         incoming = i2c_read(1);
         address = incoming;
         }
      if(state == 2)                     //Second received byte is data
         {
         incoming = i2c_read(1);
         msb_current = incoming;
         change_current=1;
         }
   }
   if(state == 0x80)                     //Master is requesting data
      {
      if(address==0x00)
         lsb=lsb_status_send;
      if(address==0x01)                    //i2c register
         lsb=msb_status_send;
      if(address==0x02)                    //i2c register
         lsb=lsb_volt_send;
      if(address==0x04)                    //i2c register
         lsb=lsb_temp_send;
      if(address==0x08)                       //i2c register
         lsb=lsb_percent_send;
      if(address==0x14)                      //smbus register
         lsb=lsb_ch_crnt_send;
      i2c_write(lsb);                     //write first byte
      bit_set(SSPCON1,4);                 //set to let clock float
      bit_clear(SSPCON1,5);               //turn off serial
      output_float(SMBC_E);                  //let go of clock line
      output_float(SMBD_E);                  //let go of data line
      bit_set(SSPCON1,5);                    //reanable serial
      }                                   //added due to errata with PIC
   
   output_float(SMBC_E);                  //let go of clock line
   output_float(SMBD_E);                  //let go of data line
}
#use delay(clock=8000000, RESTART_WDT)
////////////////////////////////////////////////////////////////////////////////
void write_sm_current (void)
{
#use i2c(MASTER,slow,sda=PIN_C4,scl=PIN_C6)
i2c_start();
i2c_write(0x16);
i2c_write(0x00);
i2c_write(0x06);
i2c_write(0x06);
i2c_stop();
delay_ms(1000);
i2c_start();
i2c_write(0xA0);
i2c_write(0x1A);
i2c_write(msb_current);
i2c_write(lsb_current);
i2c_stop();
delay_ms(20);
i2c_start();
i2c_write(0x16);
i2c_write(0x7D);
i2c_write(0x80);
i2c_write(0x00);
i2c_stop();
i2c_start();
i2c_write(0x16);
i2c_write(0x7D);
i2c_write(0x00);
i2c_write(0x00);
i2c_stop();
output_float(SMBC_I);                  //release data line
output_float(SMBD_I);                  //release clock line
#use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B4,scl=PIN_B6,address=0x12,RESTART_WDT)
}
/*////////////////////////////////////////////////////////////////////////////////
void sm_free (void)
{
 while (count<=16)
      {
         if (input(SMBC_I))
            bus_free=1;
         else
         {
            bus_free=0;
            count=17;
         }
         delay_us(3);
         count=count+1;
      }
      count=0;
}
 //////////////////////////////////////////////////////////////////////////////*/
////////////////////////////////////////////////////////////////////////////////
void sm_free (void)
{
 while (count<=25)
      {
         if ((input(SMBC_I))&&(input(SMBD_I)))
            bus_free=1;
         else
         {
            bus_free=0;
            count=26;
         }
         delay_us(3);
         count=count+1;
      }
      count=0;
}
////////////////////////////////////////////////////////////////////////////////
void main()
{
   //#use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B1,scl=PIN_B4,address=0x12,RESTART_WDT)
   //#use i2c(MASTER,slow,sda=PIN_B2,scl=PIN_B5)
   output_float(SMBC_I);                  //release data line
   output_float(SMBD_I);                  //release clock line
   output_float(SMBC_E);                  //release data line
   output_float(SMBD_E);                  //release clock line
   output_high(LED1);                     //turn led off
   output_high(LED2);                     //turn led off
   output_high(LED3);                     //turn led off
   output_high(LED4);                     //turn led off
   output_high(LED5);                     //turn led off
   output_high(LED6);                     //turn led off

   setup_oscillator(osc_8mhz);
   setup_adc_ports(NO_ANALOGS);
   //setup_wdt(WDT_ON|WDT_36MS);
   setup_wdt(WDT_ON|WDT_36MS);
   //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   set_rtcc(0);
   enable_interrupts(INT_RTCC);
   ext_int_edge(0,H_TO_L);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   //port_b_pullups(false);            //added to see if this could be used on chg

   set_tris_a(0b00000100);
   set_tris_b(0b01010000);
   set_tris_c(0b01010000);

   int_count=INTS_PER_SECOND;          //used for timer
   seconds=0;                          //clear out variable
   time1=1;                        //counter for time,30 seconds
   loop=0;
   
   while (TRUE)
   {
      output_float(SMBC_I);                  //release data line
      output_float(SMBD_I);                  //release clock line
      output_float(SMBC_E);                  //release data line
      output_float(SMBD_E);                  //release clock line
      output_high(LED1);                     //turn led off
      output_high(LED2);                     //turn led off
      output_high(LED3);                     //turn led off
      output_high(LED4);                     //turn led off
      output_high(LED5);                     //turn led off
      output_high(LED6);                     //turn led off
      sleep();
      if (!(input(SMBC_E)))                  //check for clock low
            time_cnt=time_cnt+1;             //count times throug loop
         else                                //that clock is low
            {
            time_cnt=0;                      //if it is not, reset counter
            set=0;
            }
      if((time_cnt==0xFF) && (set==0))
         {                 //if clock has been low for 0.065s
         msb_current=0;                      //write charge current to 0
         lsb_current=0;
         write_sm_current();                 //reset counters
         time_cnt=0;
         set=1;
         }
      /*if((percent==100) && (chg_term==0))    //if battery full
         chg_term=1;                         //set termination flag
      if(percent<=100)                        //if pack less than 80%
         chg_term=0;                         //clear termination flag
      if(chg_term==1)                        //if flag set
         {
         msb_current=0;                      //write charge current to 0
         lsb_current=0;
         write_sm_current();
         }*/
      //output_low(LED3);
      delay_us(5);
      //output_high(LED3);
      delay_us(5);
      if(seconds>=time1)                     //15 seconds has elapsed
         {
         #use i2c(MASTER,slow,sda=PIN_C4,scl=PIN_C6)     //change smbus pins
         delay_ms(10);
         sm_free();
         if (bus_free==1)
            read_sm_voltage();
         if (lsb_volt>=160)
         {
         lsb_volt_send=lsb_volt;
         sm_free();                             //check to see if bus is free
         if (bus_free==1)                       //read values
            {
            read_sm_percent();
            lsb_percent_send=lsb_percent;
            }
         sm_free();
         if (bus_free==1)
            {
            read_sm_temperature();
            lsb_temp_send=lsb_temp;
            }
         sm_free();
         if (bus_free==1)
            {
            read_sm_current();
            }
         sm_free();
         if (bus_free==1)
            {
            read_sm_status();
            lsb_status_send=lsb_status;
            msb_status_send=msb_status;
            }
         sm_free();
         if (bus_free==1)
            {
            read_sm_charging_current();
            lsb_ch_crnt_send=lsb_ch_crnt;
            }
         }
         seconds=0;       
         #use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B4,scl=PIN_B6,address=0x12,RESTART_WDT)
         }                                   //change smbus pins
      if((change_current==1) && (address==0x81))
         {
         if(msb_current>0x1F)
            value=0x1F;
         else
            value=msb_current;
         new_val=value*64;
         msb_current=make8(new_val,0);
         lsb_current=make8(new_val,1);
         write_sm_current();
         change_current=0;
         }
   }
}
Matro
Guest







Config
PostPosted: Thu Feb 14, 2008 9:25 am     Reply with quote

Hi,

your I2C is configured as a master in your #use instruction. ;-)
Just try replace "master" by "slave".

Matro
Matro
Guest







Oops
PostPosted: Thu Feb 14, 2008 9:28 am     Reply with quote

I'm already sleeping. I don't read correctly your code.
Sorry for that I will have a deeper look at it.
Matro
Guest







PostPosted: Thu Feb 14, 2008 9:35 am     Reply with quote

The problem is (in my opinion) that your code do nothing when you receive the matching address with a "write" flag (case where i2c_isr_state() will return 0x00).
It's important that you read the SSPBUF register even in that case because that's the only way to clear the BF flag and avoid a buffer overflow.

You can have the same problem with all cases that you don't catch in your SSP interrupt routine. ;-)

Regards,
Matro
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Thu Feb 14, 2008 9:40 am     Reply with quote

Sorry, I am using the PIC as both a master and a slave, i forgot to put that in the original post. The Master part has no problems at all just the slave part. I am not sure i understand what you are stating. Won't the statement "if (state<=0x80)" catch the 0x00 case you are refering to? If not, could you try to explain a bit more? Thanks
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu Feb 14, 2008 9:50 am     Reply with quote

Looking at your code, briefly, I can see a couple of things.

You have multiple #use delay() statements in your code. You only need one at the beginning of your code.

You have a #use i2c() statement _inside_ your ISR. Not a good idea. Since you're already inside the ISR it would make no sense to make a command to use it once you're already inside it.

It appears that you are trying to drive a second I2C bus with the Slave. Instead of trying to toggle back and forth, why not try bit-banging the sencondary bus with the software portion. This way you would not need to worry about re-declaring each bus. I've done it with a few projects before and it has worked nicely. Or, if you want to try it, create a multi-master setup and you only need to worry about one bus.

One suggestion. If you're using a scope to monitor the signals, try driving a spare output high upon entering the ISR and then drive the output low just before you exit the ISR. Monitor this output with your scope and you will be able to see when the ISR is entered and exited. This will show how the timing is working. I'm currently doing this with one of my projects and it helps a lot to see how to adjust delays in my Master so it doesn't send commands faster than the Slave can handle them.

Ronald
Matro
Guest







PostPosted: Thu Feb 14, 2008 9:59 am     Reply with quote

nmeyer wrote:
Sorry, I am using the PIC as both a master and a slave, i forgot to put that in the original post. The Master part has no problems at all just the slave part. I am not sure i understand what you are stating. Won't the statement "if (state<=0x80)" catch the 0x00 case you are refering to? If not, could you try to explain a bit more? Thanks


The "if (state <= 0x80à" statement will catch the 0x00 case but due to the following code it will never read the SSPBUF.
Don't make a confusion between SSPIF and BF flags.
The SSPIF (interrupt flag) will be correctly cleared because the interrupt is catched. But the BF bit of the SSP will not be cleared because you never read the SSPBUF.
Just try this code for your interrupt routine and tell me about :
Code:

#INT_SSP
void ssp_interupt (void)               //detect external smbus activity
{
   BYTE incoming, state;

   state = i2c_isr_state();
   #use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B4,scl=PIN_B6,address=0x12,RESTART_WDT)
   if(state < 0x80)                     //Master is sending data
   {     
      if(state == 1 )                     //First received byte is address
         {
         incoming = i2c_read(1);
         address = incoming;
         }
      else if(state == 2)                     //Second received byte is data
         {
         incoming = i2c_read(1);
         msb_current = incoming;
         change_current=1;
         }
      else
         {
          i2c_read()
         }
   }
   else if(state == 0x80)                     //Master is requesting data
      {
      if(address==0x00)
         lsb=lsb_status_send;
      if(address==0x01)                    //i2c register
         lsb=msb_status_send;
      if(address==0x02)                    //i2c register
         lsb=lsb_volt_send;
      if(address==0x04)                    //i2c register
         lsb=lsb_temp_send;
      if(address==0x08)                       //i2c register
         lsb=lsb_percent_send;
      if(address==0x14)                      //smbus register
         lsb=lsb_ch_crnt_send;
      i2c_write(lsb);                     //write first byte
      bit_set(SSPCON1,4);                 //set to let clock float
      bit_clear(SSPCON1,5);               //turn off serial
      output_float(SMBC_E);                  //let go of clock line
      output_float(SMBD_E);                  //let go of data line
      bit_set(SSPCON1,5);                    //reanable serial
      }                                   //added due to errata with PIC
     else
      {
        i2c_write(0x00);
      }
   
   output_float(SMBC_E);                  //let go of clock line
   output_float(SMBD_E);                  //let go of data line
}
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Thu Feb 14, 2008 10:22 am     Reply with quote

At this point i have updated my test board and it is running fine with my i2c emulator. Next i have to program it into my "real world" test set up and let it run. This takes hours of run time to gather the read writes and determine if it is functioning correctly. Thanks
Matro
Guest







PostPosted: Thu Feb 14, 2008 10:31 am     Reply with quote

You're welcome.
Good luck!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 14, 2008 12:08 pm     Reply with quote

There is a problem with your coding style. You have too many global
variables. With so many globals, it's too easy to use the wrong one
in a routine, or to confuse the data size (is it 8 or 16 bits ?) or the type.
Most of your routines can be re-written to get rid of the globals and
use local variables instead. Also have the function return the value
that it gets or calculates, instead of putting it into a global. By doing
it this way, you will reduce the possibility of accidently coding a subtle
and hard-to-find error into a program.
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Fri Feb 15, 2008 8:35 am     Reply with quote

Matro, The changes did not help in the real world test. Thanks
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Fri Feb 15, 2008 4:25 pm     Reply with quote

rnielsen wrote:
Looking at your code, briefly, I can see a couple of things.

You have multiple #use delay() statements in your code. You only need one at the beginning of your code.

You have a #use i2c() statement _inside_ your ISR. Not a good idea. Since you're already inside the ISR it would make no sense to make a command to use it once you're already inside it.

It appears that you are trying to drive a second I2C bus with the Slave. Instead of trying to toggle back and forth, why not try bit-banging the sencondary bus with the software portion. This way you would not need to worry about re-declaring each bus. I've done it with a few projects before and it has worked nicely. Or, if you want to try it, create a multi-master setup and you only need to worry about one bus.

One suggestion. If you're using a scope to monitor the signals, try driving a spare output high upon entering the ISR and then drive the output low just before you exit the ISR. Monitor this output with your scope and you will be able to see when the ISR is entered and exited. This will show how the timing is working. I'm currently doing this with one of my projects and it helps a lot to see how to adjust delays in my Master so it doesn't send commands faster than the Slave can handle them.

Ronald


The multiple #use_delays were a suggestion either from some one else on this forum or from some CCS information i had. As far as the toggling back and forth between i2c declares, i would like to use the slave as hardware so that my ssp_int functions fine. If you have any sample programs showing how to drive the master i2c part with just software please share some. I am know see how to do it differently than what i have done. Thanks
Ttelmah
Guest







PostPosted: Sat Feb 16, 2008 6:13 am     Reply with quote

The multiple #use delay approach, ensures separate delay code is used in the interrupt handlers, to that used in the main. It requires _one_ such declaration, in front of the interrupt handlers, and _one_ in front of the other code. No more.

Best Wishes
i2c victim
Guest







i2c_read() on address match?
PostPosted: Wed Mar 05, 2008 1:06 pm     Reply with quote

Matro wrote:
The problem is (in my opinion) that your code do nothing when you receive the matching address with a "write" flag (case where i2c_isr_state() will return 0x00).
It's important that you read the SSPBUF register even in that case because that's the only way to clear the BF flag and avoid a buffer overflow.

You can have the same problem with all cases that you don't catch in your SSP interrupt routine. ;-)

Regards,
Matro


This is a good point, and the PIC will not ACK if there is a buffer overflow, according to PIC datasheet.

However, in the CCS manual page 156, there is some code that does nothing if i2c_isr_state() returns 0. This seems bad. Am I missing something?
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