|
|
View previous topic :: View next topic |
Author |
Message |
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
Strange thing with i2c |
Posted: Wed Apr 30, 2008 4:14 am |
|
|
I have encountered this strange thing with the i2c_isr_state() This is my source:
Code: |
#include <18F2520.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES H4 //High speed with 4xPLL enabled
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#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)
#use delay(clock=40000000)
#define I2C_SCL PIN_C3
#define I2C_SDA PIN_C4
#use i2c(Slave,sda=PIN_C4,scl=PIN_C3,force_hw,address=0x10)
void Init()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_16,124,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
set_pwm1_duty(0);
set_pwm2_duty(0);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//enable_interrupts(INT_EXT);
//enable_interrupts(INT_EXT1);
enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);
}
#define HR1 PIN_A0
#define HL1 PIN_A1
#define LR1 PIN_A2
#define LL1 PIN_A3
#define HR2 PIN_B2
#define HL2 PIN_B3
#define LR2 PIN_B4
#define LL2 PIN_B5
#define BCKWRD 0
#define STOP 1
#define FRWRD 2
#define LEFT 3
#define RIGHT 4
struct Motor
{
int16 line;
int16 turn;
int16 error;
int16 pwm;
int status;
unsigned int32 pos;
};
void Init_Motors(void);
void Motor_Control(int direct, int16 speed, int m);
int value_X = 140, value_Y = 140;
struct Motor M1;
struct Motor M2;
#int_EXT
void EXT1_isr(void)
{
M1.pos++;
}
#int_EXT1
void EXT2_isr(void)
{
M2.pos++;
}
#int_SSP
void SSP_isr(void)
{
int incoming, state;
state = i2c_isr_state();
if(state < 0x80)
{
incoming = i2c_read();
if(state == 0)
value_X = incoming;
if(state == 1)
value_Y = incoming;
}
}
void Init_Motors(void)
{
output_bit(HR1, 0);
output_bit(HL1, 0);
output_bit(LL1, 1);
output_bit(LR1, 1);
M1.line = 0;
M1.turn = 0;
M1.error = 0;
M1.pwm = 0;
M1.status = STOP;
M1.pos = 0;
output_bit(HR2, 0);
output_bit(HL2, 0);
output_bit(LL2, 1);
output_bit(LR2, 1);
M2.line = 0;
M2.turn = 0;
M2.error = 0;
M2.pwm = 0;
M2.status = STOP;
M2.pos = 0;
}
void Motor_Control(int direct, int16 speed, int m)
{
switch(m)
{
case 1:
M1.line = speed;
M1.pwm = M1.line + M1.turn + M1.error;
set_pwm1_duty(M1.pwm);
switch(direct)
{
case BCKWRD:
output_bit(HR1, 0);
output_bit(LL1, 0);
output_bit(HL1, 1);
output_bit(LR1, 1);
M1.status = BCKWRD;
break;
case FRWRD:
output_bit(HL1, 0);
output_bit(LR1, 0);
output_bit(HR1, 1);
output_bit(LL1, 1);
M1.status = FRWRD;
break;
case STOP:
output_bit(HR1, 0);
output_bit(HL1, 0);
output_bit(LL1, 1);
output_bit(LR1, 1);
M1.status = STOP;
break;
}
break;
case 2:
M2.line = speed;
M2.pwm = M2.line + M2.turn + M2.error;
set_pwm2_duty(M2.pwm);
switch(direct)
{
case BCKWRD:
output_bit(HR2, 0);
output_bit(LL2, 0);
output_bit(HL2, 1);
output_bit(LR2, 1);
M2.status = BCKWRD;
break;
case FRWRD:
output_bit(HL2, 0);
output_bit(LR2, 0);
output_bit(HR2, 1);
output_bit(LL2, 1);
M2.status = FRWRD;
break;
case STOP:
output_bit(HR2, 0);
output_bit(HL2, 0);
output_bit(LL2, 1);
output_bit(LR2, 1);
M2.status = STOP;
break;
}
break;
}
}
void main()
{
int i = 0;
Init();
Init_Motors();
Motor_Control(FRWRD, 128, 1);
} |
When it is compiled and loaded everything works fine, but it is theoreticaly wrong. When i2c_isr_state() is 0 this means that the address is received and matched. But if I write Code: |
#int_SSP
void SSP_isr(void)
{
int incoming, state;
state = i2c_isr_state();
if(state < 0x80)
{
incoming = i2c_read();
if(state == 1)
value_X = incoming;
if(state == 2)
value_Y = incoming;
}
}
| this is how it is supposed to be, I get the value for value_Y in value_X and the value in value_Y is always 16 which is 0x10, which is the addres of the slave. I havent faced this problem before... I use PIC182520 for the first time, but I don't think this makes any difference. Any ideas what is the reason for this strange problem ? |
|
|
Matro Guest
|
|
Posted: Wed Apr 30, 2008 4:21 am |
|
|
Could you try with the following line
added at the beginning of your code?
And could you post a part of .lst corresponding to #INT_SSP function?
Matro |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Wed Apr 30, 2008 5:37 am |
|
|
Here is the .lst file with #opt 0:
Code: |
#int_SSP
.................... void SSP_isr(void)
.................... {
.................... int incoming, state;
.................... state = i2c_isr_state();
00E2: BTFSC FC7.5
00E4: GOTO 00EE
00E8: CLRF 34
00EA: BTFSC FC9.0
00EC: BSF 34.7
00EE: MOVF 34,W
00F0: INCF 34,F
00F2: MOVWF 3D
.................... if(state < 0x80)
00F4: MOVF 3D,W
00F6: SUBLW 7F
00F8: BTFSS FD8.0
00FA: GOTO 011E
.................... {
.................... incoming = i2c_read();
00FE: BTFSS FC7.0
0100: GOTO 00FE
0104: MOVFF FC9,3C
.................... if(state == 0)
0108: MOVF 3D,F
010A: BTFSS FD8.2
010C: GOTO 0114
.................... value_X = incoming;
0110: MOVFF 3C,18
.................... if(state == 1)
0114: DECFSZ 3D,W
0116: GOTO 011E
.................... value_Y = incoming;
011A: MOVFF 3C,19
.................... }
.................... }
} |
And this is without the #opt 0 statement:
Code: | #int_SSP
.................... void SSP_isr(void)
.................... {
.................... int incoming, state;
.................... state = i2c_isr_state();
00E2: BTFSC FC7.5
00E4: BRA 00EC
00E6: CLRF 34
00E8: BTFSC FC9.0
00EA: BSF 34.7
00EC: MOVF 34,W
00EE: INCF 34,F
00F0: MOVWF 3D
.................... if(state < 0x80)
00F2: MOVF 3D,W
00F4: SUBLW 7F
00F6: BNC 0110
.................... {
.................... incoming = i2c_read();
00F8: BTFSS FC7.0
00FA: BRA 00F8
00FC: MOVFF FC9,3C
.................... if(state == 0)
0100: MOVF 3D,F
0102: BNZ 0108
.................... value_X = incoming;
0104: MOVFF 3C,18
.................... if(state == 1)
0108: DECFSZ 3D,W
010A: BRA 0110
.................... value_Y = incoming;
010C: MOVFF 3C,19
.................... }
.................... } |
There is now effect on matter wether there is #opt 0 or there isn't. |
|
|
Ttelmah Guest
|
|
Posted: Wed Apr 30, 2008 7:48 am |
|
|
What are you actually sending?.
Best Wishes |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Wed Apr 30, 2008 10:45 am |
|
|
Here is the source of the sender:
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=10000000)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3,force_hw)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
void INIT(void)
{
set_tris_c(0x80);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(NO_ANALOGS);
setup_psp(PSP_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
}
#define START_BYTE 0x41
int c;
int value_X, value_Y;
void main()
{
INIT();
for(;;)
{
if(kbhit())
{
c = getc();
if(c == START_BYTE)
{
value_X = getc();
value_Y = getc();
i2c_start();
i2c_write(0x10);
i2c_write(value_X);
i2c_write(value_Y);
i2c_stop();
}
}
}
} |
Firstly I've used PIC18F4431 and there were no problems, than I've changed to PIC18F2520 and this complication appeared. |
|
|
Ttelmah Guest
|
|
Posted: Wed Apr 30, 2008 2:26 pm |
|
|
Try with the receive routine like this:
Code: |
#int_SSP
void SSP_isr(void)
{
int incoming, state;
state = i2c_isr_state();
if(state < 0x80)
{
if(state == 1)
value_X = I2C_READ();
else if(state == 2)
value_Y = I2C_READ(0);
else incoming=I2C_READ();
}
}
|
Best Wishes |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Fri May 23, 2008 4:17 pm |
|
|
Excuse me for the delay, but I had some problems...this routine
Code: | #int_SSP
void SSP_isr(void)
{
int incoming, state;
state = i2c_isr_state();
if(state < 0x80)
{
if(state == 1)
value_X = I2C_READ();
else if(state == 2)
value_Y = I2C_READ(0);
else incoming=I2C_READ();
}
} | does not work :( Any other ideas ? I have used I2C successfully with 3 PIC16F887A...this is very frustrating :( |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Sat May 24, 2008 1:34 am |
|
|
I decided to test the problem more extensively. I have changed the slave address to 0xA0 and put all the received bytes into an array and this is the result: Code: | (137,130,160,137,129,160,137,130,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) |
The first thing that I noticed is that the first byte is not the slave address, but the first data byte... Next the last received byte is not the last data byte, but the slave address... The problem is not in the sender either, here it is its source:
Code: |
#include <16F88.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8)
#use i2c(Master,sda=PIN_B1,scl=PIN_B4, Fast, force_sw)
#define I2C_SDA PIN_B1
#define I2C_SCL PIN_B4
#define START_BYTE 0x41
#define LED PIN_B0
int c;
int value_X, value_Y;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
output_bit(LED, 0);
for(;;)
{
if(kbhit())
{
c = getc();
if(c == START_BYTE)
{
value_X = getc();
value_Y = getc();
output_bit(LED, 1);
i2c_start();
i2c_write(0xA0);
i2c_write(value_X);
i2c_write(value_Y);
i2c_stop();
output_bit(LED, 0);
}
}
}
} |
This might be some kind of bug, but I am not sure, most of the times the bug is in the writer of the source :P |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Sat May 24, 2008 1:37 am |
|
|
I decided to test the problem more extensively. I have changed the slave address to 0xA0 and put all the received bytes into an array and this is the result: Code: | (137,130,160,137,129,160,137,130,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) |
The first thing that I noticed is that the first byte is not the slave address, but the first data byte... Next the last received byte is not the last data byte, but the slave address... The problem is not in the sender either, here it is its source:
Code: |
#include <16F88.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES BROWNOUT //Reset when brownout detected
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8)
#use i2c(Master,sda=PIN_B1,scl=PIN_B4, Fast, force_sw)
#define I2C_SDA PIN_B1
#define I2C_SCL PIN_B4
#define START_BYTE 0x41
#define LED PIN_B0
int c;
int value_X, value_Y;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
output_bit(LED, 0);
for(;;)
{
if(kbhit())
{
c = getc();
if(c == START_BYTE)
{
value_X = getc();
value_Y = getc();
output_bit(LED, 1);
i2c_start();
i2c_write(0xA0);
i2c_write(value_X);
i2c_write(value_Y);
i2c_stop();
output_bit(LED, 0);
}
}
}
} |
Another strange thing is that the controller does not perform any other task but the #INT_SSP routine.
This might be some kind of bug, but I am not sure, most of the times the bug is in the writer of the source :P |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat May 24, 2008 12:02 pm |
|
|
Quote: | #use i2c(Master,sda=PIN_B1,scl=PIN_B4, Fast, force_sw) |
Don't run the master in Fast mode. Microchip doesn't guarantee that
the SSP hardware will work in fast mode. |
|
|
sv_shady
Joined: 07 Mar 2008 Posts: 28
|
|
Posted: Sun May 25, 2008 7:57 am |
|
|
Just in case someone else encounters the same problem, or is just curios what's the soluten I have slightly changed the interrupt routine: Code: | #int_SSP
void SSP_isr(void)
{
int incoming, state;
output_bit(LED, 1);
incoming = i2c_read();
state = i2c_isr_state();
if(state < 0x80)
{
if(state == 1)
value_X = incoming;
if(state == 2)
{
value_Y = incoming;
cmds = 1;
}
}
output_bit(LED, 0);
} |
First I read the incoming byte then get the i2c_isr_state() value. I don't know why it shoud be like this but everything now works perfectly even in Fast mode I wonder if there is some explanation or it is just some kind of a bug ? |
|
|
|
|
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
|