![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
johnbravado
Joined: 07 Apr 2010 Posts: 11
|
i2c help pic16f886 |
Posted: Wed Apr 07, 2010 3:18 pm |
|
|
I am using a pic16f886 and can use some help. I have read extensivly the posts about this subject and nothing seems to work. I am trying to do i2c communication between 2 pics.
Code is listed below. I have tried force_hw in the #use i2c() statement. I have tried fast and slow there. I have tried putting delays in all sorts of places. Best I can deduce from the testing I have done is this.
During the initial call, or some call, the slave registers i2c_isr_state() as equal to zero, or I am the unit you wish to write to. It then locks up. I can get no other blinky light action to happen on either end. The master and the slave lock up. I cannot find when the slave locks up, but the master continues through the code until it reaches the part where it waits for a response. The slave never receives another SSP interrupt signal as through testing it only enters the interrupt function once. This could be because it may never leave the interrupt or it never returns to it. I think it never leaves it do to some other testing. I have got to be missing something simple but this is my first attempt at i2c communication and and to me logically it should work.
I also am assuming that CCS C compiler sends acklowedges with read command and then waits to receive an acklowedge at the end of every write command.
Also, since i2c protocol requires a start signal sent, then the address you wish to communicate with with 1 for read or 0 for write appended to it, i tried to do the following and it did not work
Code: |
address = 0x22;
address <<= 1;
start();
i2c_write(address);
i2c_write(data);
i2c_stop();
address++;
i2c_start();
i2c_write(address);
response = i2c_read(0);
i2c_stop();
|
Any help would be most appreciated.
thank you
/***SLAVE***/
Code: | #use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Slave,slow,sda=PIN_C4,scl=PIN_C3,address=0x22)
#int_SSP
void SSP_isr(void)
{
BYTE state, incoming;
state = i2c_isr_state();
if(state <= 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 0){
}
if(state == 1){ //First received byte is address
address = incoming;
}
if(state == 2){ //Second received byte is data
readData = incoming;
}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(address);
}
}
void main(void){
enable_interrupts(INT_RTCC);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
set_tris_c(0xBF);
while(1){}
}
|
/***MASTER***/
Code: |
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3)
void sendI2Cdata(void){
BYTE data;
BYTE ad2;
BYTE response;
ad2 = 0x22;
data = 0xFA;
i2c_start();
i2c_write(ad2);
i2c_write(data);
i2c_stop();
delay_ms(250);
ad2++; //add 1 for read
i2c_start();
i2c_write(ad2);
response = i2c_read(0);
i2c_stop();
delay_ms(250);
if(response == 0x22){
blinkRed(5);
}else if(response == 0xFA){
blinkGreen(5);
}else{
oscillate(5);
}
}
void main(void){
enable_interrupts(INT_RTCC);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
set_tris_c(0xBF);
while(1){
if(!input(PIN_A0)){
delay_ms(25);
if(!input(PIN_A0)){
while(!input(PIN_A0));
output_low(PIN_B4);
sendI2Cdata();
output_high(PIN_B4);
}
}
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 07, 2010 3:39 pm |
|
|
Explain what you're trying to do, in terms of the overall communcation
protocol.
For example, the CCS Ex_Slave.c program emulates a 16-byte eeprom.
To write to it, you send the Slave address, followed by the "eeprom"
address, and then finally you send the data byte.
To read, you send the Slave address (with read bit set), followed by
the "eeprom" address. Then you read the data byte from the slave.
In the same way, describe what you want to do.
Quote: | /***MASTER***/
enable_interrupts(INT_SSP); |
Also, explain why you are enabling #int_ssp interrupts in the master.
What purpose can that have ?
Also, why are interrupts enabled (INT_SSP and INT_RTCC) when there
are no interrupt service routines for these interrupts ? |
|
![](templates/subSilver/images/spacer.gif) |
johnbravado
Joined: 07 Apr 2010 Posts: 11
|
|
Posted: Wed Apr 07, 2010 4:03 pm |
|
|
I want chip A to send a byte that is a question, ie if chip B receives 0xFA from chip A, chip B will respond with 0x32. It is for status verification and monitoring. For this code though I just want chip A to send a command, chip B receive it and then respond with the command that was written to it so I can make sure communication works.
Why I have the interrupt in the master. I used the CCS wizard and it added it. I just didn't delete it.
I was using the ex_Slave as my slave guide, I just adjusted the send data part to use the first byte of data instead of the second like the example shows. Should have worked fine on the slave end. I also just tried to send 0XFA instead of a variable and that didn't work either.
From best I read on the i2c_isr_state(), it basically states, 0 = address matches and the next command is a write. 1-7F are following commands. 0x80 is address matches and read. So the only thing you should put in the 0x80 section is i2c_write(data);. |
|
![](templates/subSilver/images/spacer.gif) |
johnbravado
Joined: 07 Apr 2010 Posts: 11
|
|
Posted: Wed Apr 07, 2010 5:14 pm |
|
|
Thank you all for reading and responding with what you did. Got it working now. In all my testing i never got things sorted out just right. In the master program i need to do a i2c_read(0) command, which i tried multiple times, and in the slave int_ssp isr i needed to remove the incoming = i2c_read() from doing it every time. And only do it during calls to 1-7F. seems doing it during when i2c_isr_state() == 0 || 80 fails even though in the examples provided by CCS it says that you need to do it every time. The ex_slave doesn't do it when i2c_isr_state() == 80, but if you look on the web, you will find an updated version of that file they adjusted in order to fix some sort of bug.
Anyways thanks |
|
![](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
|