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

PIC to PIC I2C problem with 16f1827

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



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

PIC to PIC I2C problem with 16f1827
PostPosted: Fri Mar 11, 2016 9:36 am     Reply with quote

Hello,
I'm new here and this is my first post here (so hello all again) I'm new at CCS, used to use another compiler before and I stuck with a simple problem, couldn't solve it alone so I need some help. I would be grateful if anyone can see the problem.

I'm using 2 16f1827's to set a I2C master - slave communication, sending 5 bytes of data from master and storing them in an array in slave and when 5 bytes of data received, I'm checking these data if they are what I sent.

I established connection, sending and receiving data over I2C but an "if" condition in my code is never working and can't see thats why. I set data_ready variable to 1 when 5 bytes of data received, then checking in a "while" if data_ready is 1, program enters to part of code where data_ready set to 5 but it does not confirm in "while" loop that data_ready is one.

I'm using indicator LED's to see where program is running and where it is not running. I'll explain more with comments in my code.

This is my master code and it looks like working fine
Code:
//-------------Master--------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,BROWNOUT,NOLVP, MCLR, NOCPD, NOBROWNOUT, NOCLKOUT
#FUSES INTRC_IO, NOIESO, NOFCMEN, NOWRT, PLL_SW, NOSTVREN
#byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0
#use delay(clock = 8000000) 
#use i2c(MASTER, SDA=PIN_B1, SCL=PIN_B4)
#byte TRISA = 0x20
#byte TRISB = 0x13
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)

#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
   
#define SLAVE1_WRT_ADDR   0x08
#define SLAVE1_READ_ADDR  0x09
//====================================

#INT_EXT
void ext_isr(void)
{
putc('\n');
putc('\r');
printf("test");
output_toggle(pin_b6);
}

void main()
{
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
   i2c_start();
   i2c_write(SLAVE1_wrt_ADDR);
   i2c_write(0x0F);
   delay_ms(10);   

   i2c_write(0x10);
   delay_ms(10);   
   
   i2c_write(0x18);
   delay_ms(10);   

   i2c_write(0xFF);
   delay_ms(10);     
   
   i2c_write(0xF0);
   delay_ms(10);   
   i2c_stop();
   
   delay_ms(100);
   output_toggle(pin_b7);
}
}//main


This is my slave code
Code:
///------------------Slave-------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,NOLVP,MCLR,NOCPD,NOBROWNOUT,NOCLKOUT
#FUSES INTRC_IO,NOIESO,NOFCMEN,NOWRT,PLL_SW,NOSTVREN
#byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0
#use delay(clock = 8000000)
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0x08)
//#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x20
#byte TRISB = 0x13

#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1

int8 test_result, mdirect;
int8 datain[6];
int8 incoming, state, readcnt;
unsigned long stepamount;
volatile int8 data_ready;
#INT_SSP
void ssp_isr(void)
{
state = i2c_isr_state();
if(state < 0x80)     // Master is sending data
{
   incoming = i2c_read();
   datain[readcnt]=incoming;
   readcnt=readcnt+1;
   if(readcnt==5){
      data_ready=1;
      readcnt=0;
      output_toggle(pin_b7); //I'm tracing this signal with oscillascope and I see changes on this pin, so program enters in this "if" statement and setting data_ready to 1
   }
}
if(state >= 0x80)   // Master is requesting data from slave
  {
   i2c_write(0xFF);
  }
}
#INT_EXT
void ext_isr(void)
{
output_toggle(pin_b6);
}
//======================================
void main ()
{
readcnt=0;
data_ready=0;
i2c_SlaveAddr(0x08);
setup_adc_ports(NO_ANALOGS);

enable_interrupts(INT_SSP);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);

/*&&(datain[0]=0x0F)&&(datain[4]=0xF0)*/
while(1)
{
    //if I put an indicator code here (toggling a led) I can see that it is toggling and program looping in this "while"
    if (data_ready==1){
      output_toggle(pin_b6); // my problem is here, although program indicates that it enters I2C ISR and since it is entering there, it sets data_ready to 1 but it never enters this part.
      mdirect=datain[1];
      stepamount=make16(datain[3],datain[2]);
     
      for (int i=0;i=5;i++){
         datain[i]=0;
      }
      data_ready=0;
      if (mdirect==0x10){
         output_toggle(pin_b5);
      }
      if (stepamount==0xFF18){
         output_toggle(pin_b6);
      }
   }
 }
}


I set up the circuit in both protheus and on a board, I'm sending protheus schematics to show what I'm working on



_________________
There is nothing you can't do if you try
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 11, 2016 11:04 am     Reply with quote

Quote:
#byte OSCCON = 0x70
#byte OSCTUNE = 0
#byte DACCON0 = 0
#byte SRCON0 = 0

These statements are incorrect. The #byte statement lets you specify
the address of a PIC register, so you can r/w directly to the register in
your program. But haven't specified the addresses of the listed registers.
0x70 is not the address of the OSCCON register. Check the PIC data
sheet. 0 is not the address of the other registers.

Quote:
#define SLAVE1_WRT_ADDR 0x08
#define SLAVE1_READ_ADDR 0x09

#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0x08)

i2c_SlaveAddr(0x08);

0x8 is a reserved address for an i2c slave. The lowest slave address
that you can legally use is 0x10. This is in the NXP i2c specification.


Quote:
#byte TRISA = 0x20
#byte TRISB = 0x13

Again, #byte is not used to set the value of a register. #byte is used to
set the address of a register. The real addresses are 0x8C and 0x8D.
But if you want to set the TRIS, CCS has a function to do it. See the
manual.

Quote:
for (int i=0;i=5;i++){
datain[i]=0;
}

This loop is supposed to clear the datain[6] array, but it won't work
because the middle test is wrong. It should be
Code:
i <= 5


Your bottom schematic is missing a pullup resistor on Pin B4, the SCL line.
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Fri Mar 11, 2016 12:40 pm     Reply with quote

Also as one little comment, OSCTUNE, is loaded automatically with the
calibration value stored in the chip's memory, at boot. If you were writing to it, you should not be writing to it. OSCCON, is also setup by the clock
settings (change the clock statement to say (INTERNAL=8MHz)). This
will ensure OSCCON is correctly setup.
For 99.9% of code you should never have to touch a register directly in CCS.
elcrcp



Joined: 11 Mar 2016
Posts: 62
Location: izmir / Turkey

View user's profile Send private message

Solved
PostPosted: Fri Mar 11, 2016 2:02 pm     Reply with quote

I greatly thank you 'PCM programmer' and 'Ttelmah' for your comments and warnings, as I said before, I used to use another lang and compiler for PIC and I'm new at CCS so there are lot of things and functions I don't know in CCS.

I used to write directly to registers to setup a PIC and since I don't know how they done in CCS yet, it will take some time for me to get used to not to write directly to registers Smile

I thought #byte is writing directly to predefined registers so that is why I used it like that. I edited my codes due to your warnings and tried again, now they working without any problem, here are my edited working codes for if anyone encounters the same fate Smile

Code:
//-------------Master--------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,BROWNOUT,NOLVP, MCLR, NOCPD, NOBROWNOUT, NOCLKOUT
#FUSES INTRC_IO, NOIESO, NOFCMEN, NOWRT, PLL_SW, NOSTVREN
#use delay(clock = 8000000) 
#use i2c(MASTER, SDA=PIN_B1, SCL=PIN_B4)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x08C
#byte TRISB = 0x08D
#byte OSCCON = 0x099
#byte OSCTUNE = 0x098
#byte DACCON0 = 0x118
#byte SRCON0 = 0x11A
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1
   
#define SLAVE1_WRT_ADDR   0xA8
#define SLAVE1_READ_ADDR  0xA9
//====================================

#INT_EXT
void ext_isr(void)
{
putc('\n');
putc('\r');
printf("test");
output_toggle(pin_b6);
}

void main()
{
TRISA = 0x20;
TRISB = 0x13;
OSCCON = 0x70;
OSCTUNE = 0;
DACCON0 = 0;
SRCON0 = 0;
setup_adc_ports(NO_ANALOGS);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(1)
{
   i2c_start();
   i2c_write(SLAVE1_wrt_ADDR);
   i2c_write(0x0F);
   delay_ms(10);   

   i2c_write(0x10);
   delay_ms(10);   

   i2c_write(0x18);
   delay_ms(10);   

   i2c_write(0xFF);
   delay_ms(10);   

   i2c_write(0xF0);
   delay_ms(10);   
   i2c_stop();
   
   delay_ms(100);
   output_toggle(pin_b7);
}
}

Code:
///------------------Slave-------------------------
#include <16F1827.H>
#fuses NOWDT,NOPUT,NOLVP,MCLR,NOCPD,NOBROWNOUT,NOCLKOUT
#FUSES INTRC_IO,NOIESO,NOFCMEN,NOWRT,PLL_SW,NOSTVREN
#use delay(clock = 8000000)
#use i2c(SLAVE, SDA=PIN_B1, SCL=PIN_B4, ADDRESS=0xA8)
#use rs232(baud=9600,parity=N,xmit=PIN_A0,rcv=PIN_A1,bits=8)
#byte TRISA = 0x08C
#byte TRISB = 0x08D
#byte OSCCON = 0x099
#byte OSCTUNE = 0x098
#byte DACCON0 = 0x118
#byte SRCON0 = 0x11A
#byte APFCON0 = 0x11D //ALTERNATE PIN FUNCTION CONTROL REGISTER 0
#byte APFCON1 = 0x11E //ALTERNATE PIN FUNCTION CONTROL REGISTER 1

volatile int8 datain[8];
volatile int8 state, readcnt, mdirect, data_ready;
volatile unsigned long stepamount;
#INT_SSP
void ssp_isr(void)
{
state = i2c_isr_state();
if(state < 0x80)     // Master is sending data
{
   datain[readcnt] = i2c_read();
   readcnt=readcnt+1;
   if(readcnt==6){
      data_ready=1;
      readcnt=0;
      output_toggle(pin_b7);
   }
}
if(state >= 0x80)   // Master is requesting data from slave
  {
   i2c_write(0xFF);
  }
}
#INT_EXT
void ext_isr(void)
{
output_toggle(pin_b6);
}
//======================================
void main ()
{
readcnt=0;
data_ready=0;
i2c_SlaveAddr(0xA8);
TRISA = 0x20;
TRISB = 0x13;
OSCCON = 0x70;
OSCTUNE = 0;
DACCON0 = 0;
SRCON0 = 0;
setup_adc_ports(NO_ANALOGS);//
enable_interrupts(INT_SSP);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);


while(1)
{
   
    if ((data_ready==1)&&(datain[1]=0x0F)&&(datain[5]=0xF0)){
      mdirect=datain[2];
      stepamount=make16(datain[4],datain[3]);
      printf("Direction: %X",mdirect);
      printf(" Step Amount: %4X\n\r",stepamount);
      for (int i=0;i<=6;i++){
         datain[i]=0;
      }
      data_ready=0;
      if (mdirect==0x10){
         output_toggle(pin_b5);
      }
      if (stepamount==0xFF18){
         output_toggle(pin_b6);
      }
   }
 }
}

_________________
There is nothing you can't do if you try
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