View previous topic :: View next topic |
Author |
Message |
JamesW, Kent, England Guest
|
I2C slave help please??!!?? Works on 16F876 but not 18F2410 |
Posted: Mon Dec 22, 2008 9:59 am |
|
|
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 */ |
|
|
![](templates/subSilver/images/spacer.gif) |
JamesW, Kent, England Guest
|
|
Posted: Mon Dec 22, 2008 9:59 am |
|
|
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 */ |
|
|
![](templates/subSilver/images/spacer.gif) |
Guest
|
|
Posted: Mon Dec 22, 2008 10:01 am |
|
|
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);
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
JamesW, Kent, England Guest
|
|
Posted: Mon Dec 22, 2008 10:03 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
JamesW, Kent, England Guest
|
|
Posted: Mon Dec 22, 2008 10:08 am |
|
|
Using the debugger to inspect the values, neither of the two error flags are set. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 22, 2008 12:50 pm |
|
|
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). |
|
![](templates/subSilver/images/spacer.gif) |
JamesW, Kent, England Guest
|
|
Posted: Mon Dec 22, 2008 1:49 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
JamesW, Kent, England Guest
|
|
Posted: Tue Jan 13, 2009 4:54 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
|