|
|
View previous topic :: View next topic |
Author |
Message |
Bill_Smith
Joined: 06 Feb 2004 Posts: 26 Location: Curitiba, Brazil
|
#Use I2C() and SSP interrupts not working on PIC16F883 |
Posted: Sun Aug 17, 2008 11:33 pm |
|
|
I have a really strange I2C problem that I want to share with you all in hopes that someone can shed some light on a solution.
Hardware:
PIC16F883 (On the MCP1631 Multi-Chemistry Battery Charger Reference Design Demo Board)
Compiler:
CCS PCWHD version 4.077
ICD Environment:
MPLAB 8.14 with RealICE debugger
Problem #1:
The #use i2c(SLAVE, SDA=PIN_C3, SCL=PIN_C4, ADDRESS=0x22) compiler directive does not setup the PIC16F883 MSSP module. The following code was compiled and run on the target board.
Code: |
#include <16F883.h>
#device ADC=10
#fuses INTRC,NOWDT,MCLR,DEBUG,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOCPD
#use delay(clock=8000000) // 8MHz Clock
#use i2c(SLAVE, SDA=PIN_C3, SCL=PIN_C4, ADDRESS=0x22)
#byte SSPSTAT = 0x094
#byte SSPCON2 = 0x091
#byte SSPADD = 0x093
#byte SSPCON = 0x014
#byte PIR1 = 0x00C
#bit GCEN = SSPCON2.7
#bit SSPIF = PIR1.3
#INT_SSP
void ssp_interupt(void)
{
if(SSPIF)
SSPIF = 0;
delay_us(1);
delay_us(1);
delay_us(1);
}// End ISR SSP
void main(void)
{
setup_oscillator(OSC_8MHZ,0); //set oscillator to 8Mhz
set_tris_c (0b00011000); // C3 and C4 are INPUTS
//SSPCON = 0b00110110;
GCEN = 1; // Allow General Calls
//SSPADD = 0x22; // Slave Device Address
enable_interrupts(INT_SSP); // Enable I2C Interrupts
enable_interrupts(GLOBAL); // Enable Global Interrupts
while(TRUE)
{
}
}
|
Debugger Watch Window shows:
Address Symbol Name Value
014 SSPCON 00000000
091 SSPCON2 10000000
094 SSPSTAT 00000000
093 SSPADD 0x00
00C PIR1 00000000
013 SSPBUF 0x44
Then I checked to see if I could directly set the register values.
Code: |
#include <16F883.h>
#device ADC=10
#fuses INTRC,NOWDT,MCLR,DEBUG,NOPROTECT,NOLVP,NOBROWNOUT,NOPUT,NOCPD
#use delay(clock=8000000) // 8MHz Clock
//#use i2c(SLAVE, SDA=PIN_C3, SCL=PIN_C4, ADDRESS=0x22)
#byte SSPSTAT = 0x094
#byte SSPCON2 = 0x091
#byte SSPADD = 0x093
#byte SSPCON = 0x014
#byte PIR1 = 0x00C
#bit GCEN = SSPCON2.7
#bit SSPIF = PIR1.3
#INT_SSP
void ssp_interupt(void)
{
if(SSPIF)
SSPIF = 0;
delay_us(1);
delay_us(1);
delay_us(1);
}// End ISR SSP
void main(void)
{
setup_oscillator(OSC_8MHZ,0); //set oscillator to 8Mhz
set_tris_c (0b00011000); // C3 and C4 are INPUTS
SSPCON = 0b00110110;
GCEN = 1; // Allow General Calls
SSPADD = 0x22; // Slave Device Address
enable_interrupts(INT_SSP); // Enable I2C Interrupts
enable_interrupts(GLOBAL); // Enable Global Interrupts
while(TRUE)
{
}
}
|
This time when running the compiled program, I get the expected results.
Debugger Watch Window shows:
Address Symbol Name Value
014 SSPCON 00110110
091 SSPCON2 10000000
094 SSPSTAT 00000000
093 SSPADD 0x22
00C PIR1 00000000
013 SSPBUF 0x44
Problem #2:
INT_SSP never occurs.
With a known GOOD I2C Master, I generated a simple QuickWrite transaction, which essentially sends the following:
i2c_start(); // [START]
ack = i2c_write((address<<1)|0x00); // [ADDRESS + W]
i2c_stop(); // [STOP]
I set a breakpoint on the first delay_us(1); statement in the SSP_ISR and ran the program.
Without any code in the SSP isr I am not expecting it to respond, but i did expect the SSP interrupt to occur and stop at the breakpoint. This did not happen.
I ran this same code on a PIC16F88 target board and everything works as expected.
Does anyone have any suggestions? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 18, 2008 12:32 am |
|
|
Quote: | #use i2c(SLAVE, SDA=PIN_C3, SCL=PIN_C4, ADDRESS=0x22) |
You have the SDA and SCL pins reversed. That's why the code
generation is not correct.
Quote: | i2c_start(); // [START]
ack = i2c_write((address<<1)|0x00); // [ADDRESS + W]
i2c_stop(); // [STOP] |
What is contents of the 'address' variable before it is shifted left ?
I want to check if you are confusing the 8-bit slave address format
used by CCS and Microchip, and the 7-bit format used by Philips. |
|
|
Bill_Smith
Joined: 06 Feb 2004 Posts: 26 Location: Curitiba, Brazil
|
|
Posted: Mon Aug 18, 2008 11:39 am |
|
|
Wow PCM, sorry about this. I guess I need some sleep. You were spot on with the pins being reversed and the device address. Changing the #use i2c statement to the following loaded all the MSSP registers correctly.
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, ADDRESS=0x44)
Rolling the device address bits 1 position to the left so that I am loading the SPPADD register with [0x44], instead of [0x22], solved the No SSP_INT problem as well. I guess CCS must have recently changed how the compiler interprets the I2C Slave address. I could have sworn it used to be as I first had it.
Anyway everything is working now. Thank you for your help.
|
|
|
danishamjad
Joined: 28 Apr 2015 Posts: 1 Location: Pakistan
|
Same Issue-- Interrupt is not firing |
Posted: Tue Apr 28, 2015 9:56 am |
|
|
I am trying simple project to study i2c. I am using PIC18F4550 and CCS PIC C compiler.
Here is a scenario.
Master:
1. Button is connected to PIN_E1.
2. When Button is pressed, it sends code 0x01 to slave.
3. When Button is pressed again, it sends code 0x02 to slave.
Slave:
1. Only one slave is connected. It's address is 0x0a.
2. When it receives 0x01, it should turn LED on connected at PIN_E0.
3. When it receives 0x02, it should turn LED off.
I was observing SCL and SDA on oscilloscope and found correct pattern always, when the button is pressed.
But interrupt in slave is not working at all. I just changed slave scenario:
1. LED is turned off at first.
2. Whenever interrupt is fired it should remain turn on.
Here is my slave code:
Code: |
#include <18F4550.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES CPUDIV4 //System Clock by 4
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#use delay(crystal=20000000, clock=5000000)
#use i2c(SLAVE, sda=PIN_B0, scl=PIN_B1, address=0x0a, force_hw)
BYTE address, buffer[0x10];
#INT_SSP
void ssp_interupt (){
BYTE incoming, state;
state = i2c_isr_state();
if(state < 0x80) //Master is sending data
{
incoming = i2c_read();
if(state == 1) //First received byte is address
address = incoming;
if(state == 2) //Second received byte is data
buffer[address] = incoming;
}
if(state == 0x80) //Master is requesting data
{
i2c_write(buffer[address]);
}
output_high(PIN_E0);
}
void main()
{
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
set_tris_B ( 0b01111111 );
set_tris_e(0x06);
output_low(PIN_E0);
while(1){}
}
|
Kindly, tell me if I'm doing something wrong. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|
|
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
|