示例#1
0
文件: i2cm.c 项目: ohayak/tars_code
// Receive a frame from an address
// Slave must respect the i2c_ryder protocol : first byte tells if there are
// data to transmit or not
// Return number of read bytes
uint8_t i2cm_rcv(uint8_t slave_addr, uint8_t n, uint8_t* data)
{
  int i;

  I2C_START();

  // Slave address + Read bit (1)
  I2C_SEND((slave_addr<<1)+1);

  // No ACK, no data
  if( TW_STATUS != TW_MR_SLA_ACK )
  {
    I2C_STOP();
    wait_4cyc(100);
    return 0;
  }

  // First byte: is there something to transmit?
  I2C_ACK();
  if( TWDR == 0 )
  {
    I2C_NACK();
    I2C_STOP();
    wait_4cyc(100);
    return 0;
  }

  // Read all data
  for( i=0; i<n; i++ )
  {
    I2C_ACK();
    data[i] = TWDR;
  }

  I2C_NACK();
		
  I2C_STOP();
  wait_4cyc(100);

  return 1;
}
示例#2
0
/* @brief Receive data from an I2C slave.
 *
 * Parameters for the '>' command:
 *  - I2C slave address (u8)
 *  - data size (u8) or 0
 *
 * If the data size is 0, the value is read from the first data byte and is the
 * number of bytes to read after this first one. This is used to read protocol
 * replies from the slave.
 */
static void cmd_i2c_recv(void)
{
  const uint8_t addr = init_cmd_i2c();
  if( addr == 0 ) {
    return; // reply sent by init_cmd_i2c()
  }

  uint8_t size = recv_u8();
  // poll the slave
  do I2CM_START(); while( TW_STATUS != TW_START );
  // slave address + Read bit (1)
  I2C_SEND((addr<<1)+1);
#ifndef DISABLE_STRICT_CHECKS
  if( TW_STATUS != TW_MR_SLA_ACK && TW_STATUS != TW_MR_SLA_NACK ) {
    I2CM_STOP();
    goto slave_i2c_error;
  }
#endif
  if( size == 0 ) {
    // read the size in the first byte
    I2C_ACK();
    size = TWDR;
    reply_success(size+1);
    send_u8(size);
  } else {
    reply_success(size);
  }
  while( size-- != 1 ) {
    I2C_ACK();
    const uint8_t c = TWDR;
    send_u8(c);
  }
  I2C_NACK();
  send_u8( TWDR );
  I2CM_STOP();

  return;
#ifndef DISABLE_STRICT_CHECKS
slave_i2c_error:
  reply_error(STATUS_I2C_ERROR);
  return;
#endif
}
示例#3
0
int DS1672_GetNextByte(void)
{
	int t;
	I2C_Init(100,1000000);
	I2C_Start();
	t=I2C_TX(DS1672_READ_ADDRESS);
	if(t!=0) {
		Log_Error((FARROM*)"DS1672: GetNextByte Error sending Address\r\n");
		return -1; 
	}
	t=I2C_RX();
	if(t==-1) {
		Log_Error((FARROM*)"DS1672: GetNextByte Error receiving byte\r\n");
		return -1;
	}
	I2C_NACK();
	I2C_Stop();	
	return t;

}
示例#4
0
unsigned long DS1672_Value(void)
{
	unsigned long value;
	int t;
	unsigned long v;
	I2C_Init(100,1000000);
	I2C_Start();
	t=I2C_TX(0xD1);
	if(t!=0) return 0xffffffff;

	t=I2C_RX();
	if(t==-1) return 0xffffffff;
	value=t;
	I2C_ACK();

	t=I2C_RX();
	if(t==-1) return 0xffffffff;
	v = t;
	value+=v<<8;
	I2C_ACK();

	t=I2C_RX();
	if(t==-1) return 0xffffffff;
	v = t;
	value+=v<<16;
	I2C_ACK();
	
	t=I2C_RX();
	if(t==-1) return 0xffffffff;
	v = t;
	value+=v<<24;
	I2C_NACK();

	I2C_Stop();	
	return value;

}
示例#5
0
inline void i2c_handle_sda_irq(int controller)
{
	volatile struct i2c_status *p_status = i2c_stsobjs + controller;
	/* 1 Issue Start is successful ie. write address byte */
	if (p_status->oper_state == SMB_MASTER_START
			|| p_status->oper_state == SMB_REPEAT_START) {
		uint8_t addr = p_status->slave_addr;
		/* Prepare address byte */
		if (p_status->sz_txbuf == 0) {/* Receive mode */
			p_status->oper_state = SMB_READ_OPER;
			/*
			 * Receiving one byte only - set nack just
			 * before writing address byte
			 */
			if (p_status->sz_rxbuf == 1)
				I2C_NACK(controller);

			/* Write the address to the bus R bit*/
			I2C_WRITE_BYTE(controller, (addr | 0x1));
			CPRINTS("-ARR-0x%02x", addr);
		} else {/* Transmit mode */
			p_status->oper_state = SMB_WRITE_OPER;
			/* Write the address to the bus W bit*/
			I2C_WRITE_BYTE(controller, addr);
			CPRINTS("-ARW-0x%02x", addr);
		}
		/* Completed handling START condition */
		return;
	}
	/* 2 Handle master write operation  */
	else if (p_status->oper_state == SMB_WRITE_OPER) {
		/* all bytes have been written, in a pure write operation */
		if (p_status->idx_buf == p_status->sz_txbuf) {
			/*  no more message */
			if (p_status->sz_rxbuf == 0) {
				/* need to STOP or not */
				if (p_status->flags & I2C_XFER_STOP) {
					/* Issue a STOP condition on the bus */
					I2C_STOP(controller);
					CPUTS("-SP");
					/* Clear SDAST by writing dummy byte */
					I2C_WRITE_BYTE(controller, 0xFF);
				}

				/* Set error code */
				p_status->err_code = SMB_OK;
				/* Set SMB status if we need stall bus */
				p_status->oper_state
				= (p_status->flags & I2C_XFER_STOP)
					? SMB_IDLE : SMB_WRITE_SUSPEND;
				/*
				 * Disable interrupt for i2c master stall SCL
				 * and forbid SDAST generate interrupt
				 * until common layer start other transactions
				 */
				if (p_status->oper_state == SMB_WRITE_SUSPEND)
					i2c_interrupt(controller, 0);
				/* Notify upper layer */
				task_set_event(p_status->task_waiting,
						TASK_EVENT_I2C_IDLE, 0);
				CPUTS("-END");
			}
			/* need to restart & send slave address immediately */
			else {
				uint8_t addr_byte = p_status->slave_addr;
				/*
				 * Prepare address byte
				 * and start to receive bytes
				 */
				p_status->oper_state = SMB_READ_OPER;
				/* Reset index of buffer */
				p_status->idx_buf = 0;

				/*
				 * Generate (Repeated) Start
				 * upon next write to SDA
				 */
				I2C_START(controller);
				CPUTS("-RST");
				/*
				 * Receiving one byte only - set nack just
				 * before writing address byte
				 */
				if (p_status->sz_rxbuf == 1) {
					I2C_NACK(controller);
					CPUTS("-GNA");
				}
				/* Write the address to the bus R bit*/
				I2C_WRITE_BYTE(controller, (addr_byte | 0x1));
				CPUTS("-ARR");
			}
		}
		/* write next byte (not last byte and not slave address */
		else {
			I2C_WRITE_BYTE(controller,
					p_status->tx_buf[p_status->idx_buf++]);
			CPRINTS("-W(%02x)",
					p_status->tx_buf[p_status->idx_buf-1]);
		}
	}
	/* 3 Handle master read operation (read or after a write operation) */
	else if (p_status->oper_state == SMB_READ_OPER) {
		uint8_t data;
		/* last byte is about to be read - end of transaction */
		if (p_status->idx_buf == (p_status->sz_rxbuf - 1)) {
			/* need to STOP or not */
			if (p_status->flags & I2C_XFER_STOP) {
				/* Stop should set before reading last byte */
				I2C_STOP(controller);
				CPUTS("-SP");
			}
		}
		/* Check if byte-before-last is about to be read */
		else if (p_status->idx_buf == (p_status->sz_rxbuf - 2)) {
			/*
			 * Set nack before reading byte-before-last,
			 * so that nack will be generated after receive
			 * of last byte
			 */
			if (p_status->flags & I2C_XFER_STOP) {
				I2C_NACK(controller);
				CPUTS("-GNA");
			}
		}

		/* Read last byte but flag don't include I2C_XFER_STOP */
		if (p_status->idx_buf == p_status->sz_rxbuf-1) {
			/*
			 * Disable interrupt before i2c master read SDA reg
			 * (stall SCL) and forbid SDAST generate interrupt
			 * until common layer start other transactions
			 */
			if (!(p_status->flags & I2C_XFER_STOP))
				i2c_interrupt(controller, 0);
		}

		/* Read data for SMBSDA */
		I2C_READ_BYTE(controller, data);
		CPRINTS("-R(%02x)", data);

		/* Read to buffer */
		p_status->rx_buf[p_status->idx_buf++] = data;

		/* last byte is read - end of transaction */
		if (p_status->idx_buf == p_status->sz_rxbuf) {
			/* Set current status */
			p_status->oper_state = (p_status->flags & I2C_XFER_STOP)
					? SMB_IDLE : SMB_READ_SUSPEND;
			/* Set error code */
			p_status->err_code = SMB_OK;
			/* Notify upper layer of missing data */
			task_set_event(p_status->task_waiting,
					TASK_EVENT_I2C_IDLE, 0);
			CPUTS("-END");
		}
	}
}
示例#6
0
static void I2C_SEND_LAST(uint8_t d) { TWDR = (d); I2C_NACK(); }