|
|
View previous topic :: View next topic |
Author |
Message |
jmorrow333 Guest
|
I2C and PIC18F6722 |
Posted: Thu Mar 20, 2008 8:19 pm |
|
|
Hello,
I am having an odd issue with using the I2C bus to communicate between 2 PIC18F6722 chips. It works in FAST mode but not SLOW mode. The oscilloscope shows all normal until reading back to the slave (see comment in code). I would leave in FAST mode but the I2C locks up about once per day.
Slave code is from EX_SLAVE.C example.
The master settings are
Does not work with
Code: | #use i2c(Master,sda=PIN_C4,scl=PIN_C3,force_hw) |
But does work with
Code: | #use i2c(Master,fast, sda=PIN_C4,scl=PIN_C3,force_hw) |
Code to read 2 bytes from the slave is:
Code: | i2c_start();
i2c_write(0xA0); // slave address write
i2c_write(4); // data area to read from
i2c_start();
i2c_write(0xA1); // slave address read
StatByte= i2c_read(); // SDA line is stuck low here
BillState = i2c_read(0);
i2c_stop(); |
Compiler version is 3.249
Thanks for your help.
John |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 20, 2008 8:33 pm |
|
|
Post the slave program. Show the #include, #fuses, #use delay(),
and #use statements. The program should be compilable without errors. |
|
|
jmorrow333 Guest
|
|
Posted: Thu Mar 20, 2008 8:50 pm |
|
|
Here is the slave interrupt code and fuses. I didn't post the full code it is 3k lines long.
Thanks!
Code: |
#include <18F6722.h>
//#define USE_ICD
#ifdef USE_ICD
#device ICD=TRUE
#FUSES NOWDT
#FUSES DEBUG //Debug mode for ICD
#else
#FUSES WDT
#FUSES NODEBUG //No Debug mode for ICD
#endif
#device adc=8
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES BBSIZ1K //1K words Boot Block size
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=COM1)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=8,stream=COM2)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,force_hw)
//Interrupts are set up as
enable_interrupts(INT_RDA);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
// I2C interrupt routine
#int_SSP
SSP_isr()
{
char incoming, state, offset,Temp;
/*
I2C comm with processor 2
Commands
Poll 1 Any Data?
Stack Bill 2 Stack the bill
Return Bill 3 Return the Bill
Get Data 4 Get the data
Replys
ACK 0x10 No data
Bill inserted 0x11 Bill has been inserted into bill accepter
Mag read 0x12 Mag read has occured
Barcode read 0x12 Barcode read has occured
Data 0x13 Return data in response to get data command
*/
state = i2c_isr_state();
if(state < 0x80){ //Master is sending data
incoming = i2c_read();
if(state == 0){ //First received byte determines which buffer data goes into
TargetBuffer = incoming;
}
if(state == 1){ //Second received byte is offset for that buffer
Offset = incoming;
}
if(state >= 2){ // all rest of bytes go into the buffer
switch(TargetBuffer){
case 1:
if((offset+state-2)<150){
InBufferMagReader[offset+state-2] = incoming;
}
else{
MagSerPortEn = FALSE; // Shut down the port
I2COutBuffer[0] = (I2COutBuffer[0]&0x01)|(PortStates<<1); // Send new port states
SendPortStatesFlag = TRUE; // Notify SS of new settings
}
break;
case 2:
if((offset+state-2)<100){
InBufferBarcodeReader[offset+state-2] = incoming;
}
else{
BarcodeSerPortEn = FALSE; // Shut down the port
I2COutBuffer[0] = (I2COutBuffer[0]&0x01)|(PortStates<<1); // Send new port states
SendPortStatesFlag = TRUE; // Notify SS of new settings
}
break;
case 3:
InBufferBillAccepter[offset+state-2] = incoming;
break;
// no case 4 -- no write to buffer, use for reading from slave
} // end switch
} // end state >=2
} // end state < 0x80
if(state >= 0x80){ //Master is requesting data
i2c_write(I2COutBuffer[state-0x80]); // GBO 2/6/08
if((state-0x80) == 1) // GBO 2/6/08
I2COutBuffer[1] = 0; // GBO 2/6/08
}
} |
John |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 20, 2008 9:52 pm |
|
|
Quote: | Here is the slave interrupt code and fuses.
#FUSES LVP
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,force_hw) |
1. You should only use LVP if you're using a Low Voltage Programmer.
Very few people ( < 1%) use an LVP programmer. If you have
an ICD2, ICD-U40, etc., then change the fuse to NOLVP.
Do that in all your programs.
2. Your #use i2c() statement is for master mode. For slave mode, you
need to change it to 'Slave' and also specify the slave address.
3. Also, I would add ERRORS to both of your #use rs232() statements.
4. Probably, you should add a #priority statement and give the SSP
interrupt priority over the RDA interrupt. |
|
|
Guest
|
|
Posted: Fri Mar 21, 2008 5:55 am |
|
|
Oops, I posted the fuses for the master.
Good catch on the RS232 errors, I usually do.
Errata #7 for the 8722 family recommends not using high priority interrupts due to an error in the fast return (RETFIE)
Thanks.
Fuses for Slave
Code: | #include <18F6722.h>
//#define USING_ICD
#ifdef USING_ICD
#device ICD=TRUE
#FUSES DEBUG //Debug mode for use with ICD
#FUSES NOWDT
#else
#FUSES NODEBUG
#FUSES WDT
#endif
#device adc=8
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV25 //Brownout reset at 2.5V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES BBSIZ1K //1K words Boot Block size
#use delay(clock=20000000, restart_wdt)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=COM1,enable=PIN_F5,errors)
#use rs232(baud=9600,parity=N,xmit=PIN_G1,rcv=PIN_G2,bits=8,stream=COM2,errors)
#use i2c(Slave,slow,sda=PIN_C4,scl=PIN_C3,force_hw,address=0xa0) |
John |
|
|
|
|
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
|