| View previous topic :: View next topic |
| Author |
Message |
Linuxbuilders
Joined: 20 Mar 2010 Posts: 193 Location: Auckland NZ
|
|
Posted: Tue Aug 18, 2015 3:00 am |
|
|
this seem to be working well, I had a look at the ex_slave.c example and it shows up state 1 as an address which is confusing a little because the manual says this:
| Quote: | If 0x00 or 0x80 is returned, an i2C_read( ) needs to be performed to read the I2C address that was
sent (it will match the address configured by #USE I2C so this value can be ignored) |
Any light on it? The other thing is that somehow I am unable to use c = i2c_read(); just once and reload the data into a buffer, it is unstable when I do that, now sure why.
| Code: | void ssp_interupt(VOID)
{
byte c;
state = i2c_isr_state ();
IF (state <= 0x80) // send data here
{
switch (state)
{
case 0x80:
i2c_read(2);
break;
case 0:
c = i2c_read();
i2cbuffer[0] = c;
IF (c == 0xA0)
{
process_i2c = 1;
}
else
{
process_i2c = 0;
}
break;
case 1:
c = i2c_read();
i2cbuffer[1] = c;
break;
case 2:
c = i2c_read();
i2cbuffer[2] = c;
break;
case 3:
c = i2c_read();
i2cbuffer[3] = c;
break;
case 4:
c = i2c_read();
i2cbuffer[4] = c;
break;
case 5:
c = i2c_read();
i2cbuffer[5] = c;
break;
case 6:
c = i2c_read();
i2cbuffer[6] = c;
break;
case 7:
c = i2c_read();
i2cbuffer[7] = c;
break;
case 8:
c = i2c_read();
i2cbuffer[8] = c;
break;
case 9:
c = i2c_read();
i2cbuffer[9] = c;
break;
default:
i2c_read();
break;
}
}
IF (state >= 0x80) // read data from here
{
IF (i2cbuffer[0] == 0xA0)
{
check_data_to_i2c ();
i2cdata = read_back;
i2c_write (i2cdata);
SSP_locked = 0;
}
}
} |
_________________ Help "d" others and then you shell receive some help from "d" others. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Tue Aug 18, 2015 3:16 am |
|
|
The confusion is on the word 'address'.
There are two addresses in I2C.
The device address.
The register address.
State 0/0x80 returns the device address.
Then the next I2C operation (state 1), is normally used to send the register address. |
|
 |
Linuxbuilders
Joined: 20 Mar 2010 Posts: 193 Location: Auckland NZ
|
|
Posted: Tue Aug 18, 2015 3:21 am |
|
|
correction:
| Code: |
void ssp_interupt(VOID)
{
int c;
state = i2c_isr_state ();
IF (state <= 0x80) // send data here
{
if (state == 0x80)
{
i2c_read(2);
}
else
{
c = i2c_read();
}
switch (state)
{
case 0:
i2cbuffer[0] = c;
IF (c == 0xA0)
{
process_i2c = 1;
}
else
{
process_i2c = 0;
}
break;
case 1:
i2cbuffer[1] = c;
break;
case 2:
i2cbuffer[2] = c;
break;
case 3:
i2cbuffer[3] = c;
break;
case 4:
i2cbuffer[4] = c;
break;
case 5:
i2cbuffer[5] = c;
break;
case 6:
i2cbuffer[6] = c;
break;
case 7:
i2cbuffer[7] = c;
break;
case 8:
i2cbuffer[8] = c;
break;
case 9:
i2cbuffer[9] = c;
break;
default:
break;
}
}
IF (state >= 0x80) // read data from here
{
IF (i2cbuffer[0] == 0xA0)
{
check_data_to_i2c ();
i2cdata = read_back;
i2c_write (i2cdata);
SSP_locked = 0;
}
}
} |
_________________ Help "d" others and then you shell receive some help from "d" others. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 20061
|
|
Posted: Tue Aug 18, 2015 3:27 am |
|
|
As a comment, don't use a default in the switch statement.
The way CCS handles switches, is if you have a number of switch values _and no default_, it codes this as a jump table. Simple looking up the address, and jumping to the required routine. As soon as you add a default, it instead behaves like a if statement, and has to manually check every condition.
If I have (say) 20 consecutive values, and then want a default if outside this range, I'd manually test for the value being outside the range, and then call the switch for the range _only_, without the default. |
|
 |
Linuxbuilders
Joined: 20 Mar 2010 Posts: 193 Location: Auckland NZ
|
|
Posted: Tue Aug 18, 2015 4:03 am |
|
|
thnx, this is actually very handy information. _________________ Help "d" others and then you shell receive some help from "d" others. |
|
 |
|