|
|
View previous topic :: View next topic |
Author |
Message |
snock
Joined: 10 Oct 2011 Posts: 24
|
SSP question |
Posted: Fri Aug 17, 2012 7:55 am |
|
|
Does anyone know if the SSP module will work independently of the CPU? I have an application which consists of input and output cards each with a PIC that reads data over i2c. I'm having transient issues with the relay output card which cause the card to lockup but I can still read data back from it over the i2c bus.
Has anyone here ever had this issue and what was done to resolve it? I set up the WDT but it doesn't seem to work.
I compiled this with v4.050 Here is the code:
Code: |
// ************ RAINDROP CONTROL SUBSYSTEM QR16 RELAY OUTPUT CARD **************
// * Version 1.0 *
// * Project P008-QR16 Rev 0 *
// * Device: PIC16F882-I/SO SOIC-28 *
// * ------------------------------------------------------------------------- *
// * 12/12/11 (v1.1) - Added default i2c address. *
// * 04/03/12 (v1.2) - Added watchdog timer and brownout detect *
// *****************************************************************************
#include<16f882.h>
#fuses XT, MCLR, WDT, NOLVP, BROWNOUT, BORV40, NODEBUG, NOFCMEN, PUT
#use delay(clock=4MHz)
#use fast_io(b)
#use fast_io(c)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xa0, force_hw, slow)
// * PORT A DEFINITIONS ********************************************************
#define Q8 PIN_A0
#define Q9 PIN_A1
#define Q10 PIN_A2
#define Q11 PIN_A3
#define Q12 PIN_A4
#define IO_FLT PIN_A5
// *****************************************************************************
// * PORT B DEFINITIONS ********************************************************
#define Q0 PIN_B0
#define Q1 PIN_B1
#define Q2 PIN_B2
#define Q3 PIN_B3
#define Q4 PIN_B4
#define Q5 PIN_B5
#define Q6 PIN_B6
#define Q7 PIN_B7
// *****************************************************************************
// * PORT C DEFINITIONS ********************************************************
#define ADDR0 PIN_C0
#define ADDR1 PIN_C1
#define ADDR2 PIN_C2
#define SCL PIN_C3
#define SDA PIN_C4
#define Q13 PIN_C5
#define Q14 PIN_C6
#define Q15 PIN_C7
// *****************************************************************************
// * PORT E DEFINITIONS ********************************************************
#define SHDN PIN_E3
// *****************************************************************************
// * PROGRAM DEFINITIONS *******************************************************
// *****************************************************************************
#zero_ram
#byte ANSEL=0x188
static int8 mem_addr;
static int8 card_data[20];
// * I2C INTERRUPT HANDLER *****************************************************
#int_ssp
void i2c_handler(void) {
int8 state;
state=i2c_isr_state();
if(state<0x80) { // Master is sending data
if(state==1) mem_addr=i2c_read(1); // Store the address
if(state==2) card_data[mem_addr]=i2c_read(1); // Read and store the data
}
if(state>=0x80) { // Master is requesting data
i2c_write(card_data[mem_addr]); // Write the memory over i2c
}
}
// *****************************************************************************
// * OUTPUT CONTROL ROUTINE ****************************************************
void set_output(int1 bank, int8 value) {
if(!bank) {
output_b(value); // Write to bank A
} else { // Write to bank B
output_a(value & 0x1f); // Write first five bits
output_c(value & 0xe0); // Write last three bits
}
}
// *****************************************************************************
// * MAIN ROUTINE **************************************************************
void main(void) {
int8 i2c_address;
set_tris_b(0b00000000); // Set port B direction
set_tris_c(0b00011111); // Set port C direction
set_tris_e(0b00001000); // Set port E direction
setup_adc_ports(NO_ANALOGS);
setup_comparator(NC_NC_NC_NC);
setup_wdt(WDT_18MS | WDT_ON);
ANSEL=0; // Bug work around
output_b(0); // Clear relays on port B
output_c(0); // Clear relays on port C
output_float(IO_FLT); // Float the I/O fault line
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
i2c_address=(~input_c() & 0x07)<<5; // Read address switch at startup
if(i2c_address==0) i2c_address=1<<5; // Default if not set
i2c_slaveaddr(i2c_address); // Assign i2c address
while(TRUE) { // Loop forever
restart_wdt(); // Restart the watchdog timer
card_data[0]=10; // Card is a QR16 relay card
card_data[1]=0; // Set status byte, do more with later
set_output(0,card_data[10]); // Write bank A value
set_output(1,card_data[11]); // Write bank B value
}
}
// ***************************************************************************** |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19554
|
|
Posted: Fri Aug 17, 2012 8:44 am |
|
|
If you are able to read data from the I2C, then the CPU is still running OK. This is why the watchdog doesn't trigger.
Get rid of the 'slow' keyword. _Only master devices have a speed setting_. Having this can cause problems, programming illegal combinations into the registers.....
4.050, is _before_ CCS V4 really worked. Late V4.07x compilers were the first ones that had most features working. This could be a second problem.
In state 0x80 in the INT_SSP, you must read the register, before writing the reply. The effect of not doing this varies between chips, but failure to do this, can cause erratic behaviour of the I2C peripheral. If you look at the examples, the 'read' section uses <=0x80, while the write section uses >=0x80, so both transactions are done in state 0x80.
What happens to your code, if state==3 or more?. Though (presumably) you don't expect this to happen, you should always handle such things.
You should not enable INT_SSP, till _after_ you have setup the slave address.
Best Wishes |
|
|
snock
Joined: 10 Oct 2011 Posts: 24
|
|
Posted: Fri Aug 17, 2012 1:29 pm |
|
|
Thanks for the pointers. I just determined that what you said is indeed correct. The CPU is still running it's just that i2c isn't working at the point it locks up. I will implement your suggestions and see how things turn out. Thanks a lot. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9249 Location: Greensville,Ontario
|
|
Posted: Fri Aug 17, 2012 4:17 pm |
|
|
hmm...
"I'm having transient issues with the relay output card"...
Might also be hardware related.
Have you got suppression diodes across the relays (if mechanical types) ??
To verify relays are the cause of the transients, replace with LEDs and resistors and run the program.
Also be sure the power supply and power lines to the relays are hefty enough for the power levels the relays need. Your PIC VDD may be 'dipping' long enough to just enough to cause 'transient' problems.
hth
jay |
|
|
|
|
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
|