CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C slave help please??!!?? Works on 16F876 but not 18F2410

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
JamesW, Kent, England
Guest







I2C slave help please??!!?? Works on 16F876 but not 18F2410
PostPosted: Mon Dec 22, 2008 9:59 am     Reply with quote

Hi Folks,

The title says it all really.

I'm using I2C to communicate between two pics.

I originally used a 16F876 as the slave but lack of RAM caused me to change to an 18F2410. (I'm using the slave pic to drive a modem and send a text message, so I need a 160 character buffer for the message)

The code I used was based on the i2c slave eeprom example as included with the compiler.

compiler version 4,073

As mentioned the code works perfectly on the 876.

There are a number of other devices on the I2C bus and these are all communicating fine with the master (until I try to talk to the slave pic, then the bus hangs).

Using the ICD on the slave I can verify that it reaches the ISR. It only reaches the ISR when I address that device (ie a message is sent over i2c for device address 0xE0

I have an LED flashing off the timer interrupt on the slave pic, and this hangs when I try to transmit to the slave PIC.

Code:
/* HEADER FILE */
#include <18F2410.h>

#device ICD=TRUE
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV42                   //Brownout reset at 4.2V
#FUSES PUT                      //Power Up Timer
#FUSES NOSTVREN                 // NO Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    // NO Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT                    // NO Program memory not write protected
#FUSES NOIESO                   // NO Internal External Switch Over mode enabled
#FUSES NOFCMEN                  // NO Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //NO PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //NO Boot block not write protected
#FUSES NOEBTR                   //NO  Memory not protected from table reads
#FUSES NOEBTRB                  // Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES NOLPT1OSC                // NO Timer1 configured for low-power operation
#FUSES MCLR                     // Master Clear pin enabled
#FUSES NOXINST                  // NO Extended set extension and Indexed Addressing mode enabled


#use delay(clock=20000000)

#use rs232(baud=115200, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xE0)


/* PIC INTERNAL REGISTERS */
#byte  port_c  = 0xF82
#byte  port_b  = 0xF81
#byte  port_a  = 0xF80

/* TRIS REGISTERS */
#byte  tris_a  = 0xF92 /* 0x85 */
#byte  tris_b  = 0xF93 /* 0x86 */
#byte  tris_c  = 0xF94 /* 0x87 */
JamesW, Kent, England
Guest







PostPosted: Mon Dec 22, 2008 9:59 am     Reply with quote

The I2C code is here...

Code:
/* SERIAL PORT DEFINITIONS */
#define COM2_BUFFER_SIZE 10

unsigned int COM2_buffer[COM2_BUFFER_SIZE];
unsigned int COM2_next_in = 0;
unsigned int COM2_next_out = 0;

/* COMMAND 0x00 IS A WRITE TO THE PROTOCOL BUFFER */
/* COMMAND 0x01 IS A WRITE TO THE I/O PORTS       */

#byte PIC_SSPBUFF=0xFC9
#byte PIC_SSPADD=0xFC8
#byte PIC_SSPSTAT=0xFC7
#byte PIC_SSPCON1=0xFC6
#byte PIC_SSPCON2=0xFC5
#bit CKP   = PIC_SSPCON1.4      // 1 = Release Clock, 0 = Holds Clock Low (clock stretch)
#bit SEN   = PIC_SSPCON2.0      // 1 = Clock Stretching Enabled for Slave Tx and Rx, 0 = Clock Stretching Enabled for Slave Tx only
#bit BF    = PIC_SSPSTAT.0      // B1 = data transmit in progress, 0 = data transmit complete
#bit WCOL  = PIC_SSPCON1.7      // I2C Write Collision
#bit SSPOV = PIC_SSPCON1.6      // I2C Buffer Overflow
#bit SSPEN = PIC_SSPCON1.5      // Synchronus Serial Port Enable Bit
/* -------------------------------------------------------------------------- */
/* GLOBAL VARIABLES */

unsigned int Command;


/* THIS IS THE STATE OF THE SYSTEM TO BE POLLED BY MASTER UNIT */
/* BIT 7 =                                                     */
/* BIT 6 =                                                     */
/* BIT 5 =                                                     */
/* BIT 4 =                                                     */
/* BIT 3 = MODEM POWER STATE                                   */
/* BIT 2 = MODEM STATE                                         */
/* BIT 1 = MODEM STATE                                         */
/* BIT 0 = MODEM STATE                                         */

unsigned int SystemState = 0;


/* ------------------------------------------------------------------------- */
#INT_SSP
void ssp_interupt ()
{
 
   unsigned int Data, state, t;
 
   state = i2c_isr_state();

   /* MASTER UNIT IS SENDING DATA */
   if (state < 0x80)
   {
 
      Data = i2c_read();

      /* FIRST BYTE RECEIVED IS THE i2C COMMAND */
      if(state == 1)       
      {
         Command = Data;
      }
     
      /* WRITE */
      if (state == 2)
      {
     
         /* WRITE DATA PORT COMMAND - 0x01 */
         if (Command == 0x01)
         {
            /* BIT 0 IS PIN C0 STATE */
            if( bit_test(Data,0))
            {
               output_low(PIN_C0);
            }
            else
            {
               output_high(PIN_C0);
            }

         } /* END COMMAND = 1 */
         /* ELSE ADD TO THE PSEUDO SERIAL PORT BUFFER  */
         else
         {
            COM2_buffer[COM2_next_in] = Data;
           
            t = COM2_next_in;
           
            COM2_next_in = (COM2_next_in + 1) % COM2_BUFFER_SIZE;
           
            if(COM2_next_in == COM2_next_out)
            {
              COM2_next_in = t;           /* Buffer full !! */
            }
         } /* END COM2 DATA */
      } /* END WRITE */
   }/* STATE < 0x80 */
   
   /* MASTER IS REQUESTING DATA */
   if(state == 0x80)
   {
      i2c_write(SystemState);
   }
   
   /* DEBUG AS SUGGESTED BY CCS FORUM POSTS */
   if (SSPOV==1)
   {
       SSPOV=0;
   }
   if (BF==1)
   {
       Data = i2c_read();
   }
   
}

/* ------------------------------------------------------------------------- */
#define COM2_kbhit (COM2_next_in != COM2_next_out)
/* ------------------------------------------------------------------------- */

unsigned char COM2_bgetc()
{
   unsigned char c;

   while(!COM2_kbhit);
   
   c = COM2_buffer[COM2_next_out];
   COM2_next_out = (COM2_next_out+1) % COM2_BUFFER_SIZE;

   return(c);
}

/* ------------------------------------------------------------------------- */
/* END OF CODE */
Guest








PostPosted: Mon Dec 22, 2008 10:01 am     Reply with quote

And the main code ...
Code:

#include "Pic_I2C_Slave.h"
#include <ctype.h>

#include "sleep.c"
#include "i2c.c"
#include "protocol.c"
#include "modem.c"



/* -------------------------------------------------------------------------- */
void main ()
{
   unsigned char DataToSendToModem = 0;

 
   TRIS_A = 0b00000000;
   TRIS_C = 0b10111000;
   TRIS_B = 0b00001001;
   
   
   /* TURN OFF THE MODEM */
   output_low(TC65_POWER);      /* POWER    */
   output_low(TC65_IGNITION);   /* IGNITION */
   output_low(TC65_EMERGENCY);  /* E-RESET */
   
   /* SETUP THE I2C BUS */
   output_float(PIN_C3);
   output_float(PIN_C4);
   
   output_high(PIN_C0);
   output_high(PIN_C1);
   output_high(PIN_C2);

   /* INITIALISE THE TIMER INTERRUPT */
   Timer_init();
   enable_interrupts(INT_SSP);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);

 

 
   /* TURN ON THE MODEM */
//   output_high(TC65_POWER);
   
   //delay_ms(1000);
   
  // output_high(TC65_IGNITION); /* TURN ON THE MODEM IGNITION */
   
   for (;;)
   {
      /* IF WE HAVE RECIEVED ANYTHING FROM THE I2C BUS IN "RS232 MODE" */
      if (COM2_kbhit)
      {
         delay_us(1);
     
         /* ADD DATA TO PACKET - ROUTINE RETURNS 1 IF PACKET COMPLETE */
         if (RecievePacket(COM2_bgetc()) == 1)
         {
            /* IF SO - PROCESS IT */
            ProcessPacket();
         
         }
         

      }
     
      delay_us(1);
}

}
JamesW, Kent, England
Guest







PostPosted: Mon Dec 22, 2008 10:03 am     Reply with quote

As mentioned, I haven't bothered trying to get the packet processing side working yet, as the system hangs when I just try to write the port command to it.

Any suggestions would be gratefully received

Cheers

James
JamesW, Kent, England
Guest







PostPosted: Mon Dec 22, 2008 10:08 am     Reply with quote

Using the debugger to inspect the values, neither of the two error flags are set.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 22, 2008 12:50 pm     Reply with quote

You need to prove that the 18F2410 can work as an i2c slave.
Start with a simple test program. Use the Ex_Slave.c program
for the slave PIC. It's in this directory:
Quote:
Quote:
c:\Program Files\picc\Examples\Ex_Slave.c


Use the code in this post for the Master PIC:
http://www.ccsinfo.com/forum/viewtopic.php?t=32368&start=3
Change the #include, #fuses, and #use delay() statements to fit
your hardware.

See if this simple test works. Make sure you have pull-ups on the
i2c lines (4.7K will work).
JamesW, Kent, England
Guest







PostPosted: Mon Dec 22, 2008 1:49 pm     Reply with quote

Thanks,

I will try this first thing tomorrow.

At close of play today I've resorted to ordering an I2C SRAM and was thinking about unsoldering the 18F4610 and putting the 16F876 back in and using software I2C to talk to the ram - but it seems such a waste.

Cheers

James
JamesW, Kent, England
Guest







PostPosted: Tue Jan 13, 2009 4:54 pm     Reply with quote

I tried all of the above, with no sucess.

I've had a reply from Microchip technical saying that in certain 18F parts there are some slave addresss that are "reserved" and as such may not work - this may be the issue, but time is pressing and so I can't devote any more time to debugging this.

As is, I've replaced the part with a 16F876 and (I know that Microchip have this flagged as approaching obsolescence but they are in plentiful supply at the moment).

Thanks for the help

James
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