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

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



Joined: 16 Apr 2012
Posts: 3
Location: India

View user's profile Send private message AIM Address

I2C - PIC16F887
PostPosted: Mon Apr 16, 2012 10:23 pm     Reply with quote

HI
I am using PIC 16F887 and CCS-C compiler (version 4.093) plugin in MPLAB IDE. I used i2c code posted by PCM programmer to simulate i2c operation in proteus. The code works for pic16f877 but it is not working for pic16f887. What should I change to make it work in 16f887 ? The code is as follows, I've made few changes in it. My objective is to communicate between two PIC16f887 controllers, where the slave controller collects sensor data and sends it to master controller which displays it on LCD and PC using RS232 connection.
The simulation results with 16f877 using Proteus is as follows(temperature measurement):

30 c (correct value)
-1 (wrong value)
-1
-1
and so on -1 continues.
Please help me on this...

MASTER:
Code:

#include <16F887.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
   
#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13

//====================================
void main()
{
int8 data;

while(1)
  {
   i2c_start();
   i2c_write(SLAVE1_READ_ADDR);
   data = i2c_read(0);
   i2c_stop();

   printf("temp %d \n\r", data);

   delay_ms(1000);
  }

}


SLAVE:
Code:

#include <16F887.h>
#device adc=10
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)

int8 adc_result;

#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(adc_result);
  }
}
//======================================
void main ()
{
setup_adc_ports( ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_4);
set_adc_channel(0);
delay_us(20);
adc_result = read_adc();
adc_result = adc_result*0.48828125;

enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
   
while(1)
  {
   adc_result = read_adc();
   adc_result = adc_result*0.48828125;
   delay_ms(500);
  }

}
Ttelmah



Joined: 11 Mar 2010
Posts: 19496

View user's profile Send private message

PostPosted: Tue Apr 17, 2012 1:38 am     Reply with quote

1) Forget Proteus....
It can sometimes emulate some chips, but unfortunately does not reflect problems with real hardware, and will often just not work, for no reason, or work with setups that will fail miserably in real life....

2) Change your oscillator. For 4MHz, you should be using 'XT', not 'HS'. Proteus will not complain about this, but it is likely to cause problems with some crystals.

3) Problem with the slave code. Study carefully what _must_ happen on state 0x80. On this, you _must_ read the incoming address byte before loading the reply. You are not doing this, and this could hang the I2C peripheral.

Code:

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

   state = i2c_isr_state();

   if(state <= 0x80)  { //Note the '=' here
     incoming = i2c_read();
   }
   if(state >= 0x80)  {
     i2c_write(adc_result);
   }
}


The 0x80 state, is 'unique', in that here a byte must both be read, and a new one written....

4) You have got pull-up resistors on the two bus wires?. '-1' reflects receiving the byte 0xFF, and the commonest reason for receiving this is that the bus is not properly pulled up. Look at something between 2.2KR, and 4.7KR, depending on the length of the bus.

Best Wishes
alique89



Joined: 21 Apr 2012
Posts: 7

View user's profile Send private message

PostPosted: Sat Apr 21, 2012 5:32 pm     Reply with quote

try changing the place holder and see the result in hex. it might be play with the value. check if the value is not rolling over when you multiply.
[email protected]



Joined: 07 Feb 2012
Posts: 19
Location: pakistan

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

PostPosted: Mon Apr 23, 2012 6:06 am     Reply with quote

I'm posting master and slave code of I2c, it really work on real-time hardware.

There is little bit error in slave code, you can replace slave code with EX_slave.c example
Code:

#include <18F458.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xC0)
 BYTE datar;
BYTE dataw=0x60; 
   
 #INT_SSP   
 void ssp_interupt ()   
 {   
    BYTE  state;   
 

      //printf("*/n");
      state = i2c_isr_state();    //0 - Address match received with R/W bit clear

                                  //1-0x7F - Master has written data; i2c_read() will immediately return the data
 
                                  //0x80 - Address match received with R/W bit set; respond with i2c_write()

                                  //0x81-0xFF - Transmission completed and acknowledged; respond with i2c_write()

      if(state == 0x00)
         {
          datar=i2c_read();
          //printf("Adress match:%x\n",datar);
          output_a(datar);
         
        }

      else if(state > 0 && state < 0x80)
        {
         datar= i2c_read();
         //printf("Bytes:%x\n",datar);
        //datar=0x00;
        output_a(datar);
        }
      else if(state == 0x80)
        {
         i2c_write(dataw);
          //printf("Data write on Master:%x\n",dataw);
       }
      else if(state > 0x80 && state < 0x100)
        {
        //printf("Data has been acknowledged\n");
       }
   

 }   
   
 void main ()   
 { 
    //port_b_pullups(TRUE); 
    enable_interrupts(GLOBAL);   
    enable_interrupts(INT_SSP);   
   
    while (TRUE) {}   
 } 


Master
Code:

#include <18F452.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,address=0x60)
void main ()
{
while(1)
{
 i2c_start();
 //while(i2c_write(0xC0));// Device address
 i2c_write(0xc0);
 output_a(0x1);
 delay_ms(1000);
 //while(i2c_write(0x1F));
 i2c_write(0x2);
 output_a(0x2);
 delay_ms(1000);
 //while(i2c_write(0x7C));
 i2c_write(0x3);
 output_a(0x3);
 delay_ms(1000);
 // while(i2c_write(0x30));
 i2c_write(0x4);
 output_a(0x4);
 delay_ms(1000);
 //while(i2c_write(0x00));
 i2c_write(0x5);
 output_a(0x5);
 delay_ms(1000);
 //while(i2c_write(0x00));
 i2c_stop();
}

}

Try it again on hardware, you will success.
vasanth



Joined: 16 Apr 2012
Posts: 3
Location: India

View user's profile Send private message AIM Address

I2C - PIC16F887
PostPosted: Mon Apr 23, 2012 7:07 pm     Reply with quote

THANH YOU ! ITS WORKING NOW
vasanth



Joined: 16 Apr 2012
Posts: 3
Location: India

View user's profile Send private message AIM Address

I2C - PIC16F887
PostPosted: Wed May 23, 2012 12:26 am     Reply with quote

Hi,
I am using PIC 16F887 and CCS-C compiler(version 4.093) plugin in MPLAB IDE.

I have dumped the code in hardware and I2C is working.
Now, I do not know at what speed the I2C communication is taking place ?
Can you help?

master
Code:
#include <16f887.h>
#device ADC=10
#use delay(clock=16000000)   
#fuses HS, NOWDT, NOPROTECT, NOLVP       
#use RS232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#include <flex_lcd.c>
#define P1B PIN_D5
#define SLAVE1_WRT_ADDR   0x12
#define SLAVE1_READ_ADDR  0x13
     
       int16 temp_adc1;
       float temp1;
       int16 temp_adc2;
       float temp2;

       int16 volt_adc1;
       float volt1;
       int16 volt_adc2;
       float volt2;
     
       
       int16 crnt_adc1;
       float crnt1;
       int16 crnt_adc2;
       float crnt2;

       int pwmv_adc1;
       int8 data;

void set_deadband(int8 deadband)
{
#byte PWM1CON = 0x9B
     
if(deadband > 127)
   deadband == 127;

PWM1CON = deadband;
}


void main()
 {
 lcd_init();
 setup_adc(ADC_CLOCK_DIV_32);
 setup_timer_2(T2_DIV_BY_16, 255, 1);
 setup_ccp1(CCP_PWM_HALF_BRIDGE | CCP_PWM_H_H );
 output_low(P1B);
 set_deadband(127);

while(1)
 {
        printf ( lcd_putc, "Battery Status\n" );
        delay_ms(5);      //print to lcd  --- clear LCD ---  lcd_putc("\f");
        printf ("Battery Status\n\r" );  //print to serial com
        delay_ms(5);
       
        //PWM
       
         set_adc_channel(4); //read analog input from channel 0
         delay_ms(10);
         pwmv_adc1 = read_adc();
         set_pwm1_duty(pwmv_adc1);

      //I2c
         
        i2c_start();
         i2c_write(SLAVE1_READ_ADDR);
         data = i2c_read(0);
         i2c_stop();
        lcd_gotoxy(1,2);
        printf ( lcd_putc,"%5.1f", (float)data);
        lcd_putc("  i2c_temp");
        delay_ms(500);
         printf("i2c_temp %d \n\r", data);
         delay_ms(500);
      
      //temperature measurement   
         
         set_adc_channel(0); //read analog input from channel 0
         delay_ms(10);
         temp_adc1 = read_adc();
         temp1 = 5.00*temp_adc1*100.00/1023.00;    // = temp_adc*0.48828125
         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)temp1);   // printf(lcd_putc, "value = %lu \n",value)                     
         lcd_putc(223);                              //this number 223 will display the degree sign
         lcd_putc('C');
         lcd_putc("  b1_temp");
         delay_ms(500);
         
         printf ("\n");
         printf ("%5.1f", (float)temp1);
         putc(223);
         putc('C');
         puts("  b1_temp");
         printf ("\n\r");
         delay_ms(5);
         
         set_adc_channel(1); //read analog input from channel 1
         delay_ms(10);
         temp_adc2 = read_adc();
         temp2 = temp_adc2*0.48828125;
         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)temp2);
         lcd_putc(223);      //this number 223 will display the degree sign
         lcd_putc('C');
         lcd_putc("  b2_temp");
         delay_ms(500);
       
         printf ("%5.1f", (float)temp2);
         putc(223);
         putc('C');
         puts("  b2_temp");
         printf ("\n\r");
         delay_ms(5);
         
        //voltage measrement
       
         set_adc_channel(2); //read analog input from channel 2
         delay_ms(10);
         volt_adc1 = read_adc();
         volt1 = (volt_adc1*0.0048875855)+9;//(volt*5)/1023

         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)volt1);
         lcd_putc('V');
         lcd_putc("  b1_volt");
         delay_ms(500);
       
         
         printf ("%5.1f", (float)volt1);
         putc('V');
         puts("  b1_volt");
         printf ("\n\r");
         delay_ms(5);
         if(volt1<=10.5)
         output_high(PIN_B2);
         else
         output_low(PIN_B2);
         
         set_adc_channel(5); //read analog input from channel 5
         delay_ms(10);
         volt_adc2 = read_adc();
         volt2 = (volt_adc2*0.0048875855)+9;//(volt*5)/1023
         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)volt2);
         lcd_putc('V');
         lcd_putc("  b2_volt");
         delay_ms(500);
         
         printf ("%5.1f", (float)volt2);
         putc('V');
         puts("  b2_volt");
         printf ("\n\r");
         delay_ms(5);
         if(volt2<=10.5)
         output_high(PIN_B3);
         else
         output_low(PIN_B3);
         
        // current measurement

         set_adc_channel(3); //read analog input from channel 3
         delay_ms(10);
         crnt_adc1 = read_adc();
         crnt1 = crnt_adc1*0.0048875855;//(volt*5)/1023
         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)crnt1);
         lcd_putc('A');
         lcd_putc("  b1_crnt");
         delay_ms(500);
         
         printf ("%5.1f", (float)crnt1);
         putc('A');
         puts("  b1_crnt");
         printf ("\n\r");
         delay_ms(5);

         set_adc_channel(6); //read analog input from channel 6
         delay_ms(10);
         crnt_adc2 = read_adc();
         crnt2 = crnt_adc2*0.0048875855;//(volt*5)/1023
         lcd_gotoxy(1,2);
         printf ( lcd_putc,"%5.1f", (float)crnt2);
         lcd_putc('A');
         lcd_putc("  b2_crnt");
         delay_ms(500);
         
         printf ("%5.1f", (float)crnt2);
         putc('A');
         puts("  b2_crnt");
         printf ("\n\r");
         delay_ms(5);
}
}



slave
Code:
#include <16F887.h>
#device adc=10
#fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(internal=8M)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0x12)

int8 adc_result;

#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(adc_result);
  }
}
//======================================
void main ()
{
setup_adc_ports( ALL_ANALOG );
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
delay_us(20);
adc_result = read_adc();
adc_result = adc_result*0.48828125;

enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
   
while(1)
  {
   adc_result = read_adc();
   adc_result = adc_result*0.48828125;
   delay_ms(500);
  }

}
Mike Walne



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

View user's profile Send private message

PostPosted: Wed May 23, 2012 2:23 am     Reply with quote

Quote:
Now, I do not know at what speed the I2C communication is taking place ?

Check with a 'scope? (Will give you both bit-rate, and repeat-rate.)



What happens if the I2C interrupt occurs either, between these two lines, or during the float calculation?
Quote:
adc_result = read_adc();
adc_result = adc_result*0.48828125;


Yes, I know the probability is low in this case. (Murphy's law says that it definitely will, at THE most un-opportune moment.)

Mike
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