Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс. e-mail:jobsmp@pochta.ru |
#include <ioavr.h>
#define TWI_TWBR 10
#define TWI_READ 1
#define TWI_WRITE 0
// ---------- General TWI Master status codes --------------
#define TWI_START 0x08
// START has been transmitted
#define TWI_REP_START 0x10
// Repeated START has been transmitted
#define TWI_ARB_LOST 0x38
// Arbitration lost
// ------------ TWI Master Transmitter status codes ---------
#define TWI_MTX_ADR_ACK 0x18
// SLA+W has been tramsmitted and ACK received
#define TWI_MTX_ADR_NACK 0x20
// SLA+W has been tramsmitted and NACK received
#define TWI_MTX_DATA_ACK 0x28
// Data byte has been tramsmitted and ACK received
#define TWI_MTX_DATA_NACK 0x30
// Data byte has been tramsmitted and NACK received
// -------------- TWI Master Receiver status codes -----------
#define TWI_MRX_ADR_ACK 0x40
// SLA+R has been tramsmitted and ACK received
#define TWI_MRX_ADR_NACK 0x48
// SLA+R has been tramsmitted and NACK received
#define TWI_MRX_DATA_ACK 0x50
// Data byte has been received and ACK tramsmitted
#define TWI_MRX_DATA_NACK 0x58
// Data byte has been received and NACK tramsmitted
// --------------- TWI Slave Transmitter status codes ---------
#define TWI_STX_ADR_ACK 0xA8
// Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0
// Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK 0xB8
// Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK 0xC0
// Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8
// Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
// ---------------- TWI Slave Receiver status codes ---------------
#define TWI_SRX_ADR_ACK 0x60
// Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68
// Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK 0x70
// General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78
// Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK 0x80
// Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK 0x88
// Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK 0x90
// Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK 0x98
// Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART 0xA0
// A STOP condition or repeated START condition has been received while still addressed as Slave
// ------------------ TWI Miscellaneous status codes -------------
#define TWI_NO_STATE 0xF8
// No relevant state information available; TWINT = “0”
#define TWI_BUS_ERROR 0x00
// Bus error due to an illegal START or STOP condition
// values of TWI control register
#define TWI_CTRL_ACK ((1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA))
#define TWI_CTRL_NACK ((1<<TWEN)|(1<<TWIE)|(1<<TWINT))
#define TWI_CTRL_START ((1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTA))
#define TWI_CTRL_STOP ((1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWSTO))
typedef enum {
IDLE = 0,
BUSY,
SUCCESS,
ARB_LOST,
ADDR_NACK,
DATA_NACK,
BUS_ERROR,
UNEXPECTED
} twi_state_t;
typedef struct {
volatile twi_state_t state;
unsigned char addr;
unsigned char nbytes_rd;
unsigned char nbytes_wr;
unsigned char *buf; // holds bytes to write and the bytes read from slave
} twi_message_t;
static twi_message_t *pm;
void twi_init( void )
{
// TWAR = addr;
TWBR = TWI_TWBR;
TWDR = 0xFF; // default content = SDA released
TWCR = TWI_CTRL_NACK;
}
void twi_start( twi_message_t *m )
{
if ( m->nbytes_rd == 0 && m->nbytes_wr == 0 )
return; // nothing to do
pm = m;
pm->state = BUSY;
TWCR = TWI_CTRL_START;
}
#pragma vector=TWI_vect
__interrupt void TWI_ISR(void)
{
static unsigned char wr_idx;
static unsigned char rd_idx;
switch ( TWSR )
{
case TWI_START: // START transmitted
wr_idx = rd_idx = 0;
if ( pm->nbytes_wr )
TWDR = ( pm->addr << 1 ) | TWI_WRITE;
else if ( pm->nbytes_rd )
TWDR = ( pm->addr << 1 ) | TWI_READ;
else
; // should not be here
TWCR = TWI_CTRL_NACK;
break;
case TWI_REP_START: // Repeated START transmitted
if ( pm->nbytes_rd )
TWDR = ( pm->addr << 1 ) | TWI_READ;
else
; // should not be here
TWCR = TWI_CTRL_NACK;
break;
case TWI_MTX_ADR_ACK: // SLA+W tramsmitted, ACK received
case TWI_MTX_DATA_ACK: // Data tramsmitted, ACK received
if ( wr_idx < pm->nbytes_wr )
TWDR = pm->buf[wr_idx++];
else if ( pm->nbytes_rd )
TWCR = TWI_CTRL_START; // Generate repeated START
else
{
pm->state = SUCCESS;
TWCR = TWI_CTRL_STOP; // All done
}
break;
////////////////////////////////// receiver states
case TWI_MRX_ADR_ACK: // SLA+R tramsmitted, ACK received
if ( pm->nbytes_rd == 1 ) // first byte is also the last
TWCR = TWI_CTRL_NACK; // don't acknowledge
else
TWCR = TWI_CTRL_ACK; // acknowledge all bytes but the last
break;
case TWI_MRX_DATA_ACK: // Data received, ACK tramsmitted
pm->buf[rd_idx++] = TWDR;
if ( rd_idx == pm->nbytes_rd - 1 ) // last byte
TWCR = TWI_CTRL_NACK; // don't acknowledge
else
TWCR = TWI_CTRL_ACK; // acknowledge all bytes but the last
break;
case TWI_MRX_DATA_NACK: // Last data received, NACK tramsmitted
pm->buf[rd_idx++] = TWDR;
// if ( rd_idx != pm->nbytes_rd )
// ; // should not be here
pm->state = SUCCESS;
TWCR = TWI_CTRL_STOP; // All done
break;
////////////////////////////////// NACKs
case TWI_MTX_ADR_NACK: // SLA+W tramsmitted, NACK received
case TWI_MRX_ADR_NACK: // SLA+R tramsmitted, NACK received
pm->state = ADDR_NACK;
pm->nbytes_wr = wr_idx;
pm->nbytes_rd = rd_idx;
TWCR = TWI_CTRL_STOP;
break;
case TWI_MTX_DATA_NACK: // Data byte has been tramsmitted and NACK received
pm->state = DATA_NACK;
pm->nbytes_wr = wr_idx;
pm->nbytes_rd = rd_idx;
TWCR = TWI_CTRL_STOP;
break;
////////////////////////////////// unexpected states
case TWI_ARB_LOST: // Arbitration lost
pm->state = ARB_LOST;
break;
case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition
pm->state = BUS_ERROR;
pm->nbytes_wr = wr_idx;
pm->nbytes_rd = rd_idx;
TWCR = TWI_CTRL_STOP;
break;
default:
pm->state = UNEXPECTED;
break;
}
}