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 support@ccsinfo.com

One more I2C

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



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

One more I2C
PostPosted: Sat Feb 26, 2005 12:47 pm     Reply with quote

I know not another one...

I tried to make my routines as simple as i can and go from there, I have a master (819) sending 0x44 to the slave (877a) and the slave just gets the data and prints it to the serial port, simple right?

1. Hold reset on both
2. Release reset on slave and it prints Running...
3. Release reset on master and slave starts recieving address and data and prints them both on the screen as so:

Running...
Address: 02
Data: 43
Address: 02
Data: 43
Address: 02
Data: 43

which is correct.

I can reset the master all day long and the slave still puts on the correct data, now if i hit reset on the slave it never works again till I get both reset. It will just print 02 for address and data.

I'll assume first off I'm doing something stupid and go from there.

Master
Code:

#include <16F819.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define EEPROM_SDA  PIN_B1
#define EEPROM_SCL  PIN_B4
#use i2c(MASTER, SDA=EEPROM_SDA, SCL=EEPROM_SCL)

void main()
{
   int i2c_command = 0x43;

   output_float(EEPROM_SCL);
    output_float(EEPROM_SDA);

   while (true)
   {
      delay_ms(1000);

      i2c_start();

      i2c_write(0x02);

      i2c_write(i2c_command);

      i2c_stop();
   }
}



Slave
Code:

#include <16F877a.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x02, FORCE_HW)



#INT_SSP
void ssp_interupt()
{
   byte incoming;

   if (i2c_poll())
   {
       incoming = i2c_read();   
      if (incoming == 0x02)
      { 
         printf("\n\rAddress: %x\n\r", incoming);
           incoming = i2c_read();
         printf("\n\rData: %x\n\r", incoming);
      }
      }
}

void main()
{
   byte incoming;
   delay_ms(1000);
   printf("Running...");

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   while (true)
   {
   
   }
}



I've about run out of examples to try, this is about the first one that wants to work. Like I said I've made it as bare bones as I could, maybe too bare bones? But like I've said I've tried every example from here, internet search and CCS examples and this is the first so called success. Can anyone help? Thanks.

compiler PCM 3.186
Ttelmah
Guest







PostPosted: Sun Feb 27, 2005 3:47 am     Reply with quote

If the I2C interrupt has occured, there _is_ a byte waiting to be read (don't use 'poll'). Get rid of the printing in the slave routine. The problem here is that if the device is out of sync (which may be the case when the slave has reset), this takes time, and degrades the ability to recover. You have nothing to clear the overflow condition (where a second byte arrives, while you are in the first receive), so the slave will effectively become hung.
Code the slave with something like:
Code:

#include <16F877a.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,brgh1ok)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x02, FORCE_HW)

boolean data_available=false;
int8 data_byte;
#byte SSPSTAT=0x94
#bit DATA=SSPSTAT.5
 
#INT_SSP
void ssp_interupt()
{
      static boolean my_address=false;
      //You _must_ read the data register in each routine here
      if (DATA) {
          //Here I have a data byte
          if (my_address) {
              //Note that you should /ACK the last byte
              data_byte = i2c_read(0);
              data_available=true;
          }
          else {
              //here data is for somone else
              i2c_read();
              data_available=false;
          }
      }
      else {
          //Here an address
          data_byte=i2c_read();
          if (data_byte=0x2) my_address=true;
          else my_address=false;
      }
}

void main()
{
   delay_ms(1000);
   printf("Running...");

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_SSP);
   while (true)
   {
       if (data_available) {
         data_available=false;
         printf("\n\rData: %x\n\r", data_byte);
       }
   }
}

In the 'master', the command write, can be coded to check that the slave has acknowledged the byte.

Best Wishes
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Mon Feb 28, 2005 8:41 am     Reply with quote

Thanks for the above example, it's still doing the same thing unless I missed something you said.
Ttelmah
Guest







PostPosted: Mon Feb 28, 2005 3:40 pm     Reply with quote

One key thing, I didn't say. I generally set up the I2C myself (rather than using the CCS routines), since for this to work right, the bottom 'nibble' of SSPCON, must be set to 0110, so that the chip only interrupts on data/address bytes, and not on stop/start. Check what is in this register (with a simulator), and if necessary change these bits.

Best Wishes
Guest








PostPosted: Wed Mar 02, 2005 9:57 pm     Reply with quote

Ok, made some very good progress but now am completely lost it seems on how to pass more data through I2C.

I got it to do a pwm output and I'm passing the duty cycle through I2C pretty much using the exact code above except data_byte gets assigned the duty and I'm just doing the pwm in the main loop. I added #byte SSPCON=0x36 and then I2C worked but strangely enough I later removed that and it still works great, go figure. But anyways on to the next, I assume doing the following would work, it does not...

snippit from above, just added data_byte2
Code:

//Here I have a data byte
      if (my_address)
      {
         //Note that you should /ACK the last byte
         data_byte = i2c_read();
         data_byte2 = i2c_read();
         data_available=true;
         //data_available2=true;
      }


This is how the help files shows to do it, the next byte should be data as well? Master is the same too but added another write

Code:

i2c_start();
i2c_write((0x02|(BYTE)(address>>1))&0xfe);
i2c_write(0x02);
i2c_command--;
i2c_write(i2c_command);
i2c_write(i2c_command2);
i2c_stop();


Again from the help file it shows doing 2 writes. It seems to go haywire if I try this, can only assume the next read is NOT data like I think it is. The
#byte SSPCON=0x36 would have fixed this I assume, does not so I'm still missing something. From the amount of I2C questions here I can assume I'm not the only one getting very confused with I2C. I was extreamly happy geting a byte accross today because something finally worked (I can still make that work just fine) but getting more accross was not very successful??
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Thu Mar 03, 2005 8:05 am     Reply with quote

sspcon is being set properly without adding the sspcon line. It posted my responce as guest Idea
picer



Joined: 25 Jan 2005
Posts: 28
Location: Taxahoma

View user's profile Send private message

PostPosted: Thu Mar 03, 2005 11:13 am     Reply with quote

And I'm now using 877a as master and 819 as slave since the datasheets seem to indicate the 819 is slave I2C only, maybe that was my original problem with I2C comms so I'm now at the point of trying to make multiple byte sends work as sending one byte works fine.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Mar 03, 2005 1:05 pm     Reply with quote

picer wrote:
And I'm now using 877a as master and 819 as slave since the datasheets seem to indicate the 819 is slave I2C only, maybe that was my original problem with I2C comms so I'm now at the point of trying to make multiple byte sends work as sending one byte works fine.


Master can always be done in firmware.
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