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 routine giving FF's or lockin UP?

 
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 routine giving FF's or lockin UP?
PostPosted: Tue Jun 05, 2007 9:07 am     Reply with quote

I have been working with the !2C routines and i generated the following code. In most cases it works fine, but we have found that it will return bad data, such as FF or 00 when reading. This is a PIC16F819 set up in a slave mode. Sometimes, the I2C will even lock up totally and not respond, with the only way to get it to work again is reseting the PIC. I have stripped my program down to just the I2C and this still is having problems, so it seems to be resident in how it is set up. Does anyone have any ideas what may be causing this?
Compiler PCW 4.027
Code--

#include <16F819.h>
#device adc=10
#use delay(clock=8000000, RESTART_WDT)
#fuses WDT,INTRC_IO, PUT, MCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT
#use i2c(SLAVE,FORCE_HW,fast,sda=PIN_B1,scl=PIN_B4,address=0x12,RESTART_WDT)
#include <math.h>

#use fast_io(A)
#define LED1 PIN_A0 //100% led
#define LED2 PIN_A1 //80% led
#define LED3 PIN_A2 //60% led
#define LED4 PIN_A3 //40% led
#define LED5 PIN_A4 //10-20% led, yellow
#define LED6 PIN_A6 //below 10% or fault led, red

#use fast_io(B)
#define sw_in PIN_B0 //switch
#define SMBD_E PIN_B1 //smbus data external
#define SMBD_I PIN_B2 //smbus data internal
#define SMBC_E PIN_B4 //smbus clock external
#define SMBC_I PIN_B5 //smbus clock internal

#define INTS_PER_SECOND 15
#BYTE SSPCON1 = 0x14




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

int address,lsb_ch_crnt,lsb_cap;
char i,loop,int_count,bus_free,fault,change_current,chg_term=0,set=0;
int lsb_current,msb_current,count=0,lsb,msb,lsb_temp,lsb_volt,lsb_status;
long time1,seconds,voltage,percent,status,temperature,capacity,ch_current;
long time_cnt=0,value;
int32 new_val;
signed long current;
signed int i2c_temp;


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

state = i2c_isr_state();

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
{
lsb=lsb_status;
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 main()
{
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_adc(ADC_CLOCK_DIV_8);
setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
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(0b00000000);
set_tris_b(0b00010011);

int_count=INTS_PER_SECOND; //used for timer
seconds=0; //clear out variable
time1=15; //counter for time,30 seconds

lsb_status=0x21;
lsb_volt=0x22;
lsb_temp=0x24;
lsb_cap=0x28;
lsb_ch_crnt=0x34;



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

delay_us(5);


}
}
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 12:40 pm     Reply with quote

Make sure your Master isn't trying to send commands faster than the Slave can handle them. Try putting some delays, in your Master code, to see if that helps. I've had issues where this was happening and needed to slow my Master code down a bit to give the Slave time to do it's thing.

Ronald
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Tue Jun 05, 2007 4:06 pm     Reply with quote

Unfortuanately the Master is not my device. I have talked to the engineer who is designing it, and we can do delays, but at this point I am not sure what type of delays to have. I have tried several things there and it still has problems, even with millisecond delays. I do think this is the root cause of my problem, it seems as if the I2C is missing the calls to the interrupt.
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Wed Jun 06, 2007 8:34 am     Reply with quote

Put a scope on your bus signals and try to see what they are doing. Capture them and compare them to what they should look like. This can be extremely helpful. Also, try pulsing an extra output, during your Slave ISR, to compare how the two devices are syncing up. A probe on each bus signal plus the pulsed output will show you if you need the Master to put delays in.

Ronald
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Thu Jun 07, 2007 6:54 am     Reply with quote

The more i look at this I do not think the delay is the main issue. It seems to be very random and even after delays from the master that i would think are acceptable. I know that this part has errata from Microchip on the SSP module, and i though i had added code to take care of it, but now i am not sure.
Peter-NMB



Joined: 17 Sep 2003
Posts: 11
Location: Glasgow, Scotland

View user's profile Send private message

PostPosted: Thu Jun 07, 2007 10:30 am     Reply with quote

Does your lock up occur when you plug up your smart battery to your smart battery selector and you are trying communicate with it straight away.

When you say lock up, do you mean that your clock line is being held low constantly, which is occuring after plug up of the smart battery.

Also when you receive your data with the I2C interrupt, should you not stretch the clock to allow you time to process the data for loading up the outgoing register in case the master is trying to continue to clock.
bit_clear(PIC_SSPCON1, 4); // hold clock low
and then release after processing/ loading up I2C buffer etc
bit_set(PIC_SSPCON1, 4); // release clock to master
so the master can clock out the data
tatokash



Joined: 08 Aug 2007
Posts: 6

View user's profile Send private message

Re: I2C routine giving FF's or lockin UP?
PostPosted: Wed Aug 08, 2007 9:30 am     Reply with quote

In a past project I used the watch dog timer to recover from the I2C lockup that occurs int the PIC16F818/F819.

I used interrupts to catch an SSP interrupt and looked for I2C events. I checked the SSPSTAT register and only reset the watch dog during valid I2C events. If there was no valid I2C event, I continuously looped without resetting the watchdog so that it eventually reset the PIC.

On reset I checked the POR bit to see if the watchdog had reset and if so, continued on without restarting the whole program.

Bulletproof in my application. Hope it helps you.
_________________
Don't ever stop learning...
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