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

16F88 I2C master (software) and 16F88 Slave (hardware)

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







16F88 I2C master (software) and 16F88 Slave (hardware)
PostPosted: Tue Sep 18, 2007 7:02 am     Reply with quote

Hello:


I've been looking for some days a solution for my I2C communication problem between two PIC16f88 Pics but I've found nothing to solve i yet so I decided to expose my problem.


As I said, there is a master PIC16F88 (software master) and other same pic as hardware slave. I'm tying to send a byte from master to slave but meanwhile the SPI (I2C) interrupt works fin I can't receive nothing. I can see that the state = i2c_isr_state() returns always 128 decimal.


My master code is as simple as this:

#use delay(clock=8000000)
#use i2c(Master,sda=PIN_B1,scl=PIN_B4,slow)

void main ()
{

reset_variables();

While(1)
{
mandar_codigo();

}
}

void reset_variables()
{

setup_adc_ports(sAN0|sAN1|sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL /*ADC_CLOCK_DIV_2*/);
setup_timer_0(T1_DISABLED /*RTCC_INTERNAL|RTCC_DIV_1*/);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);

DISABLE_INTERRUPTS(GLOBAL);
#asm
MOVLW 0b00111011; //Module enable, clock
MOVWF 0x14; //SSPCON
#endasm
}
i2c_start();
delay_us(100);
i2c_write(0xA0);
delay_us(100);
i2c_write(0xAA);
delay_us(100);
i2c_write(0x55);
delay_us(100);
i2c_stop();

delay_ms(2000);
}


And the slave code is the next one:


#use delay(clock=8000000)

#use I2C(slave,SDA=PIN_B1,SCL=PIN_B4,force_hw,slow,address=0xAA)

BYTE a;
BYTE address, buffer[0x10];

#INT_SSP
void i2c_isr ()
{
BYTE incoming, state;

clear_interrupt(INT_SSP);
disable_interrupts(GLOBAL);
disable_interrupts(INT_SSP);

state = i2c_isr_state();

if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
if(state == 2) //Second received byte is data
buffer[address] = incoming;
}
if(state == 0x80) //Master is requesting data
{
i2c_write(buffer[address]);
}
}

void main ()
{

reset_variables();

While(1)
{
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}


void reset_variables()
{

setup_adc(ADC_CLOCK_INTERNAL);
setup_adc(ADC_OFF);
setup_spi(SPI_SLAVE|SPI_L_TO_H);
setup_timer_0(T1_DISABLED);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_ccp1(CCP_OFF);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ);

// HAY UN ERROR EN EL DATASHEET DEL 16F88 PARA CONFIGURAR
// EL I2C. LO ARREGLAMOS PONIENDOLO A MANO
#asm
MOVLW 0b00111110 ;Module enable, clock, 7 bits
MOVWF 0x14; //SSPCON
#endasm
clear_interrupt(INT_SSP);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 18, 2007 12:03 pm     Reply with quote

Don't use your code for the first test. See this post:
http://www.ccsinfo.com/forum/viewtopic.php?t=30905&start=3
Ttelmah
Guest







PostPosted: Tue Sep 18, 2007 1:21 pm     Reply with quote

The reason it doesn't work, is the slave is never addressed.
The address must be the first byte after the start. You are sending 'A0', while the slave has an address of 'AA'. Therefore there is never an address match.

Best Wishes
itzalak
Guest







PostPosted: Fri Sep 21, 2007 4:22 am     Reply with quote

I've tryed everything but nothing goes fine. I've used avery simple master code as you told. The slave cod is the ccs example code little bit modified for the pic16f88.

The firs thing I can see is that the interrupt occurs, ok. Then I dissable global and SPI interrupt at the first line. In main code I put on those again but the pic needs "a lot of time" to do an interrpt again, sometimes incusive some seconds. As I'm looking the sending data in the scope I think there is a problem on "interrupt secction".

The data received in (watching in debug mode) is only sometimes ok, but only afew times.



void main ()
{

reset_variables();

While(1)
{

mandar_codigo();

}
}


void reset_variables()
{

setup_adc_ports(sAN0|sAN1|sAN3|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL /*ADC_CLOCK_DIV_2*/);
setup_timer_0(T1_DISABLED /*RTCC_INTERNAL|RTCC_DIV_1*/);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);

DISABLE_INTERRUPTS(GLOBAL);

}

void mandar_codigo()

{

// Write the letter 'B' to the slave board.
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_write('B');
i2c_stop();

delay_ms(2000);

}

The 16F88.h library:

#include <16F88.h>
#device ICD=TRUE
#device adc=10

#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc
#FUSES NOPUT //No Power Up Timer
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOBROWNOUT //Reset when brownout detected
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled

#use delay(clock=8000000)
#use i2c(Master,sda=PIN_B1,scl=PIN_B4)

And the slve code:


#if defined(__PCM__)
#include <16F88.h>
#device ICD=TRUE
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,INTRC_IO
#use delay(clock=8000000)

#elif defined(__PCH__)
#include <18F88.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP,INTRC_IO
#use delay(clock=8000000)
#endif


#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, FORCE_HW, address=0xA0)

void reset_var();

unsigned int8 address=0;

BYTE buffer[0x04];

#INT_SSP
void ssp_interupt ()
{
BYTE incoming, state;

state = i2c_isr_state();

if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
if(state == 2) //Second received byte is data
buffer[address] = incoming;
}
if(state == 0x80) //Master is requesting data
{
i2c_write(buffer[address]);
}
}


void main ()
{
reset_var();

while(1)
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
}
}

void reset_var()
{
unsigned int8 i=0;

for (i=0; i<0x04; i++)
buffer[i]=0;


}



Any idea?


Thanks a lot for all your 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