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 stops working after xmitting less than 50 bytes

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



Joined: 26 Aug 2009
Posts: 6

View user's profile Send private message

I2C stops working after xmitting less than 50 bytes
PostPosted: Sun Aug 30, 2009 11:35 am     Reply with quote

I'm building an I2C bus between an 18F24J11 and an 16F690. The 18F24J11's MSSP1 module is configured as the master, the 16F690's HW SSP is configured as the slave.

I can move multiple bytes from the master to the slave as per the examples/[however many other threads]. After a seeming random (but small) number of bytes, no more data is received. Neither chip is locked up on any one statement and continue to respond to input and internal interrupts normally (confirmed through various LEDs, encoders, and LCDs). LED toggled within the I2C calls on both chips continue to blink normally.

Reading out the results of i2c_irs_state() onto an LCD. When operating normally moving two byes from the 18F to the 16F, the state is 2 after a complete transfer. Over time and the bus crash begins, the state will initially drop to 1, then start counting upwards as the bus appears to freeze. Infrequently, the I2C communications will not begin after either a hard/soft reset.

I am completely baffled by this behavior. I suspect the problem is in my slave code and probably related to how ACK's are being handled, maybe SSPBUF, BF, and/or SSPOV, however, I don't understand CCS's I2C routines well enough to see where the problem is originating.

Any input would be greatly appreciated. Getting it working is the goal, but I really want to understand what's going on here.

MASTER (18F24J11):
Code:

#include <18F24J11.h>
#fuses INTRC_IO, WDT, NOPROTECT, NOFCMEN, NODEBUG

#include "common.h" // Contains i2c addresses, some other shared globals
#use delay(clock=4000000)

// Configure I2C as HW master
#use i2c(MASTER, SCL=PIN_C3, SDA=PIN_C4, FORCE_HW, RESTART_WDT, SLOW)

volatile int1 update_i2c=0;

#define OPLIGHT PIN_B0

void main(void)
{
   delay_ms(100); // power up delay

   // Get to a roughly 1 second timer (with the irs counter)
   setup_timer_2(T2_DIV_BY_4,0xF9,8);

   enable_interrupts(INT_TIMER2);
   enable_interrupts(GLOBAL);

   // Initialize data   
   humid_act=0xff;
   temp_act=1;

   while(1)
   {
      if(update_i2c) // Wait for Timer2 to trigger the i2c event
      {
         i2c_start();
         i2c_write(FRONTEND_ADDR);
         i2c_write(temp_act);
         i2c_write(humid_act);
         i2c_stop();
         temp_act++; // Increment some debug/dummy data
         humid_act--; // These will be populated in production
         update_i2c=0; // Clear the timer flag
         output_toggle(OPLIGHT); //Toggle an LED
         delay_ms(10); // Maybe it's a timing thing?
      }
   }
}

#INT_TIMER2
void interupt_timer2(void)
{
   static int8    Timer2Ticks=0;

   Timer2Ticks++;
   if(Timer2Ticks%128==1) update_i2c=1;
}


SLAVE (16F690): Asside from the config stuff (included for context), most attention is needed in the IRS at the very bottom.
Code:

#include <16F690.h>
#device PASS_STRINGS=IN_RAM
#fuses INTRC_IO, NOPROTECT, NOFCMEN, NOBROWNOUT, NOMCLR, NOWDT, NOFCMEN
#include "common.h" // Contains the I2C addresses (0xA2 and 0xA4)
#use i2c(SLAVE, SCL=PIN_B6, SDA=PIN_B4, FORCE_HW, ADDRESS=FRONTEND_ADDR, SLOW, RESTART_WDT)
#use delay(clock=4000000)

#define EADOGM163       1
#define EADOGM_SPI_CS    PIN_C1
#define EADOGM_SPI_RS    PIN_C0
#define EADOGM_SPI_BB    1
#define EADOGM_SCLK_BB    PIN_C6 // C3 default for Bit Bang
#define EADOGM_MOSI_BB    PIN_C3 // C5 default for Bit Bang

#define OPLIGHT         PIN_C2
#define ALARM_LIGHT    PIN_C5
#define ALARM_PEIZO      PIN_C4

#define I2C_SCL       PIN_B6
#define I2C_SDA       PIN_B4

#define TEMP_ENC_CHAN_A PIN_A2
#define TEMP_ENC_CHAN_B PIN_A3
#define TEMP_ENC_SPST   PIN_A0
   
#include "EA-DOGM_SPI.c"
#include "encoders.c"

volatile int1 update_display=1;
volatile int1 update_setpoints=1;
volatile int1 update_actuals=0;
volatile int1 alarm_active=0;
volatile int1 alarm_cleared=0;
volatile int8 alarm_last=0;

#BIT SSPOV = 0xFC7.6     //Indicates overflow
#BIT BF = 0xFC6.0           //Buffer Full

BYTE state=0,address=0, trash=0; // some debug globals

void main(void)
{
   setup_oscillator(OSC_4MHZ);

   delay_ms(100); // power up delay

   set_tris_a(0b00111111);
   port_a_pullups(0b001111111);

   temp_set=read_eeprom(0x00);
   temp_set=min(temp_set,TEMP_MAX);  temp_set=max(temp_set,TEMP_MIN);

   humid_set=read_eeprom(0x01);
   humid_set=min(humid_set,HUMID_MAX); humid_set=max(humid_set,HUMID_MIN);

   eaDogM_Initialize();
   eaDogM_DisplayOn();
   eaDogM_SetPos(1,0);
   eaDogM_WriteString("??\xDF(  )  ??%(  )");

   setup_timer_2(T2_DIV_BY_1,0xFA,16);
   enable_interrupts(INT_TIMER2);
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   system_mode=ALARM_TEMP;
   while(1)
   {
      if(update_display)
      { // Data formatting display, to do...

              update_display=0;
      }
      if(update_actuals)
      {// This is mostly for debug at present, won't look like this in production
         eaDogM_SetPos(0,0); // Write out the debug state
         eaDogM_WriteChr(state/10+'0');
         eaDogM_WriteChr(state%10+'0');

         eaDogM_SetPos(0,3);// Write out the debug counter
         eaDogM_WriteChr(trash/10+'0');
         eaDogM_WriteChr(trash%10+'0');

         eaDogM_SetPos(1,0);      // Print temp_act
         eaDogM_WriteChr(temp_act/10+'0');
         eaDogM_WriteChr(temp_act%10+'0');
         eaDogM_SetPos(1,9);      // Print humid_act
         eaDogM_WriteChr(humid_act/10+'0');
         eaDogM_WriteChr(humid_act%10+'0');
         update_actuals=0;
      }
   }
}

#INT_TIMER2
void interupt_timer2(void)
{
   static int8    Timer2Ticks=0;

   Timer2Ticks++;
   if(Timer2Ticks==125) //This number is arbitrary for debugging. Tuned up later...
   {
      update_display=1;
   }
}

#INT_SSP
void ssp_interupt ()
{
   BYTE incoming;
   BYTE old_act1=0, old_act2=0; // Debug assistance for the counter

   state = i2c_isr_state();

   old_act1=temp_act;  // Debug assistance for the counter
   old_act2=humid_act;  // Debug assistance for the counter
   
   if(state <= 0x80)
   {
     incoming= i2c_read(); //how should read(0) and read(1) be correctly implemented in this situation?
         if(state == 1) temp_act  = incoming;
      else if(state == 2) humid_act = incoming;
   }
   if(state == 0x80)
   {
      i2c_write(temp_set);
      i2c_write(humid_set);
   }
   if(temp_act!=old_act1 || humid_act!=old_act2) trash++; // Update on change only (meaning I2C send data)

      update_actuals=1; // Trigger the main loop to update the LCD
   output_toggle(OPLIGHT); // visual evidence of IRS operating
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Aug 30, 2009 11:57 am     Reply with quote

Do some experiments.

Slave:
1. Disable the Timer interrupt in the Slave, so only the #INT_SSP
interrupt is operating.

2. Increase the oscillator frequency in the Slave to 8 MHz, so that
the slave is running faster than the master.

Master:
1. Disable the Timer interrupt in the Master.

2. Change the #use i2c() statement so the Master uses software i2c
instead of hardware.
Imaginos



Joined: 26 Aug 2009
Posts: 6

View user's profile Send private message

PostPosted: Sun Aug 30, 2009 7:23 pm     Reply with quote

Speeding up the slave to 8MHZ appears to have solved it (so did disabling the slave timer for that fact). I'm going to let it run overnight (and then maybe for a few days) to see if any other problems crop up.

Thanks for the help.
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