|
|
View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
i2c_isr_state |
Posted: Sat Jul 21, 2007 1:50 pm |
|
|
I'm working on an I2C master slave pair. If I send writes to the slave it behaves, but when I read it never acts like it see the read.
Here is the master code
Code: |
////////////**************8Test code for master*********/////////////////////
relaynumber=1;
while(1)
{
output_low(PIN_B7);
BoardAddress=0x50;
i2c_start();
i2c_write(BoardAddress); //Address
delay_ms(15);
i2c_write(20); // command for pour
delay_ms(15);
i2c_write(relaynumber); // send relay num
delay_ms(15);
i2c_write(4); // send time to pour
delay_ms(15);
i2c_stop();
Output_high(PIN_B7);
delay_ms(1500);
relaynumber++;
if(relaynumber>8)
relaynumber=1;
while(value==0) // 0 means still working, 1 means finished
{
printf("asking slave board if it is finished\r\n");
i2c_start(); // start condition
i2c_write(BoardAddress + 1);
value = i2c_read(0);
i2c_stop();
// delay_ms(500);
}
}
////////////**************8Test code for master*********/////////////////////
|
and here is the slave interrupt code
Code: |
#INT_SSP
void ssp_interupt ()
{
int i;
BYTE incoming, state;
donepouring=0;
state = i2c_isr_state();
printf("i2c state = %d\r\n",state);
if(state < 0x80) //Master is sending data
{
if(state >0)//data not address
{
bytecounter++;
if(bytecounter>42)// too many bytes, somethign is wrong
{
bytecounter=0;
printf("i2c overflow\r\n");
return;
}
incoming = i2c_read();
buffer[bytecounter] = incoming;
if(bytecounter ==3 ) //First received byte is address
{
if(buffer[1]==20) //pour command
{
SERIAL_BUFFER[0]='p';
SERIAL_BUFFER[1]=' ';
SERIAL_BUFFER[2]=49; //board address
SERIAL_BUFFER[3]=':';
SERIAL_BUFFER[4]=buffer[2]+48; // relay num
SERIAL_BUFFER[5]=':';
SERIAL_BUFFER[6]=buffer[3]+48; // time
SERIAL_BUFFER[7]='\r';
printf("I2c received");
for(i=1;i<=3;i++)
printf(" %d ",buffer[i]);
printf("\r\n");
printf("i2c sending command to pour ");
for(i=0;i<=7;i++)
putc(SERIAL_BUFFER[i]);
printf("\r\n");
bytecounter =0;
pour();
}
}
if(bytecounter ==8 ) //First received byte is address
{
for(i=1;i<=8;i++)
printf(" %x ",buffer[i]);
printf("\r\n");
printf("buffer[8]= %d \r\n",buffer[8]);
if((buffer[1]==0) && (buffer[2]==0xa0)
&& (buffer[3]==0) && (buffer[4]==0xaa)
&& (buffer[5]==0) && (buffer[6]==0xa5)
&& (buffer[7]==0))
{
NODE_ADDR=buffer[8];
PIC_SSPADD=NODE_ADDR;// change address
write_EEPROM (0,NODE_ADDR);// save new address
actionflag=2; //0 = nothing, 1 = read, 2 = change address
}
bytecounter=0;
}
}
}
if(state == 0x80) //Master is requesting data
{
i2c_write(donepouring);
output_low(PIN_B6);
output_low(PIN_B7);
delay_ms(100);
output_high(PIN_B6);
output_high(PIN_B7);
actionflag=1; //0 = nothing, 1 = read, 2 = change address
}
}
|
The master sends a command to the slave to activate a relay for a few seconds. As soon as the slave sees a command it sets donepouring=0; When it is finished a few seconds later it sets donepouring=1;
I would expect the master to loop until the slave is finished then move on. But if I take out the 1500ms delay in the mast loop then it does not work. Also b6, b7 never toggle on the slave so I think the state==0x80 is not firing.
the output from the printf's looks like this
i2c state = 0
i2c state = 1
i2c state = 2
i2c state = 3
I2c received 20 8 4
i2c sending command to pour p 1:8:4
pouring relay# 8 for 4 time
done pouring
The weird part to me is I have another master slave pair that only reads from the slave, and the interrupt code for 0x80 is the same and the read code is the same. Anybody see what I'm missing here? I could leave big delays in but would rather know when the lave is finished.
Thanks
Ringo _________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Sun Jul 22, 2007 10:26 am |
|
|
I narrowed the problem down to this code.
Code: |
value=1;
while(value==0) // 0 means still working, 1 means finished
{
output_low(PIN_B6);
delay_ms(500);
i2c_start(); // start condition
i2c_write(BoardAddress + 1);
value = i2c_read(0);
i2c_stop();
output_high(PIN_B6);
}
|
The program always skips the code. It never enters the wile loop. It executes code before and after it. If I change the while loop to a for loop it executes the code. Any ideas why this would happen?
I'm using CCS PCM C Compiler, Version 4.007.
Ringo _________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Sun Jul 22, 2007 10:35 am |
|
|
If I compile with CCS PCM C Compiler, Version 4.007 I get the funky problem I mentioned before. If I try to use 3.249 then I get out of ram errors. Is there a line I'm missing or something to make 3.249 work with ram better?
This is what 4.007 says
CCS PCM C Compiler, Version 4.007, 34836 22-Jul-07 12:16
Filename: F:\fw\Bartender\Bartender.lst
ROM used: 3105 words (38%)
Largest free fragment is 2048
RAM used: 154 (42%) at main() level
186 (51%) worst case
Stack: 6 worst case (1 in main + 5 for interrupts)
So it looks like I should have plenty. Why does 3.249 say I'm out of ram?
Here is my header stuff in case it helps.
#include <16F876a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_c6, rcv=PIN_c7)
#include <stdlib.h>
Thanks
Ringo _________________ Ringo Davis |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 22, 2007 10:38 am |
|
|
Quote: | Is there a line I'm missing or something to make 3.249 work with ram better? |
Add the items shown in bold below. The 2nd line enables use of all RAM
in the 16F-series PICs. (It's not needed for the 18F-series).
Quote: | #include <16F876a.h>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=19200, xmit=PIN_c6, rcv=PIN_c7, ERRORS)
#include <stdlib.h> |
|
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Sun Jul 22, 2007 10:47 am |
|
|
Thanks, That lets me compile with 3.249 but the code still does not execute. What am I missing?
Here is the C code and the code from the .lst file.
This code never executes
Code: |
value=1;
while(value==0) // 0 means still working, 1 means finished
{
output_low(PIN_B6);
delay_ms(5000);
i2c_start(); // start condition
i2c_write(BoardAddress + 1);
value = i2c_read(0);
i2c_stop();
output_high(PIN_B6);
}
|
Here is the corresponding lst code. It has been too long since I looked at assembly. Can anyone spot somethign wrong here?
.................... value=1;
0C20: MOVLW 01
0C21: MOVWF 5D
.................... while(value==0) // 0 means still working, 1 means finished
.................... {
0C22: MOVF 5D,F
0C23: BTFSS 03.2
0C24: GOTO 4A2
.................... output_low(PIN_B6);
0C25: BCF 06.6
0C26: BCF 03.5
0C27: BCF 06.6
.................... delay_ms(5000);
0C28: MOVLW 14
0C29: BSF 03.5
0C2A: MOVWF 5F
0C2B: BCF 03.5
0C2C: CLRF 28
0C2D: BTFSC 0B.7
0C2E: BSF 28.7
0C2F: BCF 0B.7
0C30: MOVLW FA
0C31: BSF 03.6
0C32: MOVWF 11
0C33: BCF 0A.3
0C34: BCF 03.6
0C35: CALL 3E0
0C36: BSF 0A.3
0C37: BTFSC 28.7
0C38: BSF 0B.7
0C39: BSF 03.5
0C3A: DECFSZ 5F,F
0C3B: GOTO 42B
.................... i2c_start(); // start condition
0C3C: BCF 03.5
0C3D: BSF 30.4
0C3E: MOVF 30,W
0C3F: BSF 03.5
0C40: MOVWF 07
0C41: MOVLW 04
0C42: MOVWF 77
0C43: DECFSZ 77,F
0C44: GOTO 443
0C45: BCF 03.5
0C46: BSF 30.3
0C47: MOVF 30,W
0C48: BSF 03.5
0C49: MOVWF 07
0C4A: MOVLW 03
0C4B: MOVWF 77
0C4C: DECFSZ 77,F
0C4D: GOTO 44C
0C4E: BCF 03.5
0C4F: BCF 07.4
0C50: BCF 30.4
0C51: MOVF 30,W
0C52: BSF 03.5
0C53: MOVWF 07
0C54: MOVLW 04
0C55: MOVWF 77
0C56: DECFSZ 77,F
0C57: GOTO 456
0C58: BCF 03.5
0C59: BCF 07.3
0C5A: BCF 30.3
0C5B: MOVF 30,W
0C5C: BSF 03.5
0C5D: MOVWF 07
.................... i2c_write(BoardAddress + 1);
0C5E: MOVLW 01
0C5F: ADDWF 5B,W
0C60: MOVWF 5F
0C61: BCF 03.5
0C62: CLRF 28
0C63: BTFSC 0B.7
0C64: BSF 28.7
0C65: BCF 0B.7
0C66: BSF 03.5
0C67: MOVF 5F,W
0C68: BCF 03.5
0C69: BSF 03.6
0C6A: MOVWF 11
0C6B: BCF 0A.3
0C6C: BCF 03.6
0C6D: CALL 3F4
0C6E: BSF 0A.3
0C6F: BTFSC 28.7
0C70: BSF 0B.7
.................... value = i2c_read(0);
0C71: CLRF 77
0C72: CLRF 28
0C73: BTFSC 0B.7
0C74: BSF 28.7
0C75: BCF 0B.7
0C76: BCF 0A.3
0C77: CALL 162
0C78: BSF 0A.3
0C79: BTFSC 28.7
0C7A: BSF 0B.7
0C7B: MOVF 78,W
0C7C: BSF 03.5
0C7D: MOVWF 5D
.................... i2c_stop();
0C7E: BCF 03.5
0C7F: BCF 30.4
0C80: MOVF 30,W
0C81: BSF 03.5
0C82: MOVWF 07
0C83: NOP
0C84: BCF 03.5
0C85: BSF 30.3
0C86: MOVF 30,W
0C87: BSF 03.5
0C88: MOVWF 07
0C89: BCF 03.5
0C8A: BTFSC 07.3
0C8B: GOTO 48E
0C8C: BSF 03.5
0C8D: GOTO 489
0C8E: MOVLW 04
0C8F: MOVWF 77
0C90: DECFSZ 77,F
0C91: GOTO 490
0C92: NOP
0C93: NOP
0C94: NOP
0C95: BSF 30.4
0C96: MOVF 30,W
0C97: BSF 03.5
0C98: MOVWF 07
0C99: MOVLW 04
0C9A: MOVWF 77
0C9B: DECFSZ 77,F
0C9C: GOTO 49B
.................... output_high(PIN_B6);
0C9D: BCF 06.6
0C9E: BCF 03.5
0C9F: BSF 06.6
.................... } _________________ Ringo Davis |
|
|
Ringo42
Joined: 07 May 2004 Posts: 263
|
|
Posted: Sun Jul 22, 2007 10:55 am |
|
|
I'm an idiot.
should be
value=0;
while(value==0)
DUHHHHHHH! _________________ Ringo Davis |
|
|
|
|
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
|