View previous topic :: View next topic |
Author |
Message |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
No ACK from slave when sending data with I2C |
Posted: Tue May 09, 2006 12:49 pm |
|
|
Hi!
I´m using the code below to send two bytes of data from one master-PIC to a slave-PIC. As you might have guessed...it doesn´t work. When I measure the signal with an oscilloscope I can see that there´s no ACK from the slave after the address have been sent. Nor after the two following data-bytes... The result is that the slave of course never enters the ISR, which sucks... :-)
Can someone please give me a reason why this problem occurs?!!
MASTER-CODE
==========
Code: | #include <i2c_test.H>
#fuses NOWDT
#use i2c(master,sda=PIN_C4,scl=PIN_C3,FORCE_HW)
void send_to_slave() //I2C-funktion
{
i2c_start();
if(i2c_write(0x00)) //address to slave
{
i2c_write(0x51); //data1
i2c_write(0x1B); //data2
}
i2c_stop();
}
main()
{
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_port_a(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
set_tris_c(0x00);
while(1) //test-loop
{
delay_ms(1000);
send_to_slave();
}
} |
SLAVE-CODE
=========
Code: | #include <i2c_test.H>
#fuses NOWDT
#use i2c(slave,sda=PIN_C4,scl=PIN_C3,address=0x00,force_hw)
int16 temp;
byte received;
typedef enum {FIRST_READ, LAST_READ} I2C_STATE;
I2C_STATE i2c_status=FIRST_READ;
#int_ssp
receive_isr()
{
port_d ^= 1; //indicator (reaching ISR?)
if(i2c_poll())
{
if(i2c_status==FIRST_READ)
{
received=i2c_read();
temp=received;
i2c_status=LAST_READ;
}
else if(i2c_status==LAST_READ)
{
received=i2c_read();
temp=(temp<<8)&0xFF00;
temp=temp+received;
i2c_status=FIRST_READ;
}
}
}
main()
{
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_port_a(NO_ANALOGS);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
set_tris_d(0x00); // PORT-D: all output
set_tris_c(0xFF); // PORT-C: all input
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
} |
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Tue May 09, 2006 2:27 pm |
|
|
You send an address of '0x51'. This has the low bit set, which means that the master is expecting to _read_ data. You then write data. The I2C_ISR_STATE variable, will be 0x80 after the first transaction (since the read bit is set), and your handler will therefore never call the read function to access the address, hence there is no acknowledge...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue May 09, 2006 2:33 pm |
|
|
In your slave add an endless loop at the end of main(). Now it will execute the sleep instruction that CCS puts there and then stop.
Tip: In the SSP interrupt routines you don't have to call i2c_poll(). You will only enter the interrupt when a character was received so calling the i2c_poll function will always return TRUE. |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
wrong... |
Posted: Tue May 09, 2006 3:06 pm |
|
|
The adress that I send is not 0x51, but 0x00. 0x51 is the first byte that I´m sending... |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
and... |
Posted: Tue May 09, 2006 3:08 pm |
|
|
...I forgot the endless loop. But it doesn´t make any difference. There´s still no ack from the slave... |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 09, 2006 3:29 pm |
|
|
You're using the General Call address of 0x00. Support for this
address has to be specifically enabled by setting the GCEN bit
This is a special address and is not normally used.
From the 16F877 data sheet:
Quote: |
The general call address is recognized when the General Call
Enable bit (GCEN) is enabled (SSPCON2<7>). |
My suggestion is to use the CCS example file for an i2c slave:
EX_SLAVE.C
You can find this file in: c:\Program Files\PICC\Examples |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
...still not working |
Posted: Wed May 10, 2006 3:21 am |
|
|
Hi again!
Changed to address 0x6C and the slave still doesn´t pull down to data-connection (ACK)....and yes, I´ve modeled the slave code after the "ex_slave.c" code-example...
/David |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed May 10, 2006 3:37 am |
|
|
Remember, that you still have to read the address. You are sending an address, then two data bytes, but only have two read functions. As I originally said (though for the wrong reason :-), part of the problem is that your reads, and writes don't match up. If GCEN is enabled, there will then be a second problem from this...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
but.... |
Posted: Wed May 10, 2006 3:43 am |
|
|
ok, good point......but still, the fact remains that the slave-PIC doesn´t even enter the ISR.... I tried putting the i2c_read()-function in the enternal while-loop in the main-program, but that did not make any difference att all.... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed May 10, 2006 4:11 am |
|
|
Which is then probably the general call problem.
The general call address, is _permanently_ decoded by the PIC. It is always 'special'. The GCEN bit, determines whether the PIC will respond to this address. Assuming that the general call 'logic', has a higher priority than the normal address decode logic, then if a general call address is seen, and GCEN is not enabled, the chip will not interrupt...
The GCEN detect logic, is not shown in MicroChip's data sheet, but I'd always avoid this address, unless you are enabling GCEN yourself, and have a modified handler to deal with it.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
ok... |
Posted: Wed May 10, 2006 4:39 am |
|
|
...but as I said, right now I´m using the address 0x6C. This seems like a quite "normal" address, right? And the GCEN-bit is cleared right now...
If I´ve understood everything, the hardware will automatically acknowledge each byte sent....but it just doesn´t. I´m watching the data-pin with an oscilloscope and I can see that the slave doesn´t pull down the signal after the address-byte has been sent, which means there´s no ACK...
Thank you so far by the way :-) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed May 10, 2006 6:28 am |
|
|
What is 'true' in C?.
You test I2C_WRITE, before sending the following bytes. What logic does I2C_Write use?.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
0=ACK |
Posted: Wed May 10, 2006 6:53 am |
|
|
...so once again you´ve made a pretty good point. Since the SLAVE does´t ACK the address-write (which is the same as the test-write), the i2c_write()-function returns TRUE=1 and sends the two data-bytes.
But this does not change the fact that the i2c-hardware in the SLAVE-pic doesn´t ACK the address-write at all.... |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Wed May 10, 2006 7:37 am |
|
|
What is the slave doing when it runs?. Hint: Unlike on a PC, there is no 'OS' for the chip to drop back to, when it exits the 'main' routine.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
davey
Joined: 04 May 2006 Posts: 17 Location: Sweden
|
I know the while(1); statment is missing in the slave-code.. |
Posted: Wed May 10, 2006 8:24 am |
|
|
...I inserted it after I posted the message on this forum. But the problem still remained.... |
|
![](templates/subSilver/images/spacer.gif) |
|