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 locking Clock low?

 
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 locking Clock low?
PostPosted: Mon May 07, 2007 9:24 am     Reply with quote

I have been testing a program for my device with an commerically purchased I2C reader/writer. I find that my code works well with the reader as long as i set the Maseter device to read 1 byte. (this is a user changable varible in the PC software for the reader). If i try to change it to have the master read 2 or more bytes, my PIC will hold the clock line low and will not release until i do a reset of the PIC. Does anyone have ideas what might be the issue?
Compiler 4.027

#include <16F819.h>
#device adc=10
#use delay(clock=4000000, RESTART_WDT)
#fuses WDT,INTRC_IO, PUT, MCLR, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG, NOPROTECT
#use i2c(MASTER,slow,sda=PIN_B2,scl=PIN_B5)
//#use i2c(SLAVE,Fast,sda=PIN_B1,scl=PIN_B4,address=0x16)
#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


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

int address;
char i,loop,int_count,bus_free,fault,change_current,chg_term=0,set=0;
int lsb_current,msb_current,count=0,lsb,msb;
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_rtcc
clock_isr()
{
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(0x0E); //absolute 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
}
////////////////////////////////////////////////////////////////////////////////
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
}
////////////////////////////////////////////////////////////////////////////////
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;
}
////////////////////////////////////////////////////////////////////////////////
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_capacity (void)
{
i2c_start(); //read capacity
i2c_write(0x16); //battery address
i2c_write(0x0F); //current register
i2c_start();
i2c_write(0x17); //tell battery to write data
lsb=i2c_read(); //read bytes
msb=i2c_read(0);
i2c_stop();
capacity=make16(msb,lsb); //combine into a word
output_float(SMBC_I); //release data line
output_float(SMBD_I); //release clock line
capacity=capacity/64;
}
////////////////////////////////////////////////////////////////////////////////
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;
}
////////////////////////////////////////////////////////////////////////////////
void read_sm_status (void)
{
i2c_start(); //read status
i2c_write(0x16); //battery address
i2c_write(0x2F); //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
}
////////////////////////////////////////////////////////////////////////////////
#int_ext
rb0_isr()
{
#use i2c(Master,slow,sda=PIN_B2,scl=PIN_B5) //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,fast,sda=PIN_B1,scl=PIN_B4,address=0x12,RESTART_WDT)
//change back to external smbus
}
////////////////////////////////////////////////////////////////////////////////
#INT_SSP
void ssp_interupt (void) //detect external smbus activity
{
BYTE incoming, state;

state = i2c_isr_state();
#use i2c(SLAVE,fast,sda=PIN_B1,scl=PIN_B4,address=0x12,RESTART_WDT)
if(state < 0x80) //Master is sending data
{
//incoming = i2c_read(1);

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 == 3) //third received byte is data
{
lsb_current = incoming;
//change_current=1;
}*/
}
if(state == 0x80) //Master is requesting data
i2c_write(lsb); //write first byte
// if(state > 0x80)
//i2c_write(msb); //write second byte
output_float(SMBC_E); //let go of clock line
output_float(SMBD_E); //let go of data line
}
////////////////////////////////////////////////////////////////////////////////
void write_sm_current (void)
{
#use i2c(MASTER,slow,sda=PIN_B2,scl=PIN_B5)
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,fast,sda=PIN_B1,scl=PIN_B4,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 main()
{
#use i2c(SLAVE,fast,sda=PIN_B1,scl=PIN_B4,address=0x12,RESTART_WDT)
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_4mhz);
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(0b00000001);

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


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
Code here that reads varibles and processes them. NOthing here that
will affect the issue i am seeing.

}
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon May 07, 2007 11:34 am     Reply with quote

Quote:
commerically purchased I2C reader/writer

What is this device ?
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Mon May 07, 2007 11:41 am     Reply with quote

It is an Aardvark I2C/SPI interface from TotalPhase. www.totalphase.com. At this point, I have been able to keep the my PIC from locking up by Clearing the SSPEN in the SSPCON1 and then setting it again, at the end of my IF(state==2) . It does not lock up anymore, but i am not sure if this is the best solution.

Thanks
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Mon May 07, 2007 11:43 am     Reply with quote

Sorry. I ment in the IF(state==0x80) in the INT_SSP interupte routine.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon May 07, 2007 11:50 am     Reply with quote

See if this errata on the SSP module for the 16F819 applies to your code:
http://ww1.microchip.com/downloads/en/DeviceDoc/80132f.pdf


Also I noticed that you have #use i2c Slave statements sprinkled in your
code, sometimes just a few lines apart. A #use i2c statement remains
in effect until another one seen. This is linear, from top to bottom in
the program. It's not done on a routine by routine basis. You should
clean this up.
nmeyer



Joined: 09 Jul 2004
Posts: 70

View user's profile Send private message

PostPosted: Mon May 07, 2007 11:57 am     Reply with quote

Thanks. I never thought that it might be an issue with the chip itself. It looks like that is what is causeing my problem and that i am doing what they suggest. Well, i think i have functional code now. Thanks for the sanity check.
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