Hi,
I got some time and have the usi doing byte streams both ways now. I was
curious if I have the optimum solution, (or missed something and didn't
need a hack), for the awk when the slave is being read.
With this method, I don't have to dissable the start interrupt or loop
till condition.
After the 8 bits are sent from my slave I set up the USISRL and one
count and output. In the TI examples they appear to break the rule as to
keeping the awk low while SCL is high, I don't see how this will work.
They set SDA to input while the clock is high and that lets the data
line go high.
What I did was to use the port interrupt in just this special case to
watch for the clock to go low before setting SDA back to input.
if( ..awk on read )
P1IFG= 0;
P1IES= BIT6;
P1IE= BIT6;
...
Am I missing something or is there a more elegant way? USI stuff below.
Thanks, Dan.
interrupt ( USI_VECTOR ) usi_interrupt( void )
{
if( USICTL1 & USISTTIFG ) // START received....
{
USICTL1&= ~USISTTIFG; // Clear START flag...
USICNT= 0x08 | USISCLREL; // Clears USISCLREL
usi_state= USISTATE_RCVADR; //Next is receive address
USICTL0&= ~USIOE;
USICTL1|= USIIE; // Enable Counter Interrupt
return;
}
if( USICTL & USISTP )//A stop condition was detected
{
initialize_i2c( );//reset USI
return;
}
//Address and r/w should be in shift reg...
if( usi_state & USISTATE_RCVADR )
{
//Is it _not_ our address?
if( USISRL >> 1 != USI_OURADDRESS )
{
usi_state= USISTATE_NULL;
initialize_i2c( );//reset USI, Wait for next start
return;
}
//else our address, get the r/w bit next
if( USISRL & 0x01 )
{
usi_state= USISTATE_WRITE | USISTATE_AWK;
usi_buf_ptr= 0xf800;
}
else
{
usi_state= USISTATE_READ | USISTATE_AWK;
usi_buf_ptr= buffer;
}
USISRL= 0;
USICNT= 0x01 | USISCLREL; //Get ready to awk
USICTL0|= USIOE; //Take SDA.
return;
}
if( usi_state & USISTATE_AWK )
{
if( usi_state & USISTATE_READ )
{
P1IFG= 0;
P1IES= BIT6;
P1IE= BIT6;
}
else
USISRL= *usi_buf_ptr++;
USICNT= 0x08 | USISCLREL;
usi_state&= ~USISTATE_AWK;
return;
}
if( usi_state & USISTATE_AWK_WRITE )
{
if( USISRL & 0X01 )
initialize_i2c( ); //Master said no more...
else
{
usi_state= USISTATE_WRITE;
USICTL0|= USIOE; //Take SDA.
USISRL= *usi_buf_ptr++;
USICNT= 0x08 | USISCLREL;
}
return;
}
//Recieve/transmit data from/to the master
if( usi_state & USISTATE_READ )
{
*usi_buf_ptr++= USISRL;
//Do awk
usi_state|= USISTATE_AWK;
USISRL= 0;
USICNT= 0x01 | USISCLREL;
USICTL0|= USIOE; //Take SDA.
return;
}
if( usi_state & USISTATE_WRITE )
{
usi_state|= USISTATE_AWK_WRITE;
USICTL0&= ~USIOE; //Release SDA.
USISRL= 0;
USICNT= 0x01 | USISCLREL;
return;
}
}
void initialize_i2c( void )
{
USICTL0= USIPE6 | USIPE7 | USISWRST;//Port, I2C slave
USICTL1= USII2C | USISTTIE; //Enable I2C mode, disable
counter
USICKCTL= USICKPL; //Setup clock polarity
USICNT= USISCLREL; //SCL released
USICTL0&= ~USISWRST; // Clear Reset of USI
//Initialize State machine and sit idle until START condition
usi_state= USISTATE_NULL;
}
interrupt ( PORT1_VECTOR ) usi_interrupt2( void )
{
P1IES= 0;
P1IE= 0;
P1IFG= 0;
USICTL0&= ~USIOE;
}
--
email: y...@lakeweb.com but drop the 'x'.
------------------------------------

(You need to be a member of msp430 -- send a blank email to msp430-subscribe@yahoogroups.com )