![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
rudy
Joined: 27 Apr 2008 Posts: 167
|
I2C Over 16F690 x 16F877a |
Posted: Sun Feb 05, 2012 4:17 pm |
|
|
Hi all.
I used to have a pretty good routine to interface two 16F877A, one as i2c master and the other one as slave. Now I need to put one 16F690 in the game, and I simply cannot put my slave routine to work on the 16F690.
Code: |
#INT_SSP
void SSP_isr()
{
state=i2c_isr_state();
if(state>=0x80)i2c_write(buffer[state-0x80]);
else if(state>0)buffer[state-1]=i2c_read();
if(state==0x07)i2c_message=1;
}
|
It simply don't work, is it possible that the ENHANCED UART of 16F690 is doing something that I can't figure out?
Please help me.
Regards. |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1331
|
|
Posted: Sun Feb 05, 2012 6:50 pm |
|
|
I'm pretty surprised that work for two reasons:
1. Your not reading when state == 0x00 and you should
2. Your not reading when state == 0x80 and you should
You want something like (untested mind you):
Code: |
if(state <= 0x80){ //reads incoming data
buffer[state]=i2c_read(); //I changed state-1 to just state for now
}
if(state >= 0x80){ //writes incoming data
i2c_write(buffer[state-0x80]);
}
if(state == 0x07){
i2c_message=1;
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
rudy
Joined: 27 Apr 2008 Posts: 167
|
|
Posted: Mon Feb 06, 2012 3:01 pm |
|
|
Hi.
It is not working....
I made the following changes:
Code: |
#INT_SSP
void SSP_isr()
{
state=i2c_isr_state();
if(state <= 0x80) //reads incoming data
{
buffer[aux]=i2c_read(); //I changed state-1 to just state for now
aux++;
}
if(state >= 0x80) //writes incoming data
{
i2c_write(buffer[state-0x80]);
}
if(aux == 0x07)i2c_message=1;
}
|
Then, when the i2c_message flag is set, I turn off the SSP interruptin and put the buffer in eeprom, to analize after.
I can only see 0x04 in all eeprom addres, that is the slave address.
The data I am sending from master are:
{0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07}
I am pretty shure that the 0x04 value in eeprom is the slave adress, because I changed to 0x02, and the value in eepron becomes all 0x02.
I really don´t know what is going wrong. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19388
|
|
Posted: Mon Feb 06, 2012 3:43 pm |
|
|
Remember if you send 8 bytes, there will be _9_ reads necessary. The first byte received by I2C, is the device address. So you should receive:
address, 0, 1, 2, 3, 4, 5, 6, 7
Your read will therefore terminate one byte early, and the next time you enable the interrupt (you should really leave it enabled....), the device will interrupt immediately, for the extra byte, and be out of sync from then on.
The UART has nothing to do with SSP.
The 16F690, only has an SSP module, not an MSSP module, but this shouldn't affect slave operation (it doesn't support master operation in the hardware).
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
rudy
Joined: 27 Apr 2008 Posts: 167
|
|
Posted: Mon Feb 06, 2012 4:29 pm |
|
|
Hi,
Yes I know, something is really strange. My suspicion is that, I don't know why yet, the state doesn't change. i2c_isr_state(); is always equal to zero.
I start to think that the slave clock speed is wrong, although I use clock=4000000, I will check and revert back again.
Best regards |
|
![](templates/subSilver/images/spacer.gif) |
rudy
Joined: 27 Apr 2008 Posts: 167
|
|
Posted: Mon Feb 06, 2012 6:23 pm |
|
|
Hi.
It is finally perfect.
Code: |
void SSP_isr()
{
state=i2c_isr_state();
if(state > 0 && state <= 0x80)
{
buffer[i2c_count]=i2c_read();
i2c_count++;
}
if(state > 0x80)i2c_write(buffer[state-0x80]);
if(i2c_count == 0x03)
{
i2c_message=1;
i2c_count=0;
disable_interrupts(INT_SSP);
}
}
|
In fact, the code was right, the only mistake was:
Code: |
.
.
.
.
if(state <= 0x80) //reads incoming data
.
.
.
if(state >= 0x80) //writes incoming data
.
.
|
As you can see, <= 0x80 and >= 0x80, "equal" at the same time.
So I give up state = 0, this is the address match condition, and it means nothing to me in this simple application.
I really don´t need this line even;
Code: |
.
.
if(state >= 0x80) //writes incoming data
.
.
|
I discovered that I cannot go FAST, but when I use SLOW directive, it is pretty fine. This may be because of the strong capacitance of the wires in my protoboard, when I get the PCB, I will give another try to go FAST.
Best regards, and thanks to all friends. |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1331
|
|
Posted: Mon Feb 06, 2012 9:13 pm |
|
|
That actually surprises me. The <= and >= overlapping was on purpose. I haven't done I2C in a while, but I thought you had to do i2c_read() when state==0 and that you should i2c_read() and i2c_write() when state ==0x80. It surprises me that you don't have to now, but again, I haven't messed with I2C in a while. |
|
![](templates/subSilver/images/spacer.gif) |
rudy
Joined: 27 Apr 2008 Posts: 167
|
|
Posted: Tue Feb 07, 2012 4:41 am |
|
|
Yes you can.
I made a lot of tests, always stopping SSP ISR and recording the values on eeprom. When state==0, it means that you match the slave address only, the others bytes that follows address, drive state to be different them zero, that´s why I just jump over state == 0, because this is a simple routine, I just want to send three bytes of data to a slave, them it automatic update the ports states, and consequently, the relays attached to them.
Thanks anyway, your tip was very much appreciated, it make start to understand what was wrong in my original code.
Regards. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|