roboforum.ruТехнический форум по робототехнике. |
|
|
#define I2CAVRADDR 0x34
#define i2cFreq 100000
#define twps 0 // 0,1,2,3
#define twpsexp 1 // 1,4,16,64
char i2cinit()
{
DDRC=(DDRD & ~0x30); // sda and scl are input
PORTC=(PORTD&~0x30); // pullup off
TWBR=((WorkFreq/i2cFreq-16)/2)/twpsexp;
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWEA);
TWSR=twps;
TWAR=(I2CAVRADDR<<1)|1;
return 0;
}
#define eeprom ((volatile __eeprom char*)0)
char dtcnt;
unsigned short address_;
unsigned short tmpbuf;
char data[16];
#pragma vector=TWI_vect
__interrupt void TWIint()
{
switch (TWSR&0xF8)
{
// slave receiver mode
case 0x60: // slave address has been received
case 0x68: // slave address has been received after arbitration lost
case 0x70: // general call address has been received
case 0x78: // general call address has been received after arbitration lost
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA); // wait for data
dtcnt=0;
break;
case 0x80: // Previously addressed with own SLA+W; data has been received; ACK has been returned
case 0x90: // Previously addressed with general call; data has been received; ACK has been returned
if (dtcnt==0) { address_=TWDR; dtcnt++; }
else if (dtcnt==1) { address_=(address_<<8) | TWDR; dtcnt++; }
else
{
char d=TWDR;
if (address_==2) { start_key_pressed=d; }
else if (address_==3) { key_pressed=d; }
else if (address_==20) { sndfrq=d; sndvol=0; }
else if (address_==21) { sndvol=d; }
else if (address_<32) { ; }
else if (address_<32+16) { data[address_-32]=d; }
else if (address_<512) { eeprom[address_]=d; }
else { ; }
if (address_==20) { UpdSound(); }
else if (address_==21) { UpdSound(); }
address_++;
}
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA); // wait for data
break;
case 0x88: // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
case 0x98: // Previously addressed with general call; data has been received; NOT ACK has been returned
case 0xA0: // A STOP condition or repeated START condition has been received while still addressed as slave
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA); // wait for new address
break;
// slave transmitter mode
case 0xA8: // Own SLA+R has been received; ACK has been returned
case 0xB0: // Arbitration lost in SLA+R/W as master; own SLA+R has been received; ACK has been returned
case 0xB8: // Data byte in TWDR has been transmitted; ACK has been received
{
char d=0x5A;
if (address_==0) { d=1; } // bios ID
else if (address_==1) { d=2; } // bios ver
else if (address_==2) { d=start_key_pressed; }
else if (address_<32) { d=0xA5; } // reserved
else if (address_<32+16) { d=data[address_-32]; }
else if (address_<512) { d=eeprom[address_]; } // eeprom except first 32 bytes
else { d=0x5A; }
TWDR=d;
address_++;
}
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA); // not last byte will be transmitted
// TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT); // last byte will be transmitted
break;
case 0xC0: // Data byte in TWDR has been transmitted; NOT ACK has been received
case 0xC8: // Last data byte in TWDR has been transmitted (TWEA = ?0?); ACK has been received
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA); // Switched to the not addressed slave mode own SLA will be recognized;
break;
// miscellanenous states
case 0x00: // Bus error due to an illegal START or STOP condition
TWCR=(1<<TWIE)|(1<<TWEN)|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO); // send a normal stop
break;
case 0xF8: // No relevant state information available; TWINT = ?0?
break; // do nothing
}
}
Сейчас этот форум просматривают: Bing [Bot] и гости: 4