⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c.c

📁 atmel avr hardwire i2c source
💻 C
📖 第 1 页 / 共 2 页
字号:
}

//! I2C (TWI) interrupt service routine
SIGNAL(SIG_2WIRE_SERIAL)
{
    // read status bits
    unsigned char status = inb(TWSR) & TWSR_STATUS_MASK;

	i2c_data = TWCR;
	i2c_code = TWSR & TW_NO_INFO;

	twi_had_isr = 1;

    switch(status)
    {
    // Master General
    case TW_START:                      // 0x08: Sent start condition
    case TW_REP_START:                  // 0x10: Sent repeated start condition
        // send device address
        i2cSendByte(I2cDeviceAddrRW);
        //outb(TWDR, I2cDeviceAddrRW);
        //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        break;
    
    // Master Transmitter & Receiver status codes
    case TW_MT_SLA_ACK:                 // 0x18: Slave address acknowledged
    case TW_MT_DATA_ACK:                // 0x28: Data acknowledged
        if(I2cSendDataIndex < I2cSendDataLength)
        {
            // send i2c_data
            i2cSendByte( I2cSendData[I2cSendDataIndex++] );
            //outb(TWDR, I2cSendData[I2cSendDataIndex++]);
            //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        }
        else
        {
            // transmit stop condition, enable SLA ACK
            i2cSendStop();
            //outb(TWCR, inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));
            // set state
            I2cState = I2C_IDLE;
        }
        break;
    case TW_MR_DATA_NACK:               // 0x58: Data received, NACK  reply ssued
        // store final received i2c_data byte
        I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
        // continue to transmit STOP condition
    case TW_MR_SLA_NACK:                 // 0x48:  Slave  address not acknowledged
    case TW_MT_SLA_NACK:                 // 0x20:  Slave  address not acknowledged
    case TW_MT_DATA_NACK:               // 0x30: Data not acknowledged
        // transmit stop condition, enable SLA ACK
        i2cSendStop();
        //outb(TWCR, inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));
        // set state
        I2cState = I2C_IDLE;
        break;
    case TW_MT_ARB_LOST:                // 0x38: Bus arbitration lost
    //case TW_MR_ARB_LOST:              // 0x38: Bus arbitration lost
        // release bus
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        // set state
        I2cState = I2C_IDLE;
        // release bus and transmit start when bus is free
        //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTA));
        break;
    case TW_MR_DATA_ACK:                // 0x50: Data acknowledged
        // store received i2c_data byte
        I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
        // fall-through to see if more bytes will be received
    case TW_MR_SLA_ACK:                 // 0x40: Slave address acknowledged
        if(I2cReceiveDataIndex < (I2cReceiveDataLength-1))
            // i2c_data byte will be received, reply with ACK (more bytes in transfer)
            i2cReceiveByte(TRUE);
            //outb(TWCR, inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        else
            // i2c_data byte will be received, reply with NACK (final byte in transfer)
            i2cReceiveByte(FALSE);
            //outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        break;

    // Slave Receiver status codes
    case TW_SR_SLA_ACK:                 // 0x60: own SLA+W has been received, ACK has been returned
    case TW_SR_ARB_LOST_SLA_ACK:        //  0x68: own  SLA+W has  been eceived, ACK has been returned
    case TW_SR_GCALL_ACK:               // 0x70:     GCA+W has been received, ACK has been returned
    case TW_SR_ARB_LOST_GCALL_ACK:      //  0x78:     GCA+W  has been eceived, ACK has been returned
        // we are  being addressed as  slave for writing  (i2c_data will be  received from master)
        // set state
        I2cState = I2C_SLAVE_RX;
        // prepare buffer
        I2cReceiveDataIndex = 0;
        // receive i2c_data byte and return ACK
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        break;
    case TW_SR_DATA_ACK:                // 0x80: i2c_data byte has been  received, ACK has been returned
    case TW_SR_GCALL_DATA_ACK:          // 0x90: i2c_data byte has been received, ACK has been returned
        // get previously received i2c_data byte
        I2cReceiveData[I2cReceiveDataIndex++] = inb(TWDR);
        // check receive buffer status
        if(I2cReceiveDataIndex < I2C_RECEIVE_DATA_BUFFER_SIZE)
        {
            // receive i2c_data byte and return ACK
            outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        }
        else
        {
            // receive i2c_data byte and return NACK
            outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        }
        break;
    case TW_SR_DATA_NACK:               // 0x88: i2c_data byte has been received, NACK has been returned
    case TW_SR_GCALL_DATA_NACK:         // 0x98: i2c_data byte has been received, NACK has been returned
        // receive i2c_data byte and return NACK
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        break;
    case TW_SR_STOP:                    // 0xA0: STOP or REPEATED START has been received while addressed as slave
        // switch to SR mode with SLA ACK
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        // i2c receive is complete, call i2cSlaveReceive
        if(i2cSlaveReceive) i2cSlaveReceive(I2cReceiveDataIndex, I2cReceiveData);
        // set state
        I2cState = I2C_IDLE;
        break;

    // Slave Transmitter
    case TW_ST_SLA_ACK:                 // 0xA8: own SLA+R has been received, ACK has been returned
    case TW_ST_ARB_LOST_SLA_ACK:        //  0xB0:     GCA+R  has been eceived, ACK has been returned
        // we are being addressed as slave for reading (i2c_data must be transmitted back o master)
        // set state
        I2cState = I2C_SLAVE_TX;
        // request i2c_data from application
        if(i2cSlaveTransmit)
			I2cSendDataLength = i2cSlaveTransmit(I2C_SEND_DATA_BUFFER_SIZE, I2cSendData);
        // reset i2c_data index
        I2cSendDataIndex = 0;
        // fall-through to transmit first i2c_data byte
    case TW_ST_DATA_ACK:                 // 0xB8:  i2c_data byte  has been ransmitted, ACK has been received
        // transmit i2c_data byte
        outb(TWDR, I2cSendData[I2cSendDataIndex++]);
        if(I2cSendDataIndex < I2cSendDataLength)
            // expect ACK to i2c_data byte
            outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        else
            // expect NACK to i2c_data byte
            outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT));
        break;
    case TW_ST_DATA_NACK:                // 0xC0:  i2c_data byte  has been ransmitted, NACK has been received
    case TW_ST_LAST_DATA:               // 0xC8:
        // all done
        // switch to open slave
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWEA));
        // set state
        I2cState = I2C_IDLE;
        break;

    // Misc
    case TW_NO_INFO:                    // 0xF8: No relevant state information
        // do nothing
        break;
    case TW_BUS_ERROR:                  // 0x00: Bus error due to illegal start or top condition
        // reset internal hardware and release bus
        outb(TWCR, (inb(TWCR)&TWCR_CMD_MASK)|BV(TWINT)|BV(TWSTO)|BV(TWEA));
        // set state
        I2cState = I2C_IDLE;
        break;
    }
}



void neweprom_init(void) {
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
#if defined(TWPS0)
  /* has prescaler (mega128 & newer) */
  TWSR = 0;
#endif
  TWBR = 6;
  
}

int neweprom_read_byte(uint16_t eeaddr, char *buf)
{
  uint8_t n = 0;

restart:
  if (n++ >= MAX_TRIES)
    return -1;

begin:
	// send start cond.
	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) {
		return -1;
	}
	
	// send 0xa0
	// 0xa0 = 1010 000 0
	// 4 bits:   <a..device-indentifier>
	// 3 bits:   <device-address set with chip pins>
	// last bit: <0..write>
	TWDR = 0xa0;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_SLA_NACK) goto restart;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_SLA_ACK) goto error;
	
	// send low 8 bits of eeaddr 
	TWDR = eeaddr;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_DATA_NACK) goto restart;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_DATA_ACK) goto error;
	
	// send high 8 bits of eeaddr
	TWDR = eeaddr << 8;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_DATA_NACK) goto restart;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_DATA_ACK) goto error;
	
	// send start cond.
	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) {
		return -1;
	}

	// send 0xa1
	// 0xa0 = 1010 000 1
	// 4 bits:   <a..device-indentifier>
	// 3 bits:   <device-address set with chip pins>
	// last bit: <1..read>
	TWDR = 0xa1;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MR_SLA_NACK) goto quit;
	if (TW_STATUS == TW_MR_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MR_SLA_ACK) goto error;
	
	// start read transmission
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));

	switch ((twst = TW_STATUS)) {
		case TW_MR_DATA_NACK:
			// FALLTHROUGH 
		case TW_MR_DATA_ACK:
			*buf = TWDR;
			break;
		default:
			goto error;
	}
	
quit:
	//stop condition
	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	return 1;

error:
	//stop condition
	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	return -1;
}

int new_eprom_write_byte(uint16_t eeaddr, char buf) {
  uint8_t n = 0;

restart:
  if (n++ >= MAX_TRIES)
    return -1;
begin:

	// start cond.
	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) {
		return -1;
	}

	// send 0xa0
	// 0xa0 = 1010 000 0
	// 4 bits:   <a..device-indentifier>
	// 3 bits:   <device-address set with chip pins>
	// last bit: <0..write>
  	TWDR = 0xa0;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_SLA_NACK) goto restart;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_SLA_ACK) goto error;

	// send low 8 bits of eeaddr 
	TWDR = eeaddr;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_DATA_NACK) goto quit;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_DATA_ACK) goto error;

	// send high 8 bits of eeaddr 
	TWDR = eeaddr << 8;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS == TW_MT_DATA_NACK) goto quit;
	if (TW_STATUS == TW_MT_ARB_LOST) goto begin;
	if (TW_STATUS != TW_MT_DATA_ACK) goto error;

	// put byte into i2c_data register and start transmission
	TWDR = buf;
	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!(TWCR & (1 << TWINT)));
	if (TW_STATUS != TW_MT_DATA_ACK) goto error;

quit:
	// send stop condition
	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	return 1;

error:
	// send stop condition
	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	return -1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -