Example #1
0
File: i2c.c Project: pandc/unitek
int I2C_Read(uint8_t addr,void *pbuffer,uint16_t len)
{
struct i2c_job_st i2c_job;

	xSemaphoreTake(xSemaphoreI2C_Mutex,portMAX_DELAY);

	if (I2C_isBusy())
	{
		i2c_error_flags = I2C_SR1_SB;
		xSemaphoreGive(xSemaphoreI2C_Mutex);
		return FALSE;
	}

	i2c_cntr = 0;
	i2c_oper = I2C_Direction_Receiver;
	job = &i2c_job;
	i2c_addr = addr << 1;
	i2c_job.buf = (uint8_t *)pbuffer;
	i2c_job.len = len;
	i2c_job.dir = I2C_Direction_Receiver;
	i2c_job.last = TRUE;

	i2c_done = i2c_err = FALSE;

	// clear the semaphore
	while (xSemaphoreTake(xSemaphoreI2C_Work,0));

	if ((i2c_oper == I2C_Direction_Receiver) && (len == 2))
		I2C_NACKPositionConfig(I2Cx,I2C_NACKPosition_Next);
	else
		I2C_NACKPositionConfig(I2Cx,I2C_NACKPosition_Current);
	I2C_AcknowledgeConfig(I2Cx,ENABLE);
	I2C_ITConfig(I2Cx,I2C_IT_BUF | I2C_IT_ERR | I2C_IT_EVT,ENABLE);

	/* Send START condition */
	I2C_GenerateSTART(I2Cx, ENABLE);

	while (!i2c_done && !i2c_err)
	{
		if (!xSemaphoreTake(xSemaphoreI2C_Work,SEMA_DELAY))
		{
			I2C_Open(0);
			i2c_err = TRUE;
			break;
		}
	}

	I2C_ITConfig(I2Cx,I2C_IT_BUF | I2C_IT_ERR | I2C_IT_EVT,DISABLE);

	xSemaphoreGive(xSemaphoreI2C_Mutex);
	return !i2c_err;
}
Example #2
0
void DS1307SetTime() {
	uint8_t index;
	uint8_t values[8] = { 0x00, 0x15, 0x00, 0x01, 0x15, 0x05, 0x13, 0x10 };

	I2C_AcknowledgeConfig(I2C2, ENABLE);

	// Start setting register
	I2C_GenerateSTART(I2C2, ENABLE);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
		;

	I2C_Send7bitAddress(I2C2, I2C2_SLAVE_ADDRESS, I2C_Direction_Transmitter);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
		;

	I2C_SendData(I2C2, 0x00);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
		;

	for (index = 0; index < 8; index++) {
		I2C_SendData(I2C2, values[index]);
		while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
			;
	}

	I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Current);
	I2C_AcknowledgeConfig(I2C2, DISABLE);

	I2C_GenerateSTOP(I2C2, ENABLE);

	while (I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF))
		;
}
Example #3
0
void DS1307ReadTime(DATE_TYPE* date) {
	uint8_t index;
	uint8_t values[8] = { 0 };

	I2C_AcknowledgeConfig(I2C2, ENABLE);

	// Start setting register
	I2C_GenerateSTART(I2C2, ENABLE);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
		;

	I2C_Send7bitAddress(I2C2, I2C2_SLAVE_ADDRESS, I2C_Direction_Transmitter);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
		;

	I2C_SendData(I2C2, 0x00);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
		;

	I2C_GenerateSTART(I2C2, ENABLE);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
		;

	I2C_Send7bitAddress(I2C2, I2C2_SLAVE_ADDRESS, I2C_Direction_Receiver);
	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
		;

	for (index = 0; index < 8; index++) {
		while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
			;
		values[index] = I2C_ReceiveData(I2C2);
		if (index == 6) {
			I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Current);
			I2C_AcknowledgeConfig(I2C2, DISABLE);
		}
	}

	I2C_GenerateSTOP(I2C2, ENABLE);
	while (I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF))
		;

	date->sec1 = (values[0] & 0xF0) >> 4;
	date->sec0 = values[0] & 0x0F;
	date->min1 = (values[1] & 0xF0) >> 4;
	date->min0 = values[1] & 0x0F;
	date->hour1 = (values[2] & 0x30) >> 4;
	date->hour0 = values[2] & 0x0F;
	date->day1 = (values[4] & 0x30) >> 4;
	date->day0 = values[4] & 0x0F;
	date->month1 = (values[5] & 0x10) >> 4;
	date->month0 = values[5] & 0x0F;
	date->year1 = (values[6] & 0xF0) >> 4;
	date->year0 = values[6] & 0x0F;
}
Example #4
0
File: i2c.c Project: richese/aeris
u8 i2c_read_reg(u8 dev_adr, u8 reg_adr)
{
    u8 res;

    /*re-enable ACK bit incase it was disabled last call*/
    I2C_AcknowledgeConfig(I2C2, ENABLE);
    /* Test on BUSY Flag */
    while (I2C_GetFlagStatus(I2C2,I2C_FLAG_BUSY));

    /* Enable the I2C peripheral */

    I2C_GenerateSTART(I2C2, ENABLE);
    /* Test on start flag */
    while (!I2C_GetFlagStatus(I2C2,I2C_FLAG_SB))  __asm("nop");;
    /* Send device address for write */
    I2C_Send7bitAddress(I2C2, dev_adr, I2C_Direction_Transmitter);
    /* Test on master Flag */
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))  __asm("nop");;
    /* Send the device's internal address to write to */
    I2C_SendData(I2C2, reg_adr);
    /* Test on TXE FLag (data sent) */
    while (!I2C_GetFlagStatus(I2C2,I2C_FLAG_TXE))  __asm("nop");;

      /* Send START condition a second time (Re-Start) */
    I2C_GenerateSTART(I2C2, ENABLE);
    /* Test start flag */
    while (!I2C_GetFlagStatus(I2C2,I2C_FLAG_SB))  __asm("nop");;
    /* Send address for read */
    I2C_Send7bitAddress(I2C2, dev_adr, I2C_Direction_Receiver);
    /* Test Receive mode Flag */
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))  __asm("nop");;
    /* load in all 6 registers */
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))  __asm("nop");;
    res = I2C_ReceiveData(I2C2);

    /*enable NACK bit */
    I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Current);
    I2C_AcknowledgeConfig(I2C2, DISABLE);

    /* Send STOP Condition */
    I2C_GenerateSTOP(I2C2, ENABLE);
    while(I2C_GetFlagStatus(I2C2, I2C_FLAG_STOPF))  __asm("nop");; // stop bit flag




    return res;
}
short read8(I2C_TypeDef* I2Cx){
	uint8_t msb=0, lsb=0;
	unsigned char dummy1;
	unsigned short data;

	I2C_AcknowledgeConfig(I2Cx, ENABLE);
	while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));

	I2C_GenerateSTART(I2Cx, ENABLE);
	while(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB));
	while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

	I2C_Send7bitAddress(I2Cx,0x6B<<1,I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2Cx,0x28);
	while(!I2C_GetFlagStatus(I2Cx,I2C_FLAG_TXE));
	while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_GenerateSTART(I2Cx, ENABLE);
	while(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_SB));

	I2C_Send7bitAddress(I2Cx, 0x6B<<1, I2C_Direction_Receiver);
	while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	msb = I2C_ReceiveData(I2Cx);
	while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

	I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);
	I2C_AcknowledgeConfig(I2Cx, DISABLE);

	lsb = I2C_ReceiveData(I2Cx);
	while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

	//dummy1 = I2C_ReceiveData(I2Cx);
	//while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

	I2C_GenerateSTOP(I2Cx, ENABLE);
	while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF));


	data  = msb<<8;
	data |= lsb;

	return data;
}
Example #6
0
void MPU6050_Read_Data()
{
	uint8_t i;

	I2C_AcknowledgeConfig(I2C2, ENABLE);

    I2C_GenerateSTART(I2C2, ENABLE);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C2, MPU6050_I2C_ADDR, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    I2C_SendData(I2C2, MPU6050_ACCEL_XOUT_H);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    I2C_GenerateSTART(I2C2, ENABLE);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));

    I2C_Send7bitAddress(I2C2, MPU6050_I2C_ADDR, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    for (i=0;i<14;i++)
    {
    	while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED));
        MPU6050_Data_Buffer[i] = I2C_ReceiveData(I2C2);

        if (i == 12)
        {
        	I2C_NACKPositionConfig(I2C2, I2C_NACKPosition_Current);
            I2C_AcknowledgeConfig(I2C2, DISABLE);
        }
    }

    Acc_X = MPU6050_Data_Buffer[0]<<8 | MPU6050_Data_Buffer[1];
    Acc_Y = MPU6050_Data_Buffer[2]<<8 | MPU6050_Data_Buffer[3];
    Acc_Z = MPU6050_Data_Buffer[4]<<8 | MPU6050_Data_Buffer[5];

    Gyr_X = MPU6050_Data_Buffer[8]<<8  | MPU6050_Data_Buffer[9];
    Gyr_Y = MPU6050_Data_Buffer[10]<<8 | MPU6050_Data_Buffer[11];
    Gyr_Z = MPU6050_Data_Buffer[12]<<8 | MPU6050_Data_Buffer[13];

    Temp = MPU6050_Data_Buffer[6]<<8 | MPU6050_Data_Buffer[7];

    Temp = (float)((float)((int16_t)Temp/(float)340.0) + (float)36.53);
}
Example #7
0
uint8_t i2c_read(uint8_t DeviceAddr, uint8_t IntAddr)
{
	printf("r\n\r");
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); 
	I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
	printf("r\n\r");
	I2C_Send7bitAddress(I2C1, MPU6050, I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
	printf("ack\n\r");
	I2C_SendData(I2C1,IntAddr);							  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
	printf("r\n\r");
	I2C_GenerateSTART(I2C1, ENABLE);						  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));			    I2C_Send7bitAddress(I2C1, MPU6050, I2C_Direction_Receiver);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
	I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);			
	I2C_GenerateSTOP(I2C1, ENABLE);				    
	return I2C_ReceiveData(I2C1);

}
Example #8
0
uint8_t I2C_Read8(uint8_t addr, uint8_t reg)
{
	uint8_t data = 0;

	I2C_AcknowledgeConfig(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

	I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB));
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

	I2C_Send7bitAddress(I2C1, addr<<1,I2C_Direction_Transmitter);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

	I2C_SendData(I2C1, reg);
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

	I2C_GenerateSTART(I2C1, ENABLE);
	while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB));

	I2C_Send7bitAddress(I2C1, addr<<1, I2C_Direction_Receiver);
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

	I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);
	I2C_AcknowledgeConfig(I2C1, DISABLE);

	//need to add a wait here for new data, right now it goes to fast to get the new data.
	while(!I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE));
	data = I2C_ReceiveData(I2C1);
	//while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED));

	I2C_GenerateSTOP(I2C1, ENABLE);
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));

	return data;
}
Example #9
0
File: i2c.c Project: pandc/unitek
void I2Cx_EV_IRQHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
uint32_t lasteve;

	i2c_cntr++;
	switch(i2c_oper)
	{
	case I2C_Direction_Transmitter:
		lasteve = I2C_GetLastEvent(I2Cx);
		switch(lasteve)
		{
		case I2C_EVENT_MASTER_MODE_SELECT:
		/* If SB = 1, I2Cx master sent a START on the bus: EV5) */
			// Send the slave address for transmssion or for reception
			// according to the configured value in the write master write routine
			I2C_Send7bitAddress(I2Cx, i2c_addr, job->dir);
			break;
	//---------------------------------------------------------------------------
	//--- TX States -------------------------------------------------------------
	//---------------------------------------------------------------------------
		case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
			/* Initialize the Transmit counter */
			i2c_pb = job->buf;
			i2c_len = job->len;
			/* Write the first data in the data register */
			I2Cx->DR = *i2c_pb++;
			/* If no further data to be sent, disable the I2C BUF IT
			in order to not have a TxE  interrupt */
			if (--i2c_len == 0)
			{
				if (job->last || (job[1].dir != I2C_Direction_Transmitter))
				{
					/* Disable the BUF IT in order to wait the BTF event */
					I2C_ITConfig(I2Cx,I2C_IT_BUF,DISABLE);
				}
				else
				{
					job++;
					i2c_pb = job->buf;
					i2c_len = job->len;
				}
			}
			break;
		case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
			/* Master transmits the remaing data: from data2 until the last one.  */
			/* If TXE is set */
			/* If there is still data to write */
			if (i2c_len)
			{
				/* Write the data in DR register */
				I2Cx->DR = *i2c_pb++;
				// If  no data remains to write, disable the BUF IT in order
				// to not have again a TxE interrupt
				if (--i2c_len == 0)
				{
					if (job->last || (job[1].dir != I2C_Direction_Transmitter))
					{
						/* Disable the BUF IT */
						I2C_ITConfig(I2Cx,I2C_IT_BUF,DISABLE);
					}
					else
					{
						job++;
						i2c_pb = job->buf;
						i2c_len = job->len;
					}
				}
			}
			break;
		case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
			/* If BTF and TXE are set (EV8_2), program the STOP */
			if (job->last)
			{
				/* Program the STOP */
				I2C_GenerateSTOP(I2Cx,ENABLE);
				/* Disable EVT IT In order to not have again a BTF IT */
				I2C_ITConfig(I2Cx,I2C_IT_EVT | I2C_IT_BUF,DISABLE);
				i2c_done = TRUE;
				xSemaphoreGiveFromISR(xSemaphoreI2C_Work,&xHigherPriorityTaskWoken);
			}
			else
			{
				job++;
				i2c_oper = job->dir;
				/* Send START condition */
				I2C_GenerateSTART(I2Cx, ENABLE);
			}
			break;
		}
		break;
	//---------------------------------------------------------------------------
	//--- RX States -------------------------------------------------------------
	//---------------------------------------------------------------------------
	case I2C_Direction_Receiver:
		if (I2C_GetITStatus(I2Cx,I2C_IT_SB) == SET)
		{
			/* Send slave Address for read */
			I2C_Send7bitAddress(I2Cx, i2c_addr, I2C_Direction_Receiver);
			i2c_pb = job->buf;
			i2c_len = job->len;
			if (i2c_len == 3)
			{
				/* Disable buffer Interrupts */
				I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
			}
			else
			{
				/* Enable buffer Interrupts */
				I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
			}
		}
		else if (I2C_GetITStatus(I2Cx, I2C_IT_ADDR) == SET)
		{
			if (i2c_len == 1)
			{
				I2C_AcknowledgeConfig(I2Cx, DISABLE);
			}
			/* Clear ADDR Register */
			(void)(I2Cx->SR1);
			(void)(I2Cx->SR2);
			if (i2c_len == 1)
			{
				I2C_GenerateSTOP(I2Cx, ENABLE);
			}
			else if (i2c_len == 2)
			{
				I2C_AcknowledgeConfig(I2Cx, DISABLE);
				I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);
				/* Disable buffer Interrupts */
				I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
			}
		}
		else if ((I2C_GetITStatus(I2Cx, I2C_IT_RXNE) == SET) && (I2C_GetITStatus(I2Cx, I2C_IT_BTF) == RESET))
		{
			/* Store I2C received data */
			*i2c_pb++ = I2C_ReceiveData (I2Cx);
			i2c_len--;

			if (i2c_len == 3)
			{
				/* Disable buffer Interrupts */
				I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
			}
			else if (i2c_len == 0)
			{
				/* Disable Error, Event and Buffer Interrupts */
				I2C_ITConfig(I2Cx,I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
				i2c_done = TRUE;
				xSemaphoreGiveFromISR(xSemaphoreI2C_Work,&xHigherPriorityTaskWoken);
			}
		}    
		/* BUSY, MSL and RXNE flags */
		else if (I2C_GetITStatus(I2Cx, I2C_IT_BTF) == SET)
		{
			/* if Three bytes remaining for reception */
			if (i2c_len == 3)
			{
				I2C_AcknowledgeConfig(I2Cx, DISABLE);
				/* Store I2C received data */
				*i2c_pb++ = I2C_ReceiveData(I2Cx);
				i2c_len--;
			} 
			else if (i2c_len == 2)
			{           
				I2C_GenerateSTOP(I2Cx, ENABLE);    

				/* Store I2C received data */
				*i2c_pb++ = I2C_ReceiveData(I2Cx);
				i2c_len--;
				/* Store I2C received data */
				*i2c_pb++ = I2C_ReceiveData(I2Cx);
				i2c_len--;
				/* Disable Error, Event and Buffer Interrupts */
				I2C_ITConfig(I2Cx,I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, DISABLE);
				i2c_done = TRUE;
				xSemaphoreGiveFromISR(xSemaphoreI2C_Work,&xHigherPriorityTaskWoken);
			}
			else 
			{
				/* Store I2C received data */
				*i2c_pb++ = I2C_ReceiveData(I2Cx);
				i2c_len--;
			}
		}
		break;
	}
	portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
/**
  * @brief  Reads a buffer of 2 bytes from the device registers.
  * @param  RegisterAddr: The target register adress (between 00x and 0x24)
  * @retval The data in the buffer containing the two returned bytes (in halfword).   
  */
uint16_t I2C_ReadDataBuffer(uint32_t RegisterAddr)
{
  uint8_t IOE_BufferRX[2] = {0x00, 0x00};  
  
  /* Enable the I2C peripheral */
  I2C_GenerateSTART(IOE_I2C, ENABLE);
 
  /* Test on EV5 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
   
  /* Send device address for write */
  I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Transmitter);
  
  /* Test on EV6 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;  
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
  
  /* Read status register 2 to clear ADDR flag */
  IOE_I2C->SR2;
  
  /* Test on EV8 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_TXE))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
  
  /* Send the device's internal address to write to */
  I2C_SendData(IOE_I2C, RegisterAddr);  
    
  /* Send START condition a second time */  
  I2C_GenerateSTART(IOE_I2C, ENABLE);
  
  /* Test on EV5 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_SB))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
  
  /* Send IO Expander address for read */
  I2C_Send7bitAddress(IOE_I2C, IOE_ADDR, I2C_Direction_Receiver);
  
  /* Test on EV6 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_ADDR))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
 
  /* Disable Acknowledgement and set Pos bit */
  I2C_AcknowledgeConfig(IOE_I2C, DISABLE);       
  I2C_NACKPositionConfig(IOE_I2C, I2C_NACKPosition_Next);
  
  /* Read status register 2 to clear ADDR flag */
  IOE_I2C->SR2;

  /* Test on EV7 and clear it */
  IOE_TimeOut = TIMEOUT_MAX;
  while (!I2C_GetFlagStatus(IOE_I2C, I2C_FLAG_BTF))
  {
    if (IOE_TimeOut-- == 0) return(IOE_TimeoutUserCallback());
  }
 
  /* Send STOP Condition */
  I2C_GenerateSTOP(IOE_I2C, ENABLE);
   
  /* Read the first byte from the IO Expander */
  IOE_BufferRX[1] = I2C_ReceiveData(IOE_I2C);
    
  /* Read the second byte from the IO Expander */
  IOE_BufferRX[0] = I2C_ReceiveData(IOE_I2C);
                                         
  /* Enable Acknowledgement and reset POS bit to be ready for another reception */
  I2C_AcknowledgeConfig(IOE_I2C, ENABLE);
  I2C_NACKPositionConfig(IOE_I2C, I2C_NACKPosition_Current);
   
  /* return the data */
  return ((uint16_t) IOE_BufferRX[0] | ((uint16_t)IOE_BufferRX[1]<< 8));
}
Example #11
0
uint8_t I2C_ReadShort(uint16_t reg_address, uint16_t dev_address)
{
	uint16_t data = 0;
	uint32_t timeout = I2C_TIMEOUT;
	dev_address = dev_address << 1;

	I2C_AcknowledgeConfig(I2C1, ENABLE);

	while (I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY)) {
		if (! timeout--)
			Usart1Put('q');
	}


	I2C_GenerateSTART(I2C1, ENABLE);

	timeout = I2C_TIMEOUT;
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)){
		if (! timeout--)
			Usart1Put('w');
	}


	I2C_Send7bitAddress(I2C1, dev_address, I2C_Direction_Transmitter);

	timeout = I2C_TIMEOUT;
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)){
		if (! timeout--)
			Usart1Put('e');
	}

	I2C_SendData(I2C1, reg_address);	// write register address
	timeout = I2C_TIMEOUT;
	while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED)){
		if (! timeout--)
			Usart1Put('r');

	}

	/* restart */
	I2C_GenerateSTART(I2C1, ENABLE);
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)){
			if (! timeout--)
				Usart1Put('t');
	}

	I2C_Send7bitAddress(I2C1, dev_address, I2C_Direction_Receiver);
	timeout = I2C_TIMEOUT;
	while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)){
		if (! timeout--)
			Usart1Put('y');
	}

	/* before last one, disable ACK */
	I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Next);
	I2C_AcknowledgeConfig(I2C1, DISABLE);


	/* Receive */
	I2C_ReceiveData(I2C1);
	timeout = I2C_TIMEOUT;
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)){
		if (! timeout--)
			Usart1Put('u');
	}

	/* Receive */
	data =	I2C_ReceiveData(I2C1);
	timeout = I2C_TIMEOUT;
	while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)){
		if (! timeout--)
			Usart1Put('i');
	}

	I2C_GenerateSTOP(I2C1, ENABLE);
	timeout = I2C_TIMEOUT;
	while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF)){
		if (! timeout--)
			Usart1Put('o');
	}


	return data;
}
Example #12
0
/* ---------------------------------------------------------------------------
** Reads data from the SFR02 sensor
** Implements the communication protocol specific to the SFR02 sensors
** -------------------------------------------------------------------------*/
uint16_t I2CReadData(uint8_t device_address, uint8_t register_address) {
    uint16_t timeout;
    static uint16_t	data=0;

    /*!< While the bus is busy */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_BUSY_TIMEOUT);
    }

    //1. Send a start sequence

    /*!< Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);

    /*!< Test on EV5 and clear it */
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_MASTER_MODE_TIMEOUT);
    }

    //2. Send 0xE0 ( I2C address of the SRF02 with the R/W bit low (even address - write))

    /*!< Send Sonar address for write */
    timeout = I2C_TIMEOUT;
    I2C_Send7bitAddress(I2C1, device_address, I2C_Direction_Transmitter);

    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_ADDR_TIMEOUT);
    }

    /*!< Test on EV6 and clear it */
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_MASTER_TRANSMITTER_TIMEOUT);
    }

    //3. Send 0x02 (Internal address of the first distance register)

    /*!< Send the sonar internal register address to read from */
    I2C_SendData(I2C1, register_address);

    /*!< Test on EV8 and clear it */
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_BYTE_TRANSMITTED_TIMEOUT);
    }

    I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Next);

    //4. Send a start sequence again (repeated start)

    /*!< Send START condition */
    I2C_GenerateSTART(I2C1, ENABLE);

    /*!< Test on EV5 and clear it */
    timeout = I2C_TIMEOUT;
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_MASTER_MODE_TIMEOUT);
    }

    //5. Send 0xE1 ( I2C address of the SRF02 with the R/W bit high (odd address - read))

    /*!< Send sonar address for read */
    I2C_Send7bitAddress(I2C1, device_address, I2C_Direction_Receiver);

    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_ADDR_TIMEOUT);
    }

    /* Call User callback for critical section start (should typically disable interrupts) */
    __disable_irq();

    /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
    (void)I2C1->SR2;

    /*!< Disable Acknowledgement */
    I2C_AcknowledgeConfig(I2C1, DISABLE);

    /* Call User callback for critical section end (should typically re-enable interrupts) */
    __enable_irq();

    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_BTF_TIMEOUT);
    }

    //6. Read the two data bytes, high and low from SRF02

    /* Wait for the byte to be received */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_RXNE_TIMEOUT);
    }

    /*!< Read first data byte from sonar  */
    data = I2C_ReceiveData(I2C1) << 8;

    /* Wait for the byte to be received */
    timeout = I2C_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_FLAG_RXNE_TIMEOUT);
    }

    /*!< Read second data byte from sonar */
    data |= I2C_ReceiveData(I2C1);

    //7. Send the stop sequence.

    __disable_irq();

    /*!< Send STOP Condition */
    I2C_GenerateSTOP(I2C1, ENABLE);

    /* Call User callback for critical section end (should typically re-enable interrupts) */
    __enable_irq();

    /* Wait to make sure that STOP control bit has been cleared */
    timeout = I2C_TIMEOUT;
    while(I2C1->CR1 & I2C_CR1_STOP)
    {
        if((timeout--) == 0) return I2Ctimeout(I2C_RX_CLEAR_STOP_TIMEOUT);
    }

    /*!< Re-Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig(I2C1, ENABLE);

    I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);

    return data;
}
Example #13
0
/**
@brief Read from I2C
@param[in]	devnum		I2C peripheral number (1 or 2)
@param[in]	adr			I2C address
@param[out]	buf			pointer to caller allocated buffer for data
@param[in]	nbyte		number of bytes to read (nbyte <= sizeof(buf))
@return 0 on success, non-zero otherwise
*/
uint8_t i2c_rd(uint8_t devnum, uint8_t adr, uint8_t *buf, uint32_t nbyte)
{
	I2C_TypeDef* I2Cx = i2c_get_pdef(devnum)->i2c;
	//__IO uint32_t Timeout = 0;

	//    I2Cx->CR2 |= I2C_IT_ERR;  interrupts for errors

	if (!nbyte) { return 1; }

	// Wait for idle I2C interface
	i2c_waitfor(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY), 1);

	// Enable Acknowledgement, clear POS flag
	I2C_AcknowledgeConfig(I2Cx, ENABLE);
	I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

	// Intiate Start Sequence (wait for EV5)
	I2C_GenerateSTART(I2Cx, ENABLE);
	i2c_waitfor(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT), 2);

	// Send Address
	I2C_Send7bitAddress(I2Cx, adr, I2C_Direction_Receiver);

	// EV6
	i2c_waitfor(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR), 3);

	if (nbyte == 1) {
		// Clear Ack bit
		I2C_AcknowledgeConfig(I2Cx, DISABLE);

		// EV6_1 -- must be atomic -- Clear ADDR, generate STOP
		__disable_irq();
		(void) I2Cx->SR2;
		I2C_GenerateSTOP(I2Cx,ENABLE);
		__enable_irq();

		// Receive data   EV7
		i2c_waitfor(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE), 4);
		*buf++ = I2C_ReceiveData(I2Cx);
		} else
		if (nbyte == 2) {
		// Set POS flag
		I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);

		// EV6_1 -- must be atomic and in this order
		__disable_irq();
		(void) I2Cx->SR2;                           // Clear ADDR flag
		I2C_AcknowledgeConfig(I2Cx, DISABLE);       // Clear Ack bit
		__enable_irq();

		// EV7_3  -- Wait for BTF, program stop, read data twice
		i2c_waitfor(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF), 5);

		__disable_irq();
		I2C_GenerateSTOP(I2Cx,ENABLE);
		*buf++ = I2Cx->DR;
		__enable_irq();

		*buf++ = I2Cx->DR;
	} else {
		(void) I2Cx->SR2;                           // Clear ADDR flag
		while (nbyte-- != 3) {
			// EV7 -- cannot guarantee 1 transfer completion time, wait for BTF
			//        instead of RXNE
			i2c_waitfor(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF), 6);
			*buf++ = I2C_ReceiveData(I2Cx);
		}

		i2c_waitfor(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF), 7);

		// EV7_2 -- Figure 1 has an error, doesn't read N-2 !
		I2C_AcknowledgeConfig(I2Cx, DISABLE);           // clear ack bit

		__disable_irq();
		*buf++ = I2C_ReceiveData(I2Cx);             // receive byte N-2
		I2C_GenerateSTOP(I2Cx,ENABLE);                  // program stop
		__enable_irq();

		*buf++ = I2C_ReceiveData(I2Cx);             // receive byte N-1

		// wait for byte N
		i2c_waitfor(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED), 8);
		*buf++ = I2C_ReceiveData(I2Cx);

		nbyte = 0;
	}

	// Wait for stop
	i2c_waitfor(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF), 9);
	return 0;
}
Example #14
0
/**
  * @brief  This function handles I2Cx event interrupt request.
  * @param  None
  * @retval None
  */
void I2Cx_EV_IRQHANDLER(void)
{
#if defined (I2C_MASTER)
  /* Once the Start condition is sent the master can be master receiver 
  or master transmitter */
  if (MasterMode == MASTER_MODE_TRANSMITTER)
  { 
    /* Get Last I2C Event */
    Event = I2C_GetLastEvent(I2Cx);
    switch (Event)
    {
  /* ************************************************************************/
  /*                        Master Transmitter Events                       */
  /*                                                                        */
  /* ************************************************************************/ 
/* Sending the header sequence for Master Transmitter case ----------------*/
      
#ifdef I2C_10BITS_ADDRESS
      /* Check on EV5 */
    case I2C_EVENT_MASTER_MODE_SELECT :
      /* Send Header to Slave for write */
      I2C_SendData(I2Cx, HEADER_ADDRESS_Write);
      break;
      
      /* Check on EV9 */
    case I2C_EVENT_MASTER_MODE_ADDRESS10:
      /* Send slave Address for write */
      I2C_Send7bitAddress(I2Cx, (uint8_t)SLAVE_ADDRESS, I2C_Direction_Transmitter);
      break;
      
      
#else  /* I2C_7BITS_ADDRESS */
      /* Check on EV5 */
    case I2C_EVENT_MASTER_MODE_SELECT :
      /* Send slave Address for write */
      I2C_Send7bitAddress(I2Cx, (uint8_t)SLAVE_ADDRESS, I2C_Direction_Transmitter);
      break;
      
#endif /* I2C_10BITS_ADDRESS */ 
      
      /* Check on EV6 */
    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
      /* Transmit the First Data  */
      I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
      break;
      
      /* Check on EV8 */
    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
    case I2C_EVENT_MASTER_BYTE_TRANSMITTED:      
      if (Tx_Idx == (uint8_t)NumberOfByteToTransmit)
      {
        /* Send STOP condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);
        I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
      }
      else
      {
        /* Transmit Data TxBuffer */
        I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
      }
      break;
           
    default:
      break;
    }
    
  }
  /*************************************************************************/
  /*                        Master Receiver Events                         */
  /*                                                                       */
  /*************************************************************************/
  else /* MASTER_MODE_RECEIVER */
  {
#ifdef I2C_10BITS_ADDRESS  
    /* Check on SB Flag and clear it */
    if(I2C_GetITStatus(I2Cx, I2C_IT_SB)== SET)
    {
      if (Send_HeaderStatus == 0x00) 
      {
        /* Send Header to Slave for write */
        I2C_SendData(I2Cx, HEADER_ADDRESS_Write);
        Send_HeaderStatus = 0x01;
        GenerateStartStatus = 0x01;
      }
      else
      {
        /* Send Header to Slave for Read */
        I2C_SendData(I2Cx, HEADER_ADDRESS_Read);
        Send_HeaderStatus = 0x00;
        if (NumberOfByteToReceive == 0x03)
        {
          /* Disable buffer Interrupts */
          I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
        }
        else
        {
          /* Enable buffer Interrupts */
          I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
        }
      }
    }
    /* Check on ADD10 Flag */
    else if(I2C_GetITStatus(I2Cx, I2C_IT_ADD10)== SET)
    {
      /* Send slave Address */
      I2C_Send7bitAddress(I2Cx, (uint8_t)SLAVE_ADDRESS, I2C_Direction_Transmitter);   
    }   
    
#else /* I2C_7BITS_ADDRESS */
    
    /* Check on EV5 */
    if(I2C_GetITStatus(I2Cx, I2C_IT_SB)== SET)
    {
      /* Send slave Address for read */
      I2C_Send7bitAddress(I2Cx, SLAVE_ADDRESS, I2C_Direction_Receiver);
      if (NumberOfByteToReceive == 0x03)
      {
        /* Disable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
      }
      else
      {
        /* Enable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
      }
    }  
#endif /* I2C_10BITS_ADDRESS */
    
    else if(I2C_GetITStatus(I2Cx, I2C_IT_ADDR)== SET)
    {
      if (NumberOfByteToReceive == 1)
      {
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
      }
      /* Clear ADDR Register */
      (void)(I2Cx->SR1);
      (void)(I2Cx->SR2);  
      if (GenerateStartStatus == 0x00)
      { 
        if (NumberOfByteToReceive == 1)
        {
          I2C_GenerateSTOP(I2Cx, ENABLE);  
        }  
        
        if (NumberOfByteToReceive == 2)
        {
          I2C_AcknowledgeConfig(I2Cx, DISABLE);
          I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);
          /* Disable buffer Interrupts */
          I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
        }
      }
      
#ifdef I2C_10BITS_ADDRESS   
      if (GenerateStartStatus == 0x01)
      {
        /* Repeated Start */
        I2C_GenerateSTART(I2Cx, ENABLE);
        GenerateStartStatus = 0x00;
      }
      
#endif /* I2C_10BITS_ADDRESS */
    } 
    else if((I2C_GetITStatus(I2Cx, I2C_IT_RXNE)== SET)&&(I2C_GetITStatus(I2Cx, I2C_IT_BTF)== RESET))
    {
      /* Store I2C received data */
      RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
      NumberOfByteToReceive--;
      
      if (NumberOfByteToReceive == 0x03)
      {
        /* Disable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
      }
      
      if (NumberOfByteToReceive == 0x00)
      {
        /* Disable Error and Buffer Interrupts */
        I2C_ITConfig(I2Cx, (I2C_IT_EVT | I2C_IT_BUF), DISABLE);            
      }
    }    
    /* BUSY, MSL and RXNE flags */
    else if(I2C_GetITStatus(I2Cx, I2C_IT_BTF)== SET)
    {
      /* if Three bytes remaining for reception */
      if (NumberOfByteToReceive == 3)
      {
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        /* Store I2C received data */
        RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
        NumberOfByteToReceive--;        
      } 
      else if (NumberOfByteToReceive == 2)
      {           
        I2C_GenerateSTOP(I2Cx, ENABLE);    
        
        /* Store I2C received data */
        RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
        NumberOfByteToReceive--;
        /* Store I2C received data */
        RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
        NumberOfByteToReceive--;        
        /* Disable Error and Buffer Interrupts */
        I2C_ITConfig(I2Cx, (I2C_IT_EVT | I2C_IT_BUF), DISABLE);            
      }
      else 
      {
        /* Store I2C received data */
        RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
        NumberOfByteToReceive--;
      }
    } 
  }  
#endif /* I2C_MASTER*/
  

#if defined (I2C_SLAVE)
  /* Get Last I2C Event */
  Event = I2C_GetLastEvent(I2Cx);
  switch (Event)
  { 
    /* ****************************************************************************/
    /*                          Slave Transmitter Events                          */
    /*                                                                            */
    /* ****************************************************************************/  
    
    /* Check on EV1 */
  case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:  
    I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
    I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
    break;
    /* Check on EV3 */
  case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:
  case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:    
    if (Tx_Idx < NumberOfByteToTransmit)
    {
      I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
    }
    else
    {
      /* Disable I2C event interrupt */
      I2C_ITConfig(I2Cx, I2C_IT_EVT  | I2C_IT_BUF, DISABLE);
    }
    break;
    
    /* ****************************************************************************/
    /*                              Slave Receiver Events                         */
    /*                                                                            */
    /* ****************************************************************************/ 
    
    /* check on EV1*/
  case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
    Rx_Idx = 0x00;
    break;
    
    /* Check on EV2*/
  case I2C_EVENT_SLAVE_BYTE_RECEIVED:  
  case (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_SR1_BTF):  
    RxBuffer[Rx_Idx++] = I2C_ReceiveData(I2Cx);
    break;
 
    /* Check on EV4 */
  case I2C_EVENT_SLAVE_STOP_DETECTED:             
    I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);
    I2C_Cmd(I2Cx, ENABLE);
    break;
    
  default:
    break;
  }
#endif /* I2C_SLAVE*/  
}
Example #15
0
// Read data from I2C port
// input:
//   buf - pointer to data buffer
//   nbytes - number of bytes to receive
//   SlaveAddress - address of slave device
// return:
//   I2C_ERROR if there was a timeout during I2C operations, I2C_SUCCESS otherwise
I2C_Status I2C2_Read(uint8_t *buf, uint32_t nbytes, uint8_t SlaveAddress) {
	volatile uint32_t TimeOut;

	I2C_AcknowledgeConfig(I2C2_PORT,ENABLE); // Enable Acknowledgment
	I2C_NACKPositionConfig(I2C2_PORT,I2C_NACKPosition_Current); // Clear POS flag

	// Initiate start sequence
	I2C_GenerateSTART(I2C2_PORT,ENABLE);
	// Wait for EV5
	TimeOut = 0;
	while (!I2C_CheckEvent(I2C2_PORT,I2C_EVENT_MASTER_MODE_SELECT) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
	if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;

	// Send slave address
	I2C_Send7bitAddress(I2C2_PORT,SlaveAddress,I2C_Direction_Receiver); // Send slave address
	// Wait for EV6
	TimeOut = 0;
	while (!I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_ADDR) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
	if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;

	// There are can be three cases:
	//   read 1 byte
	//   read 2 bytes
	//   read more than 2 bytes
	if (nbytes == 1) {
		// Receive 1 byte (AN2824 figure 2)
		I2C_AcknowledgeConfig(I2C2_PORT,DISABLE); // Disable I2C acknowledgment (clear ACK bit)
		// EV6_1 must be atomic operation (AN2824)
		__disable_irq();
		(void) I2C2_PORT->SR1; // Clear ADDR
		(void) I2C2_PORT->SR2;
		I2C_GenerateSTOP(I2C2_PORT,ENABLE); // Send STOP condition
		__enable_irq();
		// Wait for RxNE flag (receive buffer not empty) EV7
		TimeOut = 0;
		while (!I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_RXNE) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
		if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;
		*buf++ = I2C_ReceiveData(I2C2_PORT); // Receive byte
	} else if (nbytes == 2) {
		// Receive 2 bytes (AN2824 figure 2)
		I2C_NACKPositionConfig(I2C2_PORT,I2C_NACKPosition_Next); // Set POS flag
		// EV6_1 must be atomic operation (AN2824)
		__disable_irq();
		(void) I2C2_PORT->SR2; // Clear ADDR
		I2C_AcknowledgeConfig(I2C2_PORT,DISABLE); // Clear ACK bit
		__enable_irq();
		// Wait for BTF flag set (byte transfer finished) EV7_3
		TimeOut = 0;
		while (!I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_BTF) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
		if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;

		__disable_irq();
		I2C_GenerateSTOP(I2C2_PORT,ENABLE); // Send STOP condition
		*buf++ = I2C2_PORT->DR; // Faster than call I2C_ReceiveData()
		__enable_irq();

		*buf++ = I2C2_PORT->DR; // Read second received byte
	} else {
		// Receive more than 2 bytes (AN2824 figure 1)
		(void) I2C2_PORT->SR2; // Clear ADDR flag
		while (nbytes-- != 3) {
			// Wait for BTF (cannot guarantee 1 transfer completion time)
			TimeOut = 0;
			while (!I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_BTF) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
			if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;
			*buf++ = I2C_ReceiveData(I2C2_PORT);
		}
		// Wait for BTF flag set (byte transfer finished) EV7_2
		TimeOut = 0;
		while (!I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_BTF) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
		if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;

		I2C_AcknowledgeConfig(I2C2_PORT,DISABLE); // Clear ACK bit

		__disable_irq();
		*buf++ = I2C_ReceiveData(I2C2_PORT); // Receive byte N-2
		I2C_GenerateSTOP(I2C2_PORT,ENABLE); // Send STOP condition
		__enable_irq();

		*buf++ = I2C_ReceiveData(I2C2_PORT); // Receive byte N-1
		// Wait for last byte received
		TimeOut = 0;
		while (!I2C_CheckEvent(I2C2_PORT,I2C_EVENT_MASTER_BYTE_RECEIVED) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
		if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;
		*buf++ = I2C_ReceiveData(I2C2_PORT); // Receive last byte

		nbytes = 0;
	}

	// Wait for STOP flag
	TimeOut = 0;
	while (I2C_GetFlagStatus(I2C2_PORT,I2C_FLAG_STOPF) && TimeOut < I2C_WAIT_TIMEOUT) TimeOut++;
	if (TimeOut == I2C_WAIT_TIMEOUT) return I2C_ERROR;

	return I2C_SUCCESS;
}
Example #16
0
int readFrom(byte _dev_address,byte address, int num, byte _buff[]) {
  int a=0,i=0;
  int timeout;
  uint8_t flag1=0,flag2=0;
  a=i2c_beginTransmission(I2Ci,_dev_address,i2c_write); // start transmission to device
  if(a<0) return -1;
 // usart_printfm(USART1,(const int *)"Reading from this device address: %2x\n\r",_dev_address);
  a=i2c_sendData(I2Ci,address);             // sends address to read from
  if(a<0) return -1;
  //usart_printfm(USART1,(const int *)"sent this data which is the address to read from: %2x\n\r",address);
  //  if(a<0)
//     return (a-1);
  //i2c_stopTransmission(I2Cx);         // end transmission
//  if(a<0)
//     return (a-2);
  a=i2c_beginTransmission(I2Ci,_dev_address,i2c_read); // start transmission to device
  if(a<0) return -1;
  //usart_printfm(USART1,(const int *)"Initiated the register read cycle: %2x\n\r",_dev_address);
  //  if(a<0)
//     return a;
  // request 6 bytes from device
  if(num==1){
    I2C_AcknowledgeConfig(I2Ci, DISABLE);
	
        
        /* Test on I2C1 EV8 and clear it */
        timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
         
        
	// wait until one byte has been received
      
	while( !I2C_CheckEvent(I2Ci, I2C_EVENT_MASTER_BYTE_RECEIVED) ){
          ms_delay(100);
          if((timeout--)==0){
            flag1 = I2Ci->SR1;
            flag2 = I2Ci->SR2;
            usart_printf(USARTx,"Flag1:%04x \n\r Flag2:%04x\n\r",flag1,flag2);
            usart_printf(USARTx,"Failing at read nnack stage\n\r");
            return -1;
          }
        }
	// wait until one byte has been received
	 I2C_GenerateSTOP(I2Ci, ENABLE);
	// read data from I2C data register and return data byte
	_buff[i] = I2C_ReceiveData(I2Ci);
        return 0;
  }
  if(num==2)
  {
    timeout = I2C_TIMEOUT_MAX; 
//    while(I2C_GetFlagStatus(I2Ci,I2C_FLAG_ADDR)!=SET){
//     ms_delay(100);
//          if((timeout--)==0){
//            flag1 = I2Ci->SR1;
//            flag2 = I2Ci->SR2;
//            usart_printf(USARTx,"Flag1:%04x \n\r Flag2:%04x\n\r",flag1,flag2);
//            usart_printf(USARTx,"Failing at reading 2 bytes stage\n\r");
//            return ;
//          }}
    I2C_AcknowledgeConfig(I2Ci, DISABLE);
    I2C_NACKPositionConfig(I2Ci, I2C_NACKPosition_Next);
    timeout = I2C_TIMEOUT_MAX; 
    while(I2C_GetFlagStatus(I2Ci,I2C_FLAG_BTF)!=SET){
      ms_delay(100);
          if((timeout--)==0){
            flag1 = I2Ci->SR1;
            flag2 = I2Ci->SR2;
            usart_printf(USARTx,"Flag1:%04x \n\r Flag2:%04x\n\r",flag1,flag2);
            usart_printf(USARTx,"Failing at reading 2 bytes stage2\n\r");
            return -1;
          }}
    
    i2c_stopTransmission(I2Ci);
    _buff[i] = I2C_ReceiveData(I2Ci);
    i++;
    _buff[i] = I2C_ReceiveData(I2Ci);
    num-=2;
    // receive a byte
    //usart_printfm(USART1,(const int *)"this byte read from accel: %2x\n\r",i);
   return 0; 
  }
  while(num>0)         // device may send less than requested (abnormal)
  if(num==3){
  //_buff[i]=I2C_read_ack(I2Cx);
    timeout = I2C_TIMEOUT_MAX; 
    while(I2C_GetFlagStatus(I2Ci,I2C_FLAG_BTF)!=SET){
     ms_delay(100);
          if((timeout--)==0){
            flag1 = I2Ci->SR1;
            flag2 = I2Ci->SR2;
            usart_printf(USARTx,"Flag1:%04x \n\r Flag2:%04x\n\r",flag1,flag2);
            usart_printf(USARTx,"Failing at reading 2 bytes stage2\n\r");
            return -1;
          }}
  I2C_AcknowledgeConfig(I2Ci, DISABLE);
  _buff[i]=I2C_ReceiveData(I2Ci);
  
  i++;
  num--;
  while(I2C_GetFlagStatus(I2Ci,I2C_FLAG_BTF)!=SET)
    {
     ms_delay(100);
          if((timeout--)==0){
            flag1 = I2Ci->SR1;
            flag2 = I2Ci->SR2;
            usart_printf(USARTx,"Flag1:%04x \n\r Flag2:%04x\n\r",flag1,flag2);
            usart_printf(USARTx,"Failing at reading 2 bytes stage2\n\r");
            return -1;
          }}
  i2c_stopTransmission(I2Ci);
  _buff[i]=I2C_ReceiveData(I2Ci);
  i++;
  _buff[i]=I2C_ReceiveData(I2Ci);
  i++;
  num-=2;
  //usart_print(USART1,"This byte read from nack: %2x\n\r",i);
  return 0; 
  }
  else{
    a=I2C_read(I2Ci,_buff[i]);
     if(a<0) return -1;
    i++;
    num--;
  }
//  if(i != num){
//    status = ADXL345_ERROR;
//    error_code = ADXL345_READ_ERROR;
//  }
  //ms_delay(10);
  //i2c_stopTransmission(I2Cx);         // end transmission
//end :
//  usart_printf(USARTx,"Error occured !! Restarting the interface!!");
//  ms_delay(5000);
//  return -1;
return 0;
}
Example #17
0
/**
  * @brief  This function handles I2Cx event interrupt request.
  * @param  None
  * @retval None
  */
void I2Cx_EV_IRQHandler(void)
{
#if defined (I2C_SLAVE)
  /* Get Last I2C Event */
  Event = I2C_GetLastEvent(I2Cx);
  switch (Event)
  { 
    /*****************************************************************************/
    /*                          Slave Transmitter Events                         */
    /*                                                                           */
    /* ***************************************************************************/  
    
    /* Check on EV1 */
  case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:  
      I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
      /* Enable I2C event interrupt */
      I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE);
    break;
    
    /* Check on EV3 */
  case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:  
  case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:  
    if (Tx_Idx < NbrOfDataToSend)
      I2C_SendData(I2Cx, TxBuffer[Tx_Idx++]);
    else
      /* Disable I2C event interrupt */
      I2C_ITConfig(I2Cx, I2C_IT_EVT  | I2C_IT_BUF, DISABLE);
    break;
 
  default:
    break;  
  }
#endif /* I2C_SLAVE*/
  
#if defined (I2C_MASTER)
/*****************************************************************************/
/*                               Master Receiver                             */
/*                                                                           */
/* ***************************************************************************/  
#ifdef I2C_10BITS_ADDRESS  
  /* Check on SB Flag and clear it */
  if(I2C_GetITStatus(I2Cx, I2C_IT_SB)== SET)
  {
    if (Send_HeaderStatus == 0x00) 
    {
      /* Send Header to Slave for write */
      I2C_SendData(I2Cx, HEADER_ADDRESS_Write);
      Send_HeaderStatus = 0x01;
      GenerateStartStatus = 0x01;
    }
    else
    {
      /* Send Header to Slave for Read */
      I2C_SendData(I2Cx, HEADER_ADDRESS_Read);
      Send_HeaderStatus = 0x00;
      if (NumberOfByteToReceive == 0x03)
      {
        /* Disable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
      }
      else
      {
        /* Enable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
      }
    }
  }
  /* Check on ADD10 Flag */
  else if(I2C_GetITStatus(I2Cx, I2C_IT_ADD10)== SET)
  {
    /* Send slave Address */
    I2C_Send7bitAddress(I2Cx, (uint8_t)SLAVE_ADDRESS, I2C_Direction_Transmitter);   
  }   
  
#else /* I2C_7BITS_ADDRESS */
  
  /* Check on EV5 */
  if(I2C_GetITStatus(I2Cx, I2C_IT_SB)== SET)
  {
    /* Send slave Address for read */
    I2C_Send7bitAddress(I2Cx, SLAVE_ADDRESS, I2C_Direction_Receiver);
    if (NumberOfByteToReceive == 0x03)
    {
      /* Disable buffer Interrupts */
      I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
    }
    else
    {
      /* Enable buffer Interrupts */
      I2C_ITConfig(I2Cx, I2C_IT_BUF , ENABLE);
    }
  }  
#endif /* I2C_10BITS_ADDRESS */
  
  else if(I2C_GetITStatus(I2Cx, I2C_IT_ADDR)== SET)
  {
    if (NumberOfByteToReceive == 1)
    {
      I2C_AcknowledgeConfig(I2Cx, DISABLE);
    }
    
    /* Clear ADDR Register */
    (void)(I2Cx->SR1);
    (void)(I2Cx->SR2);  
    if (GenerateStartStatus == 0x00)
    { 
      if (NumberOfByteToReceive == 1)
      {
         I2C_GenerateSTOP(I2Cx, ENABLE);  
      }  
      
      if (NumberOfByteToReceive == 2)
      {
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);
        /* Disable buffer Interrupts */
        I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
      }
    }
    
#ifdef I2C_10BITS_ADDRESS   
    if (GenerateStartStatus == 0x01)
    {
      /* Repeated Start */
      I2C_GenerateSTART(I2Cx, ENABLE);
      GenerateStartStatus = 0x00;
    }
    
#endif /* I2C_10BITS_ADDRESS */
  } 
  
  else if((I2C_GetITStatus(I2Cx, I2C_IT_RXNE)== SET)&&(I2C_GetITStatus(I2Cx, I2C_IT_BTF)== RESET))
  {
    /* Store I2C received data */
    RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
    NumberOfByteToReceive--;
    
    if (NumberOfByteToReceive == 0x03)
    {
      /* Disable buffer Interrupts */
      I2C_ITConfig(I2Cx, I2C_IT_BUF , DISABLE);
    }

    if (NumberOfByteToReceive == 0x00)
    {
      /* Disable Error and Buffer Interrupts */
      I2C_ITConfig(I2Cx, (I2C_IT_EVT | I2C_IT_BUF), DISABLE);            
    }
  }    
  /* BUSY, MSL and RXNE flags */
  else if(I2C_GetITStatus(I2Cx, I2C_IT_BTF)== SET)
  {
    /* if Three bytes remaining for reception */
    if (NumberOfByteToReceive == 3)
    {
      I2C_AcknowledgeConfig(I2Cx, DISABLE);
      /* Store I2C received data */
      RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
      NumberOfByteToReceive--;        
    } 
    else if (NumberOfByteToReceive == 2)
    {           
      I2C_GenerateSTOP(I2Cx, ENABLE);    
      
      /* Store I2C received data */
      RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
      NumberOfByteToReceive--;
      /* Store I2C received data */
      RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
      NumberOfByteToReceive--;        
      /* Disable Error and Buffer Interrupts */
      I2C_ITConfig(I2Cx, (I2C_IT_EVT | I2C_IT_BUF), DISABLE);            
    }
    else 
    {
      /* Store I2C received data */
      RxBuffer[Rx_Idx++] = I2C_ReceiveData (I2Cx);
      NumberOfByteToReceive--;
    }
  } 
#endif /* I2C_MASTER*/
}
Example #18
0
File: i2c.c Project: pandc/unitek
int I2C_RandRead(uint8_t slave,uint16_t addr,uint8_t addrsize,void *pbuffer,uint16_t len)
{
struct i2c_job_st i2c_jobs[2];
uint8_t buf_offset[2];

	xSemaphoreTake(xSemaphoreI2C_Mutex,portMAX_DELAY);

	if (I2C_isBusy())
	{
		i2c_error_flags = I2C_SR1_SB;
		xSemaphoreGive(xSemaphoreI2C_Mutex);
		return FALSE;
	}

	i2c_cntr = 0;
	i2c_oper = I2C_Direction_Transmitter;
	job = i2c_jobs;
	i2c_addr = slave << 1;
	memset(i2c_jobs,0,sizeof(i2c_jobs));
	if (addrsize == 1)
		buf_offset[0] = (uint8_t)addr;
	else
	{
		buf_offset[0] = (uint8_t)(addr >> 8);
		buf_offset[1] = (uint8_t)(addr & 0xff);
	}

	i2c_jobs[0].buf = buf_offset;
	i2c_jobs[0].len = addrsize;
	i2c_jobs[0].dir = I2C_Direction_Transmitter;

	i2c_jobs[1].buf = (uint8_t *)pbuffer;
	i2c_jobs[1].len = len;
	i2c_jobs[1].dir = I2C_Direction_Receiver;
	i2c_jobs[1].last = TRUE;

	i2c_error_flags = 0;
	i2c_done = i2c_err = FALSE;

	// clear the semaphore
	while (xSemaphoreTake(xSemaphoreI2C_Work,0));

	I2C_AcknowledgeConfig(I2Cx,ENABLE);
	I2C_NACKPositionConfig(I2Cx,I2C_NACKPosition_Current);
	I2C_ITConfig(I2Cx,I2C_IT_BUF | I2C_IT_ERR | I2C_IT_EVT,ENABLE);

	/* Send START condition */
	I2C_GenerateSTART(I2Cx, ENABLE);

	while (!i2c_done && !i2c_err)
	{
		if (!xSemaphoreTake(xSemaphoreI2C_Work,SEMA_DELAY))
		{
			I2C_Open(0);
			i2c_err = TRUE;
			break;
		}
	}

	I2C_ITConfig(I2Cx,I2C_IT_BUF | I2C_IT_ERR | I2C_IT_EVT,DISABLE);

	xSemaphoreGive(xSemaphoreI2C_Mutex);
	return !i2c_err;
}
Example #19
0
Status I2C_Read(I2C_TypeDef* I2Cx, uint8_t *buf,uint32_t nbyte, uint8_t SlaveAddress)
{
  __IO uint32_t Timeout = 0;

  //    I2Cx->CR2 |= I2C_IT_ERR;  interrupts for errors 

  if (!nbyte)
    return Success;



  // Wait for idle I2C interface

  Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));

  // Enable Acknowledgement, clear POS flag

  I2C_AcknowledgeConfig(I2Cx, ENABLE);
  I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

  // Intiate Start Sequence (wait for EV5

  I2C_GenerateSTART(I2Cx, ENABLE);
  Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

  // Send Address

  I2C_Send7bitAddress(I2Cx, SlaveAddress, I2C_Direction_Receiver);

  // EV6
  
  Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR));

  if (nbyte == 1)
    {

      // Clear Ack bit      

      I2C_AcknowledgeConfig(I2Cx, DISABLE);       

      // EV6_1 -- must be atomic -- Clear ADDR, generate STOP

      __disable_irq();
      (void) I2Cx->SR2;                           
      I2C_GenerateSTOP(I2Cx,ENABLE);      
      __enable_irq();

      // Receive data   EV7

      Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE));
      *buf++ = I2C_ReceiveData(I2Cx);

    }
  else if (nbyte == 2)
    {
      // Set POS flag

      I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);

      // EV6_1 -- must be atomic and in this order

      __disable_irq();
      (void) I2Cx->SR2;                           // Clear ADDR flag
      I2C_AcknowledgeConfig(I2Cx, DISABLE);       // Clear Ack bit
      __enable_irq();

      // EV7_3  -- Wait for BTF, program stop, read data twice

      Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF));

      __disable_irq();
      I2C_GenerateSTOP(I2Cx,ENABLE);
      *buf++ = I2Cx->DR;
      __enable_irq();

      *buf++ = I2Cx->DR;

    }
  else 
    {
      (void) I2Cx->SR2;                           // Clear ADDR flag
      while (nbyte-- != 3)
	{
	  // EV7 -- cannot guarantee 1 transfer completion time, wait for BTF 
          //        instead of RXNE

	  Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF)); 
	  *buf++ = I2C_ReceiveData(I2Cx);
	}

      Timed(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF));  

      // EV7_2 -- Figure 1 has an error, doesn't read N-2 !

      I2C_AcknowledgeConfig(I2Cx, DISABLE);           // clear ack bit

      __disable_irq();
      *buf++ = I2C_ReceiveData(I2Cx);             // receive byte N-2
      I2C_GenerateSTOP(I2Cx,ENABLE);                  // program stop
      __enable_irq();

      *buf++ = I2C_ReceiveData(I2Cx);             // receive byte N-1

      // wait for byte N

      Timed(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED)); 
      *buf++ = I2C_ReceiveData(I2Cx);

      nbyte = 0;

    }

  // Wait for stop

  Timed(I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF));
  return Success;

 errReturn:

  // Any cleanup here
  return Error;

}