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 master receiving from slave
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

i2c master receiving from slave
PostPosted: Tue Feb 28, 2012 4:08 am     Reply with quote

Hi, I need to do such thing:

Master sends command to slave (both 18F4620) then based on the command slave sends back data to master.

So far I have going:
sending data from master - easy
receiving data by slave - easy
getting and writing time to ds1307 - easy so my i2c is OK

But what I cannot get going is master side being able to get message back from slave pic.

This is master side:

Code:

         i2c_start();   
                                         
         i2c_write(0xA0);       //select address of device to communicate with
         i2c_write(0x01);             //send actual command
         
         i2cread[0] = i2c_read();   //read back from slave
         i2c_stop();


Whatever I do I get 255 as a result, any suggestions. I cannot find any useful information how master side should look. I have followed code for ds1307 and it looks easy but whatever I do my 255 is always there.

This is slave side:
Code:

void ssp_interupt(void) {                                           
   state = i2c_isr_state();
   if(state < 0x80)  {               //master is sending data
      if (state == 0) {             
         c = i2c_read();             
         buffer[0] = c;
      }                     
      if (state == 1) { //command
         c = i2c_read();
         buffer[1] = c;         
      }                     
      if (buffer[1] == 0x01) { //command 0x01 -> send back 0x05
         i2c_write(0x05);
      }                                       
   }   

What wrong am I doing here?
Thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 6:40 am     Reply with quote

comments
0) is this real hardware or a simulation?

1) Rename your variable that gets the data ( i2cread[]) to say 'slave_data[]', 'data_from_first_slave'[]. ANYTHING other than what you have which is confusing and hard to read.

2. What value are your I2C bus pullup resistors?

3. Is the slave address actually 0xA0 ?

4. Post the slave's program,perhaps there's a typo?
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 8:26 am     Reply with quote

You also need to NACK the last byte you read in the master. See the description for i2c_read() in the manual or in the IDE (Help->Index I think ).
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 4:16 pm     Reply with quote

Quote:
comments
0) is this real hardware or a simulation?

YES IT IS - WORKING BOARDS, GOT I2C TALKING TO DS1307 IN REAL TIME - NO PROBLEMS THERE, SO IT IS MY ROUTINE ON MASTER SIDE WRONG FOR READING DATA BACK FROM SLAVE
Quote:

1) Rename your variable that gets the data ( i2cread[]) to say 'slave_data[]', 'data_from_first_slave'[]. ANYTHING other than what you have which is confusing and hard to read.

WILL DO

Quote:
2. What value are your I2C bus pullup resistors?

1k8 - WORKING WITH SERIAL EEPROMS AND DS1307 - ALL GOOD ON HARDWARE SIDE

Quote:
3. Is the slave address actually 0xA0 ?

YES IT IS

4. Post the slave's program,perhaps there's a typo?
Quote:
void ssp_interupt(void) {
state = i2c_isr_state();
if(state < 0x80) { //master is sending data
if (state == 0) {
c = i2c_read();
buffer[0] = c;
}
if (state == 1) { //command
c = i2c_read();
buffer[1] = c;
}
if (buffer[1] == 0x01) { //command 0x01 -> send back 0x05
i2c_write(0x05);
}
}

_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 4:17 pm     Reply with quote

Quote:
You also need to NACK the last byte you read in the master. See the description for i2c_read() in the manual or in the IDE (Help->Index I think ).


WILL DO TODAY, ANY EXAMPLES IN MEAN TIME? thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 4:36 pm     Reply with quote

He wants you to post a complete, short, compilable program, not just a function (please continue to use the CODE tags rather than the QUOTE tags so it is readable). That way he can toss it into his compiler and see what happens to help out.

As for an example. If you go to your compiler directory there is an examples folders. Look for a file called ex_slave.c, make a copy of it in your project directory, change the PIC settings to match your particular PIC, and see if that fixes anything.

I can't post the CCS example code because it is against the rules to do so, but it comes with the compiler when you install it.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 10:42 pm     Reply with quote

This is slave code, I am testing hardware and writing simple code which is going to check all parts of the circuit. Below I'll put master too in a moment.

Code:
#include <18F4620.h>
#device ADC=10
#include <ctype.h>
#include <stddef.h>
#include <string.h>

//=========DEFINE====================
#define RX                 PIN_C7            //    serial data receive pin
#define TX                 PIN_C6            //    serial data transmit pin
#define TX_ON              PIN_C5            //    serial TX on
#define STATUS             PIN_B2            //    status led
#define GOUT1              PIN_D7
#define GOUT2              PIN_D6
#define GOUT3              PIN_D5
#define GOUT4              PIN_D4
#define GOUT5              PIN_D3
#define GOUT6              PIN_D2
#define GOUT7              PIN_D1
#define GOUT8              PIN_D0
#define BUZZ               PIN_A4                                       
#define POWER              PIN_E1                             
#define BATTERY            PIN_E2     
#define MAINS_TEST         PIN_AN3                                     
#define POWER_TEST         PIN_AN4
#define BATTERY_TEST       PIN_AN5
#define INTMP              PIN_AN0 
#define TMP1               PIN_AN1 
#define TMP2               PIN_AN2 
#define SLOT0              PIN_B1
#define SLOT1              PIN_B0               
#define SLOT2              PIN_B3 
#define SLOT3              PIN_B4
#define SLOT4              PIN_B5
#define SLOT5              PIN_B6                                               
#define SLOT6              PIN_B7
#define SLOT7              PIN_C0
#define SLOT8              PIN_C1
#define SLOT9              PIN_C2
#define I2CSCL             PIN_C3                           
#define I2CSDA             PIN_C4
//===================================
                                                       

#FUSES H4
#FUSES MCLR                                       
#FUSES BROWNOUT
#FUSES NODEBUG
#FUSES NOPROTECT                               
#FUSES WDT32768                     
#FUSES PUT                                               
#FUSES NOCPD                                           
#FUSES NOXINST 
#use delay (clock=40M, oscillator=10M)                           
                                             
#use rs232(baud=19200,xmit=TX,rcv=RX,parity=n,bits=8,stop=1,RESTART_WDT,ERRORS,TIMEOUT=15)
#use i2c(slave, sda=I2CSDA, scl=I2CSCL, address=0xA0) 
                                                               
#use fixed_io(D_outputs=GOUT1,GOUT2,GOUT3,GOUT4,GOUT5,GOUT6,GOUT7,GOUT8)
#use fixed_io(A_outputs=BUZZ)
#use fixed_io(B_outputs=STATUS)
#use fixed_io(C_outputs=TX_ON,TX)
#use fixed_io(E_outputs=POWER,BATTERY)
                                         
int a, state, c, buffer[10];
int timer = 0;
int timerstep = 0;
int timerstep2 = 0;
int timerstep3 = 0;
short print = 0;
int adc_read = 0;
short readadc = 0;
int capture[8];
short captureready = 0
                                   
#int_RTCC

void timer0_isr(void) {
   clear_interrupt(int_RTCC);
   timer++;
   if (timer == 0) {
      output_high(STATUS);
   }
   if (timer == 0xFF) {
      timerstep++;       
   }
   if (timerstep == 128) {
      output_low(STATUS);
   }                                           
   if (timerstep == 0xFF) {
      timerstep2++;       
   }
   if (timerstep2 == 0xFF) {         
      timerstep3++;
      readadc = 1;
   }
   if (timerstep3 == 0x05) {

   }
}

#int_RDA                                                                             
                                                                             
void comms_rda(void) {
   int cap;                         
   
   for (a=0;a<8;a++) {
      cap = getc();
      capture[a] = cap;         
   } 
   captureready = 1;                         
   clear_interrupt(int_RDA);
}     
   
#INT_SSP                             
                                                                                                 
//==========================
void ssp_interupt(void) {                                           
 
   state = i2c_isr_state();

   if(state < 0x80)  {               //master is sending data
      if (state == 0) { //address
         c = i2c_read();             
         buffer[0] = c;
                                     
         if (c == 0xA0) {
            print = 1;
         }
      }                                     
      if (state == 1) { //command
         c = i2c_read();
         buffer[1] = c;         
      }                     
      if (state == 2) { //data1                     
         c = i2c_read();
         buffer[2] = c;
      }                                 
      if (state == 3) { //data2
         c = i2c_read();
         buffer[3] = c;   
      }
      if (state == 4) { //data3   
         c = i2c_read();           
         buffer[4] = c;           
      }
      if (state == 5) { //data4   
         c = i2c_read();
         buffer[5] = c;
      }
      if (state == 6) { //data5
         c = i2c_read();
         buffer[6] = c;       
      }                     
      if (state == 7) { //data6                     
         c = i2c_read();
         buffer[7] = c;
      }                                 
      if (state == 8) { //data7   
         c = i2c_read();
         buffer[8] = c;   
      }
      if (state == 9) { //data8   
         c = i2c_read();           
         buffer[9] = c;                   
      }
      if (buffer[1] == 0x01) { //command 0x00 -> send value of second timer
         i2c_write(timerstep2);
      }
      if (state > 9) { //data   
         clear_interrupt(int_SSP);
      }
   }   
   if(state == 0x80) {              //master is requesting data
      //i2c_write (0xFF);  //send requested data
   }
   
}                           
//==========================

//===================================           

//========CONTROL RX485 TX===========                         
void comms_TX_high(void) {                   
   output_high(TX_ON);
   delay_ms(10);
} //void                                                                                   

void comms_TX_low(void) {
   delay_ms(10);
   output_low(TX_ON);     
} //void                                         
                       
//=================================== 
void read_i2c(void) {

         if (buffer[0] == 0xA0) { //message for us                                                   
            if (buffer[1] == 0x00) { //command 0x00 -> input status 
               if (buffer[2] == 0x01) { //input 1
                  output_high(GOUT1);   
               }
               else {
                  output_low(GOUT1);   
               }
               if (buffer[3] == 0x01) { //input 2
                  output_high(GOUT2);   
               }
               else {
                  output_low(GOUT2);   
               }
               if (buffer[4] == 0x01) {  //input 3
                  output_high(GOUT3);   
               }
               else {
                  output_low(GOUT3);   
               }                 
               if (buffer[5] == 0x01) { //input 4
                  output_high(GOUT4);   
               }
               else {
                  output_low(GOUT4);   
               }
               if (buffer[6] == 0x01) { //input 5
                  output_high(GOUT5);   
               }
               else {
                  output_low(GOUT5);                             
               }
               if (buffer[7] == 0x01) { //input 6
                  output_high(GOUT6);                             
               }
               else {                         
                  output_low(GOUT6);   
               }
               if (buffer[8] == 0x01) { //input 7
                  output_high(GOUT7);   
               }
               else {
                  output_low(GOUT7);   
               }
               if (buffer[9] == 0x01) { //input 8
                  output_high(GOUT8);   
               }
               else {
                  output_low(GOUT8);           
               }
            }
           
         }                 
}
//===================================

void read_analogue_input(unsigned char adcParameter) { //capture analogue from temperature
 
   set_adc_channel(adcParameter);             
   adc_read = read_adc();

} //void
 

//=========MAIN PROGRAM==============             

void main() {  // main program                         

setup_wdt(WDT_ON);            //set watch dog timer
disable_interrupts(GLOBAL);                 
output_float(I2CSCL);                                 
output_float(I2CSDA);                                               
set_timer0(0);               
set_rtcc(0);
setup_timer_0(RTCC_INTERNAL | RTCC_8_BIT | T0_DIV_1); //set timer 0 parameters
setup_adc_ports(AN0_TO_AN5 | VSS_VDD); //set AD ports   
setup_adc(ADC_CLOCK_DIV_16 | ADC_TAD_MUL_16);  //ADC_CLOCK_INTERNAL |                 
setup_comparator(NC_NC_NC_NC);   //turn off comparators
enable_interrupts(GLOBAL);
enable_interrupts(int_ssp);      //enable serial i2c
enable_interrupts(int_rda);      //enable serial port
enable_interrupts(INT_RTCC);     //enable TIMERs                         
       
//=========BOOT UP===================       
                                           
   output_low(STATUS);
   output_low(TX_ON);           
   output_low(GOUT1);
   output_low(GOUT2);                               
   output_low(GOUT3);
   output_low(GOUT4);
   output_low(GOUT5);
   output_low(GOUT6);
   output_low(GOUT7);
   output_low(GOUT8);
   output_low(BUZZ);   
   output_low(POWER);
   output_low(BATTERY);
   output_high(BUZZ);
   delay_ms(150);
   output_low(BUZZ);         
   delay_ms(150); 
   output_high(BUZZ);
   delay_ms(150);
   output_low(BUZZ);
   delay_ms(150);
   output_high(BUZZ);
   delay_ms(150);
   output_low(BUZZ);
   
         output_high(STATUS);
         output_high(GOUT1);
         output_high(GOUT2);
         output_high(GOUT3);
         output_high(GOUT4);
         output_high(GOUT5);           
         output_high(GOUT6);
         output_high(GOUT7);
         output_high(GOUT8);                     
         output_high(POWER);
         output_high(BATTERY);                                 

         buffer[0]=0xFF; 
         buffer[1]=0xFF;                             
         buffer[2]=0xFF;
         buffer[3]=0xFF;   
         buffer[4]=0xFF;
         buffer[5]=0xFF; 
         buffer[6]=0xFF;                             
         buffer[7]=0xFF;
         buffer[8]=0xFF;   
         buffer[9]=0xFF;
         
   while(true) { //loop program
      restart_wdt();
     
      if (captureready == 1) {
         comms_TX_high();
         printf("%u:%u:%u:%u:%u:%u:%u:%u%c",capture[0],capture[1],capture[2],capture[3],capture[4],capture[5],capture[6],capture[7],0x0D);
         comms_TX_low();
         captureready = 0;
      }
     
      if (print == 1) {
         comms_TX_high();           
         printf("%u:%u:%u:%u:%u:%u:%u:%u:%u:%u%c",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5],buffer[6],buffer[7],buffer[8],buffer[9],0x0D);
         comms_TX_low();                           
         print = 0;
      }           
     
      read_i2c();
      int mains;
      if (readadc == 1) {
         read_analogue_input(0);
         long int ar1 = adc_read;
         read_analogue_input(1);                         
         long int ar2 = adc_read;
         read_analogue_input(2);
         long int ar3 = adc_read;
         read_analogue_input(3);                   
         long int ar4 = adc_read;
         read_analogue_input(4);
            if (ar4 > 10) {               
               mains = 1;   
            }                           
         long int ar5 = adc_read;                                     
         read_analogue_input(5);                                                   
         long int ar6 = adc_read;
         
         
         float ar1f = ar1;
         float ar2f = ar2;
         float ar3f = ar3;
         float ar4f = ar4;
         float ar5f = ar5;
         float ar6f = ar6;
         
         comms_TX_high();                                               
        // printf("1. %lu TMP0: %lu TMP1: %lu TMP2: %lu MAINS: %lu POWER: %lu BATTERY %c",ar1,ar2,ar3,ar4,ar5,ar6,0x0D);
         printf("2. %f TMP0: %f TMP1: %f TMP2: %f MAINS: %f POWER: %f BATTERY %c",ar1f/4.16,ar2f/4.68,ar3f/4.68,ar4f,ar5f/13.31,ar6f/13.31,0x0D);
         comms_TX_low();
         readadc = 0;                               
      }                                       
         
   } //while
                                                                                         
} //void   

_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Tue Feb 28, 2012 10:48 pm     Reply with quote

master code:


Code:
#include <18F4620.h>

#include <ctype.h>
#include <stddef.h>
#include <string.h>

//=========DEFINE====================
#define RX                 PIN_C7           
#define TX                 PIN_C6           
#define TX_ON              PIN_C5           
#define STATUS             PIN_D5                               
#define GIN1               PIN_B1
#define GIN2               PIN_B2
#define GIN3               PIN_A4
#define GIN4               PIN_B0                                           
#define GIN5               PIN_A3
#define GIN6               PIN_A2
#define GIN7               PIN_A1
#define GIN8               PIN_A0       
/*
#define LCD_E              PIN_A5
#define LCD_RS             PIN_B3                             
#define LCD_RW             PIN_B4
#define LCD_DB4            PIN_D3
#define LCD_DB5            PIN_D2
#define LCD_DB6            PIN_D1
#define LCD_DB7            PIN_D0
*/
#define BCK_LIGHT          PIN_D4
#define LK2                PIN_E2 
#define LK1                PIN_E1
#define SLOT10             PIN_D6
#define SLOT11             PIN_D7                                               
#define SLOT12             PIN_E0
#define SLOT13             PIN_B5
#define SLOT14             PIN_B6
#define SLOT15             PIN_B7
#define SLOT16             PIN_C0
#define SLOT17             PIN_C1
#define SLOT18             PIN_C2
#define I2CSCL             PIN_C3                           
#define I2CSDA             PIN_C4
 
//===================================

#FUSES H4                                   
#FUSES MCLR
#FUSES BROWNOUT
#FUSES NODEBUG
#FUSES NOPROTECT
#FUSES WDT32768   
#FUSES NOWDT
#FUSES PUT                                               
#FUSES NOCPD                                           
#FUSES NOXINST

//===================================                               
#use delay (clock=40M, oscillator=10M)                 
#use rs232(baud=19200,xmit=TX,rcv=RX,parity=n,bits=8,stop=1,RESTART_WDT,ERRORS,TIMEOUT=15)
#use i2c(master, sda=I2CSDA, scl=I2CSCL)
#include "flex_lcd.c"
#use fixed_io(D_outputs=LCD_DB4,LCD_DB5,LCD_DB6,LCD_DB7,BCK_LIGHT,STATUS) //LCD_DB4,LCD_DB5,LCD_DB6,LCD_DB7,BCK_LIGHT,STATUS
#use fixed_io(A_outputs=LCD_E) //LCD_E
#use fixed_io(B_outputs=LCD_RS,LCD_RW) //LCD_RS,LCD_RW
#use fixed_io(C_outputs=TX_ON, TX)

//===================================           
//===================================

BYTE bin2bcd(BYTE binary_value);  //clock data
BYTE bcd2bin(BYTE bcd_value);  //clock data
int a, day, mth, year, dow, hr, min, sec; //dow - day of the week
int timer = 0;
int timerstep = 0;
int timerstep2 = 0;
int timerstep3 = 0;
int instate[8];
int in[8];
short testinputs = 0;                                                                                                                                                       
short print = 0;
short print1 = 0;
short link1,link2;
int capture[8];                 
int i2cread[9];
short settime = 0;
short chktime = 0;
short ticked = 0;
short requesti2c = 0;
short printrda = 0;

//========CONTROL RX485 TX===========                         
void comms_TX_high() {                   
   output_high(TX_ON);
   delay_ms(10);
} //void                                                                                   

void comms_TX_low() {
   delay_ms(10);
   output_low(TX_ON);
} //void
 
//=================================== 

#int_RTCC

void timer0_isr(void) {         
   clear_interrupt(int_RTCC);
   timer++;
   if (timer == 0) {
      output_high(STATUS);
   }
   if (timer == 0xFF) {
      timerstep++;                   
   }                                     
   if (timerstep == 128) {                         
      output_low(STATUS);                                                                                                                                                         
   }
   if (timerstep == 0xFF) {
      timerstep2++;
      chktime = 1;
   }
   if (timerstep2 == 0xFF) {           
      timerstep3++; 
   }
   if (timerstep3 == 1) {           
      print = 1;
      timerstep3++;
   }
   if (timerstep3 == 3) {           
      print1 = 1;
      timerstep3 = 0;
   }                     
}

#int_RDA
                                                                             
void comms_rda(void) {     
   int c;                                 
   
   for (a=0;a<8;a++) {
      c = getc();
      capture[a] = c;               
   }
   printrda = 1;
   
   if (capture[0] == 0x00) { // set time   
      settime = 1;
   }
   if (capture[0] == 0x01) { // request data back from i2c
      requesti2c = 1;
   }
   
   clear_interrupt(int_RDA);

                                           
#int_SSP     
                                                                             
void comms_ssp(void) { 
   clear_interrupt(int_SSP);
}

void clrsrcn() {
   lcd_putc("\f\n");
}

//=================================== 
// note - DS1307 ADDRESSING D0 - WRITE, D1 - READ 
// note -
//=========I2C=======================
void send_to_i2c(BYTE destinationi2c, BYTE command, BYTE data1, BYTE data2, BYTE data3, BYTE data4, BYTE data5, BYTE data6, BYTE data7, BYTE data8) {
   i2c_start();                     //begin transmission
   i2c_write(destinationi2c);       //select address of device to communicate with
   i2c_write(command);             //send actual command
   i2c_write(data1);               //send actual data
   i2c_write(data2);               //send actual data
   i2c_write(data3);               //send actual data
   i2c_write(data4);               //send actual data
   i2c_write(data5);               //send actual data
   i2c_write(data6);               //send actual data
   i2c_write(data7);               //send actual data
   i2c_write(data8);               //send actual data   
   i2c_stop();                      //terminate communication
}
 
//=================================== 
 

//=========CLOCK=====================

/// ds1307_init() - Enable oscillator without clearing the seconds register -///
///                 used when PIC loses power and DS1307 run from 3V BAT     ///
///               - Disable squarewave output                                ///
///                                                                          ///
/// ds1307_set_date_time(day,mth,year,dow,hr,min,sec)  Set the date/time   ///
///                                                                          ///
/// ds1307_get_date(day,mth,year,dow)               Get the date             ///
///                                                                          ///
/// ds1307_get_time(hr,min,sec)                     Get the time             ///

BYTE bin2bcd(BYTE binary_value)
{
  BYTE temp;
  BYTE retval;

  temp = binary_value;
  retval = 0;

  while(1)
  {
    // Get the tens digit by doing multiple subtraction
    // of 10 from the binary value.                           
    if(temp >= 10)
    {
      temp -= 10;
      retval += 0x10;
    }
    else // Get the ones digit by adding the remainder.
    {
      retval += temp;
      break;
    }
  }

  return(retval);
}


// Input range - 00 to 99.       
BYTE bcd2bin(BYTE bcd_value)
{
  BYTE temp;

  temp = bcd_value;
  // Shifting upper digit right by 1 is same as multiplying by 8.
  temp >>= 1;
  // Isolate the bits for the upper digit.
  temp &= 0x78;

  // Now return: (Tens * 8) + (Tens * 2) + Ones

  return(temp + (temp >> 2) + (bcd_value & 0x0f));
}
                                     
void ds1307_init(void)
{
   BYTE seconds = 0;

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_start();                                                       
   i2c_write(0xD1);      // RD from RTC
   seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307
   i2c_stop();
   seconds &= 0x7F;

   delay_us(3);

   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x00);      // REG 0
   i2c_write(bin2bcd(seconds));     // Start oscillator with current "seconds value
   i2c_start();
   i2c_write(0xD0);      // WR to RTC
   i2c_write(0x07);      // Control Register
   i2c_write(0x80);     // Disable squarewave output pin
   i2c_stop();

}

void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec)
{
  sec &= 0x7F;
  hr &= 0x3F;

  i2c_start();                                                                       
  i2c_write(0xD0);            // I2C write address
  i2c_write(0x00);            // Start at REG 0 - Seconds
  i2c_write(bin2bcd(sec));      // REG 0
  i2c_write(bin2bcd(min));      // REG 1
  i2c_write(bin2bcd(hr));      // REG 2
  i2c_write(bin2bcd(dow));      // REG 3
  i2c_write(bin2bcd(day));      // REG 4
  i2c_write(bin2bcd(mth));      // REG 5
  i2c_write(bin2bcd(year));      // REG 6
  i2c_write(0x80);            // REG 7 - Disable squarewave output pin
  i2c_stop();
}

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x03);            // Start at REG 3 - Day of week
  i2c_start();
  i2c_write(0xD1);
  dow  = bcd2bin(i2c_read() & 0x7f);   // REG 3
  day  = bcd2bin(i2c_read() & 0x3f);   // REG 4
  mth  = bcd2bin(i2c_read() & 0x1f);   // REG 5
  year = bcd2bin(i2c_read(0));            // REG 6
  i2c_stop();
}

void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
  i2c_start();
  i2c_write(0xD0);
  i2c_write(0x00);            // Start at REG 0 - Seconds   
  i2c_start();
  i2c_write(0xD1);
  sec = bcd2bin(i2c_read() & 0x7f);
  min = bcd2bin(i2c_read() & 0x7f);
  hr  = bcd2bin(i2c_read(0) & 0x3f);
  i2c_stop();

}
//=========CLOCK I2C ENDS============

void set_time (void) {
   if (settime == 1) {
      printf(lcd_putc,"\f%02d-%02d-%02d %02d:%02d",day,mth,year,hr,min);
      printf(lcd_putc,"\n%u,%u,%u,%u,%u,%u,%u,%u",capture[0],capture[1],capture[2],capture[3],capture[4],capture[5],capture[6],capture[7]);
      ds1307_set_date_time(capture[1],capture[2],capture[3],capture[4],capture[5],capture[6],capture[7]);
      settime = 0;
   }
}
                                                   
void inputs(void) {
     
      in[0]=input(GIN1);
      in[1]=input(GIN2);
      in[2]=input(GIN3);
      in[3]=input(GIN4);
      in[4]=input(GIN5);
      in[5]=input(GIN6);         
      in[6]=input(GIN7);
      in[7]=input(GIN8);
     
      delay_ms(10); //debouncing delay
     
      if ((instate[0] != in[0]) || (instate[1] != in[1]) || (instate[2] != in[2]) || (instate[3] != in[3]) || (instate[4] != in[4]) || (instate[5] != in[5]) || (instate[6] != in[6]) || (instate[7] != in[7]))  { //change detected
         send_to_i2c(0xA0, 0x00, in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7]);   
      }
     
      instate[0] = in[0]; // copy state to buffer
      instate[1] = in[1]; // copy state to buffer           
      instate[2] = in[2]; // copy state to buffer
      instate[3] = in[3]; // copy state to buffer           
      instate[4] = in[4]; // copy state to buffer         
      instate[5] = in[5]; // copy state to buffer           
      instate[6] = in[6]; // copy state to buffer         
      instate[7] = in[7]; // copy state to buffer         
           
      int link1=input(LK1);
      int link2=input(LK2);
     
}     

void time(void) {
   ds1307_get_date(day,mth,year,dow);                         
   ds1307_get_time(hr,min,sec);
   chktime = 0;
}         
//=========MAIN PROGRAM============== 

void main() {  // main program
                                             
setup_wdt(WDT_ON);
output_float(I2CSCL);                                 
output_float(I2CSDA);
disable_interrupts(GLOBAL);
set_timer0(0);                             
set_rtcc(0);
setup_timer_0(RTCC_INTERNAL | RTCC_8_BIT | T0_DIV_1); //set timer 0 parameters
setup_adc(ADC_OFF);   
setup_comparator(NC_NC_NC_NC);   //turn off comparators
enable_interrupts(GLOBAL);
enable_interrupts(int_ssp);      //enable serial i2c
enable_interrupts(int_rda);      //enable serial port
enable_interrupts(INT_RTCC);     //enable TIMERs
                                                     
//=========BOOT UP===================

   lcd_init();
   
   output_low(BCK_LIGHT);
   
   lcd_putc("\BOOTING...\n");
   
   delay_us(1);
   for (a=0;a<8;a++) {       
      instate[0] =0;
   }

   output_Low(TX_ON);
   output_Low(STATUS);                   

   delay_ms(2000);
   output_high(STATUS);
   output_high(BCK_LIGHT);
   
   ds1307_init();                   
   
   in[0]=input(GIN1);
   in[1]=input(GIN2);
   in[2]=input(GIN3);
   in[3]=input(GIN4);
   in[4]=input(GIN5);
   in[5]=input(GIN6);         
   in[6]=input(GIN7);
   in[7]=input(GIN8);
     
   send_to_i2c(0xA0, 0x00, in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7]);   
   clrsrcn();
   output_high(BCK_LIGHT);
   
   while(true) { //loop program
      restart_wdt();                                           
     
      set_time();
                                                                             
      if (chktime == 1) {     
         time();
         chktime = 0;
      }
      if (print == 1) {                                           
         print = 0;                 
         printf(lcd_putc,"\f%02d-%02d-%02d %02d:%02d",day,mth,year,hr,min);         
         printf(lcd_putc,"\nDoW %u; HBIT: ",dow);
      }                 
      if (print1 == 1) {
         print1 = 0;
         printf(lcd_putc,"\f%02d-%02d-%02d %02d:%02d",day,mth,year,hr,min);
         printf(lcd_putc,"\nDoW %u; HBIT: *",dow);
      }
      if (requesti2c == 1) {
         printf(lcd_putc,"\f%02d-%02d-%02d %02d:%02d",day,mth,year,hr,min);
         printf(lcd_putc,"\nRS232->%u",capture[0]);
         delay_ms(500);
         i2c_start();   
                                         
         i2c_write(0xA0);       //select address of device to communicate with
         i2c_write(0x01);             //send actual command
         i2c_write(0x02);               //send actual data
         i2c_write(0x03);               //send actual data
         i2c_write(0x04);               //send actual data
         i2c_write(0x05);               //send actual data
         i2c_write(0x06);               //send actual data
         i2c_write(0x07);               //send actual data
         i2c_write(0x08);               //send actual data
         i2c_write(0x09);               //send actual data   
         
         i2cread[0] = i2c_read();   // read data back from slave
         i2c_stop();
         printf(lcd_putc,"\f%02d-%02d-%02d %02d:%02d",day,mth,year,hr,min);
         printf(lcd_putc,"\nI2C->%u",i2cread[0]);
         delay_ms(500);
         requesti2c = 0;     
      }                           
     
      if (printrda == 1) {
         //printf(lcd_putc,"\f%u,%u,%u,%u,%u,%u,%u,%u",capture[0],capture[1],capture[2],capture[3],capture[4],capture[5],capture[6],capture[7]);
         printrda = 0;
      }
      inputs();                                   
     
   } //while                                                                                                           
                             
} //void

_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Wed Feb 29, 2012 2:02 am     Reply with quote

...this is poorly a coding issue, 2 years ago I had it going Smile, I cannot find my code then... if I find it sure I will post it. I scratch my head over this. I think I remember that need to emulate eeprom on slave pic. I remember it was tricky but was working well. Going over all files from 2009 - I may find it Smile Thnx for any hints, will speed up work.

---

found something Smile gives a hint:

Code:
#if defined(__PCM__)
#include <16F628A.h>
#include <ctype.h>
#include <stddef.h>
#include <string.h>


#use delay (clock=20000000)      // oscillator frequency for delay_ms()

// Config: ext reset, no code protect, no watchdog, 20MHz int clock
#fuses MCLR,NOPROTECT,NOWDT,HS
#use rs232(baud=9600,parity=n,xmit=pin_B2,rcv=pin_B1,bits=8,stream=PC)
#use I2C(MASTER, scl=PIN_A0, sda=PIN_A1, stream=I2CM)
#use i2c(SLAVE, sda=PIN_B4, scl=PIN_B5, address=0xA0, force_hw, stream=I2CS)
#endif

//=========COMMS I2C============
//NOTE: Must declare MASTER before SLAVE, i2c_isr_state() returns 0
//      when MASTER is the most recent #use i2c

int rcv_buf[0x10];       
int wrt_buf[0x10];       
int cmd=0xFF;           

#int_spp // interrupt on i2c activity
void  i2c_isr(void)
{
    int state, incoming;
    state = i2c_isr_state();
   
    if(state < 0x80)
    {
        incoming = i2c_read(I2CS);
        if (state == 1)
        {                                                                                                               
            cmd = incoming;
        }
       
        else if (state > 1)
        {
            rcv_buf[state-2]=incoming;
        }
    }
    else
    {
        i2c_write(I2CS,wrt_buf[state-0x80]);
    }
}

//=========COMMS ENDS============

_________________
Help "d" others and then you shell receive some help from "d" others.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Feb 29, 2012 11:35 pm     Reply with quote

Comments on Master code:

Quote:

#use fixed_io(D_outputs=LCD_DB4,LCD_DB5,LCD_DB6,LCD_DB7,BCK_LIGHT,STATUS)
#use fixed_io(B_outputs=LCD_RS,LCD_RW)

You are using the lcd's r/w pin. This means the flex driver will read the
busy bit, which requires reading the LCD's data bus. This means you
should not set the LCD_DBx pins as "output only".

Quote:

#int_RDA
void comms_rda(void) {
int c;

for (a=0;a<8;a++) {
c = getc();
capture[a] = c;
}
.
.
.
}

The getc() loop is a mistake. You should only get one character per
interrupt. What if your program receives less than 8 bytes ? It would
lock up the program, while waiting for an 8th byte that might never
arrive. Or, what if your program receives a 9th byte ? It would re-enter
the #int_rda interrupt routine and wait there, locking up your program.
Look at the CCS Ex_sisr.c example file for a better method.

Quote:

#int_rda
void comms_rda(void) {
.
.
.
clear_interrupt(int_RDA);
}

The call to clear_interrupt() at the end is not necessary. The compiler
automatically inserts code to clear the RDA interrupt flag at the end of
the isr. Look at the .LST file (in Symbolic format) to see this.

Quote:

#int_SSP
void comms_ssp(void) {
clear_interrupt(int_SSP);
}

Same thing here.
Also, you don't need SSP interrupts for an i2c master. Remove this
routine and also remove the enable_interrupts(INT_SSP) line.

Quote:

void inputs(void) {
.
.
.
.
int link1=input(LK1);
int link2=input(LK2);


}

CCS doesn't support declaring variables at any place within a routine.
You should declare them only at the start of a routine.

Quote:

i2c_start();
i2c_write(0xA0); //select address of device to communicate with
i2c_write(0x01); //send actual command
i2c_write(0x02); //send actual data
i2c_write(0x03); //send actual data
i2c_write(0x04); //send actual data
i2c_write(0x05); //send actual data
i2c_write(0x06); //send actual data
i2c_write(0x07); //send actual data
i2c_write(0x08); //send actual data
i2c_write(0x09); //send actual data

i2cread[0] = i2c_read(); // read data back from slave
i2c_stop();

0xA0 is an i2c slave address used by EEPROM chips. I wouldn't use it
for a PIC slave. What if you decide to add an external EEPROM later ?
Choose some other address for your PIC slave.

Your protocol shown above is not normal for an i2c Master that writes
to the slave and then reads from it. Look at any of the CCS driver
files for i2c eeproms, such as the 24256.c file. They do a re-start
to begin a read operation. They send the i2c read address. You're not
doing any of that. They also do a NACK on the last i2c read.
You're not doing that either.

I didn't look at your code completely. There could be other problems.
Your slave code has similar problems.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 2:39 pm     Reply with quote

Some things I noticed about the slave code:

Code:

void ssp_interupt(void) {                                           
 
   state = i2c_isr_state();

   if(state < 0x80)  {               //master is sending data
     
      /* I cut this part out for readability*/

      if (buffer[1] == 0x01) { //command 0x00 -> send value of second timer
         i2c_write(timerstep2);
      }
      if (state > 9) { //data   
         clear_interrupt(int_SSP);
      }
   }   
   if(state == 0x80) {              //master is requesting data
      //i2c_write (0xFF);  //send requested data
   }
   
}           



1. Inside of the comparison state < 0x80 IF statement, you do an i2c_write(), which you should not be doing. You should only do a i2c_write() if your state is 0x80-0xFF

2. Inside of the comparison state == 0x80 IF statement, you do not do an i2c_read() which you should. The state 0x80 indicates that the address byte was sent with the "read/write" bit set to 0. You still have to read that before writing any data back.


Take a look at the example in the manual entry for i2c_isr_state(). It lists all the rules.

Also note that there is a bug (or maybe just an undocumented feature) with using i2c_isr_state(). If you use a data stream that is 128 bytes or longer, then on some compiler versions, you will get a 0x80 and higher for those bytes because the state counter keeps incrementing past 0x7f. If your data streams are always shorter than that, then you will never run into this.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 2:57 pm     Reply with quote

Quote:
found something gives a hint:

#include <16F628A.h>

#use rs232(baud=9600,parity=n,xmit=pin_B2,rcv=pin_B1,bits=8,stream=PC)
#use I2C(MASTER, scl=PIN_A0, sda=PIN_A1, stream=I2CM)
#use i2c(SLAVE, sda=PIN_B4, scl=PIN_B5, address=0xA0, force_hw, stream=I2CS)

Also, this code which you claim gives a hint, won't work at all for an i2c
slave. The 16F628A doesn't have an SSP or MSSP module. That means
there is no hardware i2c capability. That means it can't do an i2c slave
with the CCS #use i2c() library.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 10:58 pm     Reply with quote

Quote:
This means you
should not set the LCD_DBx pins as "output only".


will do thnx


Quote:
The getc() loop is a mistake.


this is test program to check if all circuit parts are working, main software will be different and much more sofisticated, I know that this bit is wrong, thnx

Quote:
The call to clear_interrupt() at the end is not necessary.


good to know, thnx

Quote:
Also, you don't need SSP interrupts for an i2c master. Remove this
routine and also remove the enable_interrupts(INT_SSP) line.


this is inherrited from trying to get it working, thnx for confirmation

Quote:
CCS doesn't support declaring variables at any place within a routine.
You should declare them only at the start of a routine.


dirty code, thnx

Quote:
0xA0 is an i2c slave address used by EEPROM chips. I wouldn't use it
for a PIC slave. What if you decide to add an external EEPROM later ?
Choose some other address for your PIC slave.


good idea, thnx

Quote:
Your protocol shown above is not normal for an i2c Master that writes
to the slave and then reads from it. Look at any of the CCS driver
files for i2c eeproms, such as the 24256.c file. They do a re-start
to begin a read operation. They send the i2c read address. You're not
doing any of that. They also do a NACK on the last i2c read.
You're not doing that either.


this I need to research, thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 11:03 pm     Reply with quote

Quote:
1. Inside of the comparison state < 0x80 IF statement, you do an i2c_write(), which you should not be doing. You should only do a i2c_write() if your state is 0x80-0xFF


this comes for trying to get it working, how do I define the state itself? what in Master is actually telling slave that it is <80 or >80?

Quote:
2. Inside of the comparison state == 0x80 IF statement, you do not do an i2c_read() which you should. The state 0x80 indicates that the address byte was sent with the "read/write" bit set to 0. You still have to read that before writing any data back.


any example here? I am not entirely understand this bit.


Quote:
Take a look at the example in the manual entry for i2c_isr_state(). It lists all the rules.


will do in a sec

Quote:
Also note that there is a bug (or maybe just an undocumented feature) with using i2c_isr_state(). If you use a data stream that is 128 bytes or longer, then on some compiler versions, you will get a 0x80 and higher for those bytes because the state counter keeps incrementing past 0x7f. If your data streams are always shorter than that, then you will never run into this.


good to know, thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
Linuxbuilders



Joined: 20 Mar 2010
Posts: 193
Location: Auckland NZ

View user's profile Send private message

PostPosted: Thu Mar 01, 2012 11:06 pm     Reply with quote

Quote:
Also, this code which you claim gives a hint, won't work at all for an i2c
slave. The 16F628A doesn't have an SSP or MSSP module. That means
there is no hardware i2c capability. That means it can't do an i2c slave
with the CCS #use i2c() library.


this is some old code I have found in my archives, I am not surprised but the hint is that there is use of master and slave within the code.

Quote:
#use I2C(MASTER, scl=PIN_A0, sda=PIN_A1, stream=I2CM)
#use i2c(SLAVE, sda=PIN_B4, scl=PIN_B5, address=0xA0, force_hw, stream=I2CS)


I have been reading about that before. I am not sure how much it is correct to use but people indicate that it works.

thnx
_________________
Help "d" others and then you shell receive some help from "d" others.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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