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 Example needed *** Locked *** jayanthd banned for piracy
Goto page Previous  1, 2, 3, 4, 5  Next
 
Post new topic   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 3:49 pm     Reply with quote

@Ttelmah

Quote:
Have you just tried the examples you have been pointed to?

What examples? Who pointed to them?

Quote:
Have you ever actually written a program that works?

Yes. You can see in this thread where I posted a link for my project using mikroC. It uses I2C for DS1307.

Quote:

You _claim_ to have used other languages, but every language _requires_ you to follow it's syntax precisely. You are not even trying.

What syntax in my code are wrong?
Quote:


1) You are now trying to read twice in state zero.
2) You are now trying to issue start conditions in the slave - the _master_ is the only chip that can issue starts.
3) Same applies for stops
4) You are now trying to write four bytes in one ISR in the slave - I've already shown how to write multiple bytes.
5) When you actually solve the above, stop and think for a moment. What happens if the slave changes the value half way through an I2C transaction?

If I don't include the starts and stops in slave, then slave is hanging.

Where have you shown how to write multiple bytes? Please point me to the link.

Is this slave code correct?
Code:

#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
state = i2c_isr_state();
if(state < 0x80)     // Master is sending data
  {
   incoming = i2c_read();
  }

  if((state == 0) || (state == 0x80))   // Master is requesting data from slave
  {
   i2c_read();
   
  }

  if(state > 0x80)   // Master is requesting data from slave
  {
    i2c_write(fvalue.bytes[ctr]);
    ctr++;
    if(ctr > 3) ctr = 0;
  }
}


Are you telling me to use this code from EX_SLAVE.C ??
Code:

{
   unsigned int8 incoming, state;
   
   state = i2c_isr_state();
   
   if(state <= 0x80)                      //Master is sending data
   {
      if(state == 0x80)
         incoming =i2c_read(2);           //Passing 2 as parameter, causes the function to read the SSPBUF without releasing the clock
      else
         incoming = i2c_read();
     
      if(state == 1)                      //First received byte is address
         address = incoming;
      else if(state >=2 && state !=0x80)  //Received byte is data
         buffer[address++] = incoming;
      else if(state == 0x80);
         address--;
   }
   
   if(state >= 0x80)                      //Master is requesting data
   {
      i2c_write(buffer[++address]);
   }
}


Last edited by jayanthd on Sat Mar 23, 2013 4:02 pm; edited 1 time in total
jeremiah



Joined: 20 Jul 2010
Posts: 1355

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 3:59 pm     Reply with quote

I'm not an I2C expert, but I am unsure (in reference to the master code) if a NACK can be sent multiple times before a stop condition. I've not seen a device operate where you do
start
read(NACK)
start
read(NACK)

and so on.

Again, it might be fine, but one of the more seasoned veterans might chime in just in case.


Last edited by jeremiah on Sat Mar 23, 2013 4:08 pm; edited 2 times in total
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 4:03 pm     Reply with quote

jeremiah wrote:
I'm not an I2C expert, but I am unsure (in reference to the master code) if a NACK can be sent multiple times before a stop condition. I've not seen a device operate where you do
start
read(NACK)
start
read(NACK)

and so on.

Again, it might be fine, but one of the more seasoned veterans might chime in just in case.


Ok. See my last post. What is wrong in my Slave ISR code? What modifications should I do in the master code?

Here is my new ISR code for Slave
Code:

#INT_SSP
void ssp_interrupt()
{
int8 incoming, state;
BYTE address;

   state = i2c_isr_state();
   if(state <= 0x80)     // Master is sending data
   {
      if(state == 0x80)
            incoming =i2c_read();           
      //else
            //incoming = i2c_read();

      if(state == 1)                      //First received byte is address
            address = incoming;
      else if(state >=2 && state !=0x80)  //Received byte is data
               ;
      else if(state == 0x80);
            address--;
   }

   if(state >= 0x80)   // Master is requesting data from slave
   {
      i2c_read();
      i2c_write(fvalue.bytes[ctr]);
      ctr++;
      if(ctr > 3) ctr = 0;
   }
}


Is this correct? I am reading and writing when state >= 0x80


Last edited by jayanthd on Sat Mar 23, 2013 4:22 pm; edited 2 times in total
jeremiah



Joined: 20 Jul 2010
Posts: 1355

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 4:13 pm     Reply with quote

I did see your last post, I am making the comment because it could be bad for the hardware longterm and you may not notice it at this point.

as for the ISR:
The order for your slave ISR is incorrect. Please reference the example I mentioned in a previous post (the example code in the manual entry for i2c_isr_state ). You should use the if/else structure they suggest.

Also, long term you probably don't want to save your data read by the slave in incoming as if you aren't quick enough to save it elsewhere, you'll miss it when the next byte comes through.

I haven't read through ex_slave.c (we actually aren't allowed to post example code here), so I don't know the full context of that blurb. One of the other guys can comment on if that particular example is good or not. I've only ever modeled it out of the manual example.
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 4:17 pm     Reply with quote

@jerimiah

See my last post. I have written a new ISR for Slave.

See this document page no. 13 http://www.eti.pg.gda.pl/katedry/ksg/dydaktyka/dla_studentow//i2c.pdf

It tells if device want to send data more than once it has to issue i2c restart. Then why we are not issuing i2c_start() or i2c_restart() in the slave code?
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 5:12 pm     Reply with quote

To add to the mentioned problems there is still the TRIS setting problem:
Code:
   set_tris_a(0xFF);
   set_tris_d(0x00);
   output_a(0x00);
Setting port A to be all input is fine, though it is the same as the power up default so not required. Then outputting 0x00 to port A corrupts the whole port A setting. It doesn't make sense to first set the port to input and then outputting data, but, even worse is that the CCS compiler will write the TRIS-A register to make them all outputs. Your analog inputs on these ports will all read 0 after that. Crying or Very sad
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sat Mar 23, 2013 5:20 pm     Reply with quote

ckielstra wrote:
To add to the mentioned problems there is still the TRIS setting problem:
Code:
   set_tris_a(0xFF);
   set_tris_d(0x00);
   output_a(0x00);
Setting port A to be all input is fine, though it is the same as the power up default so not required. Then outputting 0x00 to port A corrupts the whole port A setting. It doesn't make sense to first set the port to input and then outputting data, but, even worse is that the CCS compiler will write the TRIS-A register to make them all outputs. Your analog inputs on these ports will all read 0 after that. Crying or Very sad


If I comment those tris setting used for lcd port and adc port then adc and lcd doesn't work. I tested it already.

Ok. I removed the tris codes from master and slave and lcd is working fine but i2c is not working i.e., data displayed by master is wrong.

No. with output_a(0x00) adc reads fine but I removed it and still adc works fine.

This is my new code. I am getting some value at master but not the right value.

Master Code
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, FORCE_HW) //FORCE_HW, stream=I2CM

#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13
#define SLAVE2_WRT_ADDR   0x22
#define SLAVE2_READ_ADDR  0x23

float fdata1 = 0, fdata2 = 0;
union float2bytes {
    float fval;
    int8  bytes[4];
}fvalue;

union float2bytes1 {
    float fval1;
    int8  bytes1[4];
}fvalue1;

#define LCD_ENABLE_PIN  PIN_D2
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>



void main()
{
     
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fMaster...\n");
   delay_ms(1000);
   
   while(TRUE)
   { 
      i2c_start(1);
      i2c_write(SLAVE1_READ_ADDR);
      fvalue.bytes[0] = i2c_read();
      i2c_start();
      fvalue.bytes[1] = i2c_read();
      i2c_start();
      fvalue.bytes[2] = i2c_read();
      i2c_start();
      fvalue.bytes[3] = i2c_read(0);
      i2c_stop();
      delay_ms(100);
      i2c_start(1);
      i2c_write(SLAVE2_READ_ADDR);
      fvalue1.bytes1[0] = i2c_read();
      i2c_start();
      fvalue1.bytes1[1] = i2c_read();
      i2c_start();
      fvalue1.bytes1[2] = i2c_read();
      i2c_start();
      fvalue1.bytes1[3] = i2c_read(0);
      i2c_stop();
                 
      if((fvalue.fval != fdata1) || (fvalue1.fval1 != fdata2)) {
         printf(lcd_putc, "\a%5.2f %5.2f", fvalue.fval, fvalue1.fval1);
         printf("%5.2f %5.2f\r\n", fvalue.fval, fvalue1.fval1);
         fdata1 = fvalue.fval;
         fdata2 = fvalue1.fval1;         
      }
      delay_ms(250);
   }

}


Slave 1 Code
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12, FORCE_HW) //FORCE_HW, stream=I2CS

#define LCD_ENABLE_PIN  PIN_D2                                   
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>

float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
    float fval;
    int8  bytes[4];
} fvalue;

#INT_SSP
void ssp_interrupt()
{
   int8 incoming, state;

   state = i2c_isr_state();
   
   if(state < 0x80)     // Master is sending data
   {
      incoming = i2c_read();
   }
   if(state >= 0x80)   // Master is requesting data from slave
   {
      i2c_write(fvalue.bytes[ctr]);
      ctr++;
      if(ctr==4)ctr = 0;
   }

}


void main()
{
   int16 adc_val = 0;
   
   setup_adc_ports(sAN0|VREF_VREF);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
   
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fSlave 1...\n");
   set_adc_channel(0);
   delay_us(20);
   
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   
   while(TRUE)
   {
      adc_val = read_adc();
      delay_ms(20);
      temp = (float)(adc_val * 0.196078431372549);
      fvalue.fval = temp;
      if(old_val != temp){
         printf(lcd_putc, "\a%5.2f", temp);
         printf("Temperature is: %5.2f", temp);
         printf(" Degree Centigrade\r\n");
         printf("%5.2f\r\n", fvalue.fval);
         printf("%lu\r\n", adc_val);
      }

      old_val = temp;
     
             
   }

}


Slave 2 Code
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x22, FORCE_HW) //FORCE_HW, stream=I2CS

#define LCD_ENABLE_PIN  PIN_D2                                   
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>

float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
    float fval;
    int8  bytes[4];
} fvalue;

#INT_SSP
void ssp_interrupt()
{
   int8 incoming, state;

   state = i2c_isr_state();
   
   if(state < 0x80)     // Master is sending data
   {
      incoming = i2c_read();
   }
   if(state >= 0x80)   // Master is requesting data from slave
   {
      i2c_write(fvalue.bytes[ctr]);
      ctr++;
      if(ctr==4)ctr = 0;
   }

}


void main()
{
   int16 adc_val = 0;
   
   setup_adc_ports(sAN0|VREF_VREF);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
   
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fSlave 1...\n");
   set_adc_channel(0);
   delay_us(20);
   
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
   
   while(TRUE)
   {
      adc_val = read_adc();
      delay_ms(20);
      temp = (float)(adc_val * 0.196078431372549);
      fvalue.fval = temp;
      if(old_val != temp){
         printf(lcd_putc, "\a%5.2f", temp);
         printf("Temperature is: %5.2f", temp);
         printf(" Degree Centigrade\r\n");
         printf("%5.2f\r\n", fvalue.fval);
         printf("%lu\r\n", adc_val);
      }

      old_val = temp;
     
             
   }

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 1:52 am     Reply with quote

Code:

//Slave ISR for data transmission
#INT_SSP
void ssp_interrupt()
{
   int8 incoming, state;
   static BYTE address; //This needs to hold it's value between calls

   state = i2c_isr_state();
   if(state <= 0x80)     // Master is sending data
   {
      incoming =i2c_read(); //Simply read in all states where a byte arrives
      if(state == 1)                      //First received byte is address
            address = incoming;
   }
   if(state >= 0x80)   // Master is requesting data from slave
   {
      i2c_write(fvalue.bytes[address++]);
      if(address> 3) address = 0;
   }
}

//Master code to call this
   union {
      float value;
      byte b[4];
   } val;
   int count;
   i2c_start();
   i2c_write(SLAVE_ADDRESS);
   i2c_write(0); //byte to read - register address 0
   i2c_start(); //restart
   i2c_write(SLAVE_ADDRESS+1);
   for (count=0;count<4;count++)
   {
      if (count==3)
         val.b[3]=i2c_read(0); //invert ACK on last byte
      else
         val.b[count]=i2c_read();
   }
   i2c_stop();
   //now val.value is the float received from the slave


The problem is you keep putting extra reads/writes in where they are not needed. You were told to add a read to state 0x80, added this, but also added one to states 0x81, 0x82 etc...

Now there is a separate issue still present here that the slave could change the value between calls. This is where a sync flag between the routines is needed, or toggling between two buffers.
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 2:12 am     Reply with quote

I found on this page http://www.ccsinfo.com/forum/viewtopic.php?t=21456

that some registers related to i2c and spi have to be configured. The 16F887.h file doesn't contain these information. I have to add these register configurations in master and slave codes.

Somebody please check and tell whether my setting are right for both master and slave. I have set the values as mentioned in the PIC16F887 datasheet.

Master
Code:

MASTER

* 16f887 bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON=0x14
#byte PIC_SSPCON2=0x91

/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP     0x00
#define PIC_SSPSTAT_BIT_CKE     0x01
#define PIC_SSPSTAT_BIT_DA      0x00
#define PIC_SSPSTAT_BIT_P       0x00
#define PIC_SSPSTAT_BIT_S       0x00
#define PIC_SSPSTAT_BIT_RW      0x00
#define PIC_SSPSTAT_BIT_UA      0x00
#define PIC_SSPSTAT_BIT_BF      0x00

#define PIC_SSPCON_BIT_WCOL    0x00
#define PIC_SSPCON_BIT_SSPOV   0x00
#define PIC_SSPCON_BIT_SSPEN   0x01
#define PIC_SSPCON_BIT_CKP     0x00
#define PIC_SSPCON_BIT_SSPM3   0x01
#define PIC_SSPCON_BIT_SSPM2   0x00
#define PIC_SSPCON_BIT_SSPM1   0x00
#define PIC_SSPCON_BIT_SSPM0   0x00

#define PIC_SSPCON2_BIT_GCEN    0x00
#define PIC_SSPCON2_BIT_ACKSTAT 0x01
#define PIC_SSPCON2_BIT_ACKDT   0x00
#define PIC_SSPCON2_BIT_ACKEN   0x01
#define PIC_SSPCON2_BIT_RCEN    0x01
#define PIC_SSPCON2_BIT_PEN     0x00
#define PIC_SSPCON2_BIT_RSEN    0x00
#define PIC_SSPCON2_BIT_SEN     0x00


Slave
Code:

* 16f887 bytes */
/* Change it per chip */
#byte PIC_SSPBUF=0x13
#byte PIC_SSPADD=0x93
#byte PIC_SSPSTAT=0x94
#byte PIC_SSPCON=0x14
#byte PIC_SSPCON2=0x91

/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP     0x00
#define PIC_SSPSTAT_BIT_CKE     0x01
#define PIC_SSPSTAT_BIT_DA      0x01
#define PIC_SSPSTAT_BIT_P       0x00
#define PIC_SSPSTAT_BIT_S       0x00
#define PIC_SSPSTAT_BIT_RW      0x01
#define PIC_SSPSTAT_BIT_UA      0x00
#define PIC_SSPSTAT_BIT_BF      0x00

#define PIC_SSPCON_BIT_WCOL    0x00
#define PIC_SSPCON_BIT_SSPOV   0x00
#define PIC_SSPCON_BIT_SSPEN   0x01
#define PIC_SSPCON_BIT_CKP     0x00
#define PIC_SSPCON_BIT_SSPM3   0x00
#define PIC_SSPCON_BIT_SSPM2   0x01
#define PIC_SSPCON_BIT_SSPM1   0x01
#define PIC_SSPCON_BIT_SSPM0   0x00

#define PIC_SSPCON2_BIT_GCEN    0x01
#define PIC_SSPCON2_BIT_ACKSTAT 0x01
#define PIC_SSPCON2_BIT_ACKDT   0x00
#define PIC_SSPCON2_BIT_ACKEN   0x00
#define PIC_SSPCON2_BIT_RCEN    0x00
#define PIC_SSPCON2_BIT_PEN     0x00
#define PIC_SSPCON2_BIT_RSEN    0x00
#define PIC_SSPCON2_BIT_SEN     0x00


I tried your new code Ttelmah and it doesn't work. The master doesn't display the read values and the slave hangs and the slave lcd data doesn't update.

I tried with one master and one slave.

Here is the codes I used

MASTER
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3) //FORCE_HW, stream=I2CM

/*
#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13
#define SLAVE2_WRT_ADDR   0x22
#define SLAVE2_READ_ADDR  0x23
*/

#define SLAVE1_ADDRESS 0x12
#define SLAVE2_ADDRESS 0x22



float fdata1 = 0, fdata2 = 0;
/*
union float2bytes {
    float fval;
    int8  bytes[4];
}fvalue;

union float2bytes1 {
    float fval1;
    int8  bytes1[4];
}fvalue1;
*/

union {
   float value;
   byte b[4];
   } val;
int count;
   
#define LCD_ENABLE_PIN  PIN_D2
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>

void main()
{
     
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fMaster...\n");
   delay_ms(500);
   
   while(TRUE)
   { 
      i2c_start();
      i2c_write(SLAVE1_ADDRESS);
      i2c_write(0);     //byte to read - register address 0
      i2c_start();      //restart
      i2c_write(SLAVE1_ADDRESS+1);
      for (count=0;count<4;count++)
      {
         if (count==3){
            val.b[3]=i2c_read(0); //invert ACK on last byte
            count = 0;
         }   
         else
            val.b[count]=i2c_read();
      }
      i2c_stop();
      //now val.value is the float received from the slave
      delay_ms(500);
      /*
      i2c_start(1);
      //i2c_write(SLAVE1_WRT_ADDR);
      //i2c_start();
      i2c_write(SLAVE1_READ_ADDR);
      fvalue.bytes[0] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      fvalue.bytes[1] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      fvalue.bytes[2] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      fvalue.bytes[3] = i2c_read(0);     
      i2c_stop();
      delay_ms(100);
      i2c_start(1);
      i2c_write(SLAVE2_READ_ADDR);
      fvalue1.bytes1[0] = i2c_read();
      i2c_start();
      fvalue1.bytes1[1] = i2c_read();
      i2c_start();
      fvalue1.bytes1[2] = i2c_read();
      i2c_start();
      fvalue1.bytes1[3] = i2c_read(0);
      i2c_stop();
      */
      if(val.value != fdata1) {
         printf(lcd_putc, "\a%5.2f", val.value);
         printf("%5.2f\r\n", val.value);
         //printf("%d %d %d %d", fvalue.bytes[0], fvalue.bytes[1], fvalue.bytes[2], fvalue.bytes[3]);
         fdata1 = val.value;
         //fdata2 = val1.value;         
      }
      //delay_ms(250);
   }

}


SLAVE
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12) //FORCE_HW, stream=I2CS

#define LCD_ENABLE_PIN  PIN_D2                                   
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>

float temp = 0, old_val = 0;
int8 ctr = 0;
union float2bytes {
    float fval;
    int8  bytes[4];
} fvalue;
/*int8 cnt = 0;
int8 buffer[3], c;

#INT_SSP
void ssp_interrupt()
{
   int8 incoming, state;

   state = i2c_isr_state();
   
   if(state < 0x80)     // Master is sending data
   {
      incoming = i2c_read();
           
   }
   else if((state== 0) || (state == 0x80)) {
      incoming = i2c_read(1);
     
      //i2c_write(cnt++);
      i2c_write(fvalue.bytes[ctr]);
      ctr++;
   }
   else if(state > 0x80)   // Master is requesting data from slave
   {
      i2c_write(fvalue.bytes[ctr]);
      ctr++;
      if(ctr==4)ctr = 0;
      //i2c_read(0);
     
      //i2c_write(cnt++);
     
   }

}
*/
//Slave ISR for data transmission
#INT_SSP
void ssp_interrupt()
{
   int8 incoming, state;
   static BYTE address; //This needs to hold it's value between calls

   state = i2c_isr_state();
   if(state <= 0x80)     // Master is sending data
   {
      incoming =i2c_read(); //Simply read in all states where a byte arrives
      if(state == 1)                      //First received byte is address
            address = incoming;
   }
   if(state >= 0x80)   // Master is requesting data from slave
   {
      i2c_write(fvalue.bytes[address++]);
      if(address> 3) address = 0;
   }
}

void main()
{
   int16 adc_val = 0;
   
   setup_adc_ports(sAN0|VREF_VREF);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
   
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fSlave 1...\n");
   set_adc_channel(0);
   delay_us(20);
   
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);
         
   while(TRUE)
   {
      adc_val = read_adc();
      delay_ms(20);
      temp = (float)(adc_val * 0.196078431372549);
      fvalue.fval = temp;
      if(old_val != temp){
         printf(lcd_putc, "\a%5.2f", temp);
         printf("Temperature is: %5.2f", temp);
         printf(" Degree Centigrade\r\n");
         printf("%5.2f\r\n", fvalue.fval);
         printf("%lu\r\n", adc_val);
      }

      old_val = temp;
     
             
   }

}


If you can fix it please do it.
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 3:26 am     Reply with quote

My Master code works but Ttelmah's master code hangs the slave. I am using Ttelmah's slave ISR.

The problem is my master code gives the value -3.99 which is wrong value and the value never changes.

My master code doesn't hang any PICs and I see I2C communication happening every 1 sec as I have used a 1 sec delay in master code but the value never changes from -3.99

http://www.pixhost.org/show/4608/16407091_i2cp.jpg

MASTER code
Code:

#include <16F887.h>
#device adc=10

#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=20000000)                //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3) //FORCE_HW, stream=I2CM


#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13
#define SLAVE2_WRT_ADDR   0x22
#define SLAVE2_READ_ADDR  0x23


#define SLAVE1_ADDRESS 0x12
#define SLAVE2_ADDRESS 0x22



float fdata1 = 0, fdata2 = 0;
/*
union float2bytes {
    float fval;
    int8  bytes[4];
}fvalue;

union float2bytes1 {
    float fval1;
    int8  bytes1[4];
}fvalue1;
*/

union {
   float value;
   byte b[4];
   } val;
int count;
   
#define LCD_ENABLE_PIN  PIN_D2
#define LCD_RS_PIN      PIN_D0                                   
#define LCD_RW_PIN      PIN_D1                                   
#define LCD_DATA4       PIN_D4                                   
#define LCD_DATA5       PIN_D5                                   
#define LCD_DATA6       PIN_D6                                   
#define LCD_DATA7       PIN_D7

#include <lcd.c>

void main()
{
     
   delay_ms(250);
   lcd_init();
   delay_ms(250);
   lcd_putc("\fMaster...\n");
   delay_ms(500);
   
   while(TRUE)
   { 
      /*
      i2c_start();
      i2c_write(SLAVE1_ADDRESS);
      i2c_write(0);     //byte to read - register address 0
      i2c_start();      //restart
      i2c_write(SLAVE1_ADDRESS+1);
      for (count=0;count<4;count++)
      {         
         if (count==3){
            val.b[3]=i2c_read(0); //invert ACK on last byte
            count = 0;
         }   
         else
            val.b[count]=i2c_read(1);
      }
      i2c_stop();
      //now val.value is the float received from the slave
      delay_ms(500);
      */
     
      i2c_start(1);
      i2c_write(SLAVE1_WRT_ADDR);
      i2c_write(0);
      i2c_start();
      i2c_write(SLAVE1_READ_ADDR);
      val.b[0] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      val.b[1] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      val.b[2] = i2c_read(1);
      i2c_start();
      //i2c_write(0x13);
      val.b[3] = i2c_read(0);     
      i2c_stop();
      /*
      delay_ms(100);
      i2c_start(1);
      i2c_write(SLAVE2_READ_ADDR);
      fvalue1.bytes1[0] = i2c_read();
      i2c_start();
      fvalue1.bytes1[1] = i2c_read();
      i2c_start();
      fvalue1.bytes1[2] = i2c_read();
      i2c_start();
      fvalue1.bytes1[3] = i2c_read(0);
      i2c_stop();
      */
      if(val.value != fdata1) {
         printf(lcd_putc, "\a%5.2f", val.value);
         printf("%5.2f\r\n", val.value);
         //printf("%d %d %d %d", fvalue.bytes[0], fvalue.bytes[1], fvalue.bytes[2], fvalue.bytes[3]);
         
         //fdata2 = val1.value;         
      }
      fdata1 = val.value;
      delay_ms(1000);
   }

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 6:05 am     Reply with quote

PCM_programmer posted a link to multi byte I2C routines right at the start of your thread.

Remove the complexity.

Like most people not used to debugging, you are making the problem too complex. Try sending a packet of known data, with none of the other fiddling around (no temperature reading, and just simple display of the data). Your code should be no more than about 30 lines at each end including headers.

Once you have this working then move on and try adding more.

If the examples don't work, then stop and look at your hardware. You _have_ got suitable pull up resistors on the bus?. You have got the grounds connected between the units?. How long is the bus?.

There are actually two errata for the 16F887 chip affecting I2C, which could explain a lot. First as a slave device, the device will prematurely release the clock line on the last byte of a multi byte transfer. Means the master _must_ pause at this point. You do delay here, but a 'caveat' for the future. Then as a master device, there is a real humdinger on handling clock stretching incorrectly. Try switching to using the software I2C on the master, instead of hardware, and see if things change....
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 6:37 am     Reply with quote

I enjoyed the beers last night, and wake up to find this thread about to spill over to page 5.

Here's my take with a few quotes thrown in.
Quote:
I finally got the i2c working somewhat but lcd is not working now. Same problem in hardware and proteus.
You've got the I2C 'working somewhat', then go off on an LCD chase.
To me, 'working somewhat' isn't good enough.
You should be getting the I2C working better than that before going off elsewhere.

Quote:
I believe the problem lays between the screen and the back of your chair.

What does that mean?
Draw a line from screen to head rest.
Then another from left ear to right.
Where do the two lines meet?

I told you back on page 2 that CCS is a different beast.
It takes some effort to get your brain into a totally new way of thinking.
It's a bit like the difference between say 'FORTH' and 'BASIC', 'WINDOWS' and 'DOS'.
At this stage, you're simply not getting it.

As I said before, I've used other 'C' compilers.
I know that Hi-Tek is not very far removed from assembler as far as register operations are concerned.
With CCS you HAVE to get away from the idea of directly operating on the registers.
Assuming that CCS has got it right, the compiler SHOULD do almost ALL register operations for you.
By playing with the registers, you're fighting the compiler.
In your recent post you've introduced a whole new list of registers to play with.
I can only assume you're contemplating screwing those up as well.

I'm not the only one telling you this, there are several of us.
You appear to be totally ignoring most of the advice you're being given on this aspect and many others.
You're even arguing with some of the exquisite responses you're getting.

Quote:
Finally what is the solution to my problem?
I stick by my comment also on page 2, you have to work it out for yourself.

That's me done. I give up.

Mike
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 9:38 am     Reply with quote

Ok. I got it working. Here is a screenshot of my project working. Very Happy

I will soon post the code after fine tuning my project.

http://www.pixhost.org/show/3166/16411281_i2c_working.jpg



http://www.edaboard.com/attachments/88453d1364142505-i2c_w1.jpg

After reading CCS C manual and microchip i2c document I was able to write the code using CCS C i2c library functions and I have tested it both on hardware and Proteus and it is working fine.

Finally I did it within 24 hours.

There is a problem. I tested the working with one slave at a time and it works fine if with single slaves. Both the slaves are working but If I connect both the slaves it just reads the data once and slave 1 and slave 2 hangs. What might be the problem? Is it that i2c bus is not clearing properly after the first read?

http://www.pixhost.org/show/2236/16412948_i2c_hang.jpg
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sun Mar 24, 2013 3:49 pm     Reply with quote

jayanthd wrote:
Ok. I got it working. Here is a screenshot of my project working.

I will soon post the code after fine tuning my project.

After reading CCS C manual and microchip i2c document I was able to write the code using CCS C i2c library functions and I have tested it both on hardware and Proteus and it is working fine.

Finally I did it within 24 hours.

There is a problem. I tested the working with one slave at a time and it works fine if with single slaves. Both the slaves are working but If I connect both the slaves it just reads the data once and slave 1 and slave 2 hangs. What might be the problem? Is it that i2c bus is not clearing properly after the first read?

Speaks for itself.

Mike
jayanthd



Joined: 06 Dec 2012
Posts: 47
Location: Banned - pirate

View user's profile Send private message

PostPosted: Mon Mar 25, 2013 1:58 am     Reply with quote

Mike Walne wrote:

Speaks for itself.

Mike


What? I said that if I use only one slave at a time it works without problem but if I use both slaves then master reads data from both the slaves and displays correctly but slaves hangs after that or thats what I think because when the master reads the slaves second time it gives data ad 0.0000 for both the slaves. In master I have written code such that it read data changes from previous data then only print the values. In the second read it is getting 0 for both the slaves. What are the causes for such a problem?

What I see in the i2c debugger is NACK is being performed which should be done only at the end of read operations. Why is it happening? I didn't change the code in anyway. If I use the same code with one slave it works fine but not with two slaves. I have 4 i2c_read operations 2 times that is for 8 read operations in total for 2 slaves to read 8 bytes data. I know that i2c_read() does ACK and i2c_read(0) does a NACK. I have used the read operation like below.

read slave 1

i2c_read()
i2c_read()
i2c_read()
i2c_read(0)

read slave 2

2c_read()
i2c_read()
i2c_read()
i2c_read(0)

What am I doing wrong?
Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies.    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5  Next
Page 4 of 5

 
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