|
|
View previous topic :: View next topic |
Author |
Message |
moacir_mendes
Joined: 10 Nov 2008 Posts: 2 Location: Brazil
|
i2c between 1 PIC16F877 master & 2 PIC16F873 slaves |
Posted: Mon Nov 10, 2008 7:37 pm |
|
|
I had a lot of problems during implementation of this circuit, more specifically with i2c protocol.
To get and send bytes between the master and one slave it works perfectly. But when I tried communicate with other slave PIC no one more communicate.
To solve this problem I do a test with SSPOV and BF bits, which indicates overflow on the buffer. If one of them are high I make it low.
#BIT SSPOV = 0x14.6
/*Indicates overflow - BIT 6 - SSPCON: SYNC SERIAL PORT CONTROL REGISTER (ADDRESS 14h)*/
#BIT BF = 0x94.0
/*Buffer Full - BIT 0 - SSPSTAT: SYNC SERIAL PORT STATUS REGISTER ADDRESS: 94h)*/
if (SSPOV || BF)
{
SSPOV = 0;
BF = 0;
}
The code is mess a bit, but it works fine
It may help someone with these problems.
Code: |
// -- SLAVE SOURCE CODE -- at address=0xA0
#include <16F873.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES PROTECT //Code protected from reads
#FUSES NOBROWNOUT //No brownout reset
#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 NODEBUG //No Debug mode for ICD
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(SLAVE,sda=PIN_C4,scl=PIN_C3,address=0xA0, force_hw)
#BIT SSPOV = 0x14.6 //Indicates overflow
#BIT BF = 0x94.0 //Buffer Full
BYTE state, address, buffer[0x08]; // address and array of Bytes, change size to suit your needs
int valvula = 0;
int temp;
#INT_SSP NOCLEAR
void ssp_interupt ()
{
clear_interrupt(int_SSP);
state = i2c_isr_state();
if(state < 0x80) //master is sending data
{
if(state == 0)
{
}
if(state == 1) //first received byte is address
{
address = i2c_read();
}
if(state == 2) //second received byte is data
{
buffer[address] = i2c_read();
}
}
if(state == 0x80) //master is requesting data
{
i2c_write (buffer[address]); //send requested data
}
}
void main()
{
set_tris_c(0xFF);
enable_interrupts(INT_SSP); //enable I2C interrupts
enable_interrupts(GLOBAL);
output_low(pin_a0);
output_low(pin_a1);
buffer[0x00] = 0b10000000;
buffer[0x01] = 0b10000001;
buffer[0x02] = 0b01000010;
buffer[0x03] = 0b01000011;
buffer[0x04] = 0b00100100;
buffer[0x05] = 0b00100101;
buffer[0x06] = 0b00010110;
buffer[0x07] = 0b00010111;
while(TRUE)
{
delay_ms(100);
if (SSPOV || BF)
{
output_high(pin_a0);
SSPOV = 0;
BF = 0;
}
else output_low(pin_a0);
if (BF) output_high(pin_a1);
else output_low(pin_a1);
if (!input(pin_b0)){
SSPOV = 0;
BF = 0;
}
if (address == 23)
{
valvula = !valvula;
if (valvula) printf("VALVE ACTIVATED\n\r");
else printf("VALVE DEACTIVATED \n\r");
address = 0x14;
}
}
}
|
// -- MASTER SOURCE CODE -- Sends to 0xA0 and 0xB0
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES WRT_50% //Lower half of Program Memory is Write Protected
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(MASTER, sda=PIN_C4,scl=PIN_C3, force_hw)
BYTE data = 0b00001111 /*15*/, result = 0, n;
#define end_1 0xA0 //FIRST SLAVE
#define end_2 0xB0 //SECOND SLAVE
BYTE recebe_i2c(BYTE end_disp, BYTE end_mem)
{
BYTE result2 = 0;
i2c_start (); //begin communication
i2c_write (end_disp); //send slave address
i2c_write (end_mem); //request slave internal memory address for analogue data
i2c_stop(); //stop write cycle to shift to read cycle
i2c_start (); //send repeated start command to begin read cycle
end_disp++;
i2c_write (end_disp); //add 1 to the address to send a write bit
result2 = i2c_read(0); //read analogue information from the slave
i2c_stop (); //terminate communication
delay_ms(10);
return result2;
}
void envia_i2c(BYTE end_disp, BYTE dado)
{
i2c_start(); //begin transmission
i2c_write(end_disp); //select address of device to communicate with
i2c_write(dado); //send actual data
i2c_stop(); //terminate communication
delay_ms(10); //debouncing delay
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_timer_0(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);
// TODO: USER CODE!!
set_tris_b(0xFF);
set_tris_c(0b10111111);
while(TRUE)
{
if(!input(PIN_B0))
{
for (n = 0; n <=7; n++)
{
result = recebe_i2c(end_1, n);
printf("BYTE %u: %u \n\r", n, result);
}
printf("-------------------------------------\n\r");
delay_ms(200);
}
if(!input(PIN_B6))
{
for (n = 0; n <=7; n++)
{
result = recebe_i2c(end_2, n);
printf("BYTE %u: %u \n\r", n, result);
}
printf("-------------------------------------\n\r");
delay_ms(200);
}
if(!input(PIN_B3))
{
envia_i2c(end_1, 23);
delay_ms(200);
}
if(!input(PIN_C0))
{
envia_i2c(end_2, 23);
delay_ms(200);
}
}
} |
|
|
|
Salenko
Joined: 08 Sep 2008 Posts: 84
|
|
Posted: Tue Mar 31, 2009 2:03 am |
|
|
hi moacir_mendes,
thank you very much, your code is very useful.
I have a question, why the code don't work when I add Fast to the both #use_i2c( ) (master and slave) ?
in fact, I need a fast i2c communication because I have a PIC Master and three slaves : a PIC (16F876), an External EEPROM (24C256) and an RTC (DS1307). |
|
|
moacir_mendes
Joined: 10 Nov 2008 Posts: 2 Location: Brazil
|
|
Posted: Wed Apr 08, 2009 7:35 pm |
|
|
Salenko wrote: | hi moacir_mendes,
thank you very much, your code is very useful.
I have a question, why the code don't work when I add Fast to the both #use_i2c( ) (master and slave) ?
in fact, I need a fast i2c communication because I have a PIC Master and three slaves : a PIC (16F876), an External EEPROM (24C256) and an RTC (DS1307). |
Hi!
Good question Salenko. I don't know too. I read it doesn't works at this way.
i think at the normal i2c communication should be enough between them, doesn't? |
|
|
ebenbekker
Joined: 02 Sep 2009 Posts: 4
|
|
Posted: Wed Sep 02, 2009 3:43 pm |
|
|
How can you edit the code given by the original poster to send packets of 8 bytes to the client?
I try to hack it so that the master can write to a buffer on the slave all the instructions needed. So far all my attempts disabled all i2c comms.
Thank you very much.
Eben |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Sep 05, 2009 2:21 pm |
|
|
It's better to ask general questions in the main forum. Most people that
post in the Code Library do not want to make modifications to their code.
Also, the main forum is more widely read every day. You have a much
better chance of getting some help there. |
|
|
cnrszr
Joined: 11 Mar 2010 Posts: 1
|
|
Posted: Thu Mar 11, 2010 10:22 am |
|
|
this program works good within proteus simulation. Unfortunatly when i read 8 byte from first slave adress 0xA0 master gets data correctly. But when pressed other button and wanna get 8 byte from other slave adress 0xB0 then false values 255,255,... comes then. After that no more correct data reading and sending to the slave is possible. There is missing something, because of this i think switching between slaves is not possible. |
|
|
gammi,grt
Joined: 17 Jul 2012 Posts: 2
|
|
Posted: Thu Jul 26, 2012 2:40 am |
|
|
Hi, I am trying i2c between two pics. I am using 16f877a as a master device and 16f88 as a slave device. So for slave device we need to know the address of pic16f877. So please anybody can tell me address of pic16f88. Thanks. |
|
|
|
|
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
|