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

i2c help pic16f886

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



Joined: 07 Apr 2010
Posts: 11

View user's profile Send private message

i2c help pic16f886
PostPosted: Wed Apr 07, 2010 3:18 pm     Reply with quote

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);
         }
      }
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 07, 2010 3:39 pm     Reply with quote

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 ?
johnbravado



Joined: 07 Apr 2010
Posts: 11

View user's profile Send private message

PostPosted: Wed Apr 07, 2010 4:03 pm     Reply with quote

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);.
johnbravado



Joined: 07 Apr 2010
Posts: 11

View user's profile Send private message

PostPosted: Wed Apr 07, 2010 5:14 pm     Reply with quote

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
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