/**
  ******************************************************************************
  * @file    	i2c.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    24-11-2014
  * @brief   
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************  
  */ 
#include "stm8l15x.h"
#include "i2c.h"

 /*I2C从设备*/
uint8_t SlaveAddress;
extern u8 BUF[8]; 

static void I2C_delay(void);
//static void delay5ms(void);
static bool I2C_Start(void);
static uint8_t I2C_RadeByte(void);
static void I2C_SendByte(uint8_t SendByte);
static bool I2C_WaitAck(void);
static void I2C_NoAck(void);
//static void I2C_Ack(void);
static void I2C_Stop(void);


/*I2C端口初始化---------------------------------------*/
void I2C_GPIO_Init(void)
{
    GPIO_Init(I2C_GPIO, I2C_SCL_PIN, GPIO_Mode_Out_OD_Low_Fast);
    GPIO_Init(I2C_GPIO, I2C_SDA_PIN, GPIO_Mode_Out_OD_Low_Fast);	
}

/*I2C的延时函数-----------------------------------------*/
void I2C_delay(void)//5us
{
		
  // uint8_t i=30; //这里可以优化速度	，经测试最低到5还能写入
  // while(i) 
  // { 
  //   i--; 
  // }  
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop();
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop();
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop();
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); 
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); 
    nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); 

    
}


/*I2C启动函数-------------------------------------------*/
bool I2C_Start(void)
{
#if 1   
        SDA_H;
	SCL_H;
	I2C_delay();
	if(!SDA_read)return FALSE;	//SDA线为低电平则总线忙,退出
	SDA_L;
	I2C_delay();
	if(SDA_read) return FALSE;	//SDA线为高电平则总线出错,退出
	SDA_L;
	I2C_delay();
	return TRUE;
#else
    SDA_H;                    //拉高数据线
    SCL_H;                    //拉高时钟线
    I2C_delay();                 //延时
    SDA_L;                    //产生下降沿
    I2C_delay();                 //延时
    SCL_L;
    return TRUE;
#endif
}

/*I2C停止函数-------------------------------------------*/
void I2C_Stop(void)
{
#if 1
        SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SDA_H;
	I2C_delay();
#else
    SDA_L;                    //拉低数据线
    SCL_H;                    //拉高时钟线
    I2C_delay();                 //延时
    SDA_H;                    //产生上升沿
    I2C_delay(); 
#endif
} 

/*I2C的ACK函数------------------------------------------*/
/*void I2C_Ack(void)
{	
	SCL_L;
	I2C_delay();
	SDA_L;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
}   


*/
void I2C_Ack(u8 ack)
{
    if(ack==1)
        SDA_H;
    else
        SDA_L;
    SCL_H;                    //拉高时钟线
    I2C_delay();                 //延时
    SCL_L;                    //拉低时钟线
    I2C_delay();                 //延时
}
/*I2C的NoACK函数----------------------------------------*/
void I2C_NoAck(void)
{	
	SCL_L;
	I2C_delay();
	SDA_H;
	I2C_delay();
	SCL_H;
	I2C_delay();
	SCL_L;
	I2C_delay();
} 

/*I2C等待ACK函数----------------------------------------*/
bool I2C_WaitAck(void) 	 //返回为:=1有ACK,=0无ACK
{
#if 1
        SCL_L;
	I2C_delay();
	SDA_H;			
	I2C_delay();
	SCL_H;
	I2C_delay();
	if(SDA_read)
	{
            SCL_L;
            I2C_delay();
            return FALSE;
	}
	SCL_L;
	I2C_delay();
	return TRUE;
#else
    SCL_H;                    //拉高时钟线
    I2C_delay();                //延时
    if(SDA_read)
    {
        SCL_L;
        I2C_delay();
        return FALSE;
    }                   //进位标志 读应答信号
    else
    {
        SCL_L;
        I2C_delay();
        return TRUE;
    }
#endif
}

/*I2C发送一个u8数据函数---------------------------------*/
void I2C_SendByte(uint8_t SendByte) //数据从高位到低位//
{
#if 1
  uint8_t i = 8;
    while(i--)
    {
        SCL_L;
        I2C_delay();
        if(SendByte&0x80)
            SDA_H;  
        else 
            SDA_L;   
       // I2C_delay();
        SCL_H;
        I2C_delay(); 
        SendByte<<=1;
    }
    SCL_L;
#else
    u8 i;

    for (i=0; i<8; i++)         //8位计数器
    {
        //SendByte <<= 1;              //移出数据的最高位
        if(SendByte&0x80)
            SDA_H;  
        else 
            SDA_L;                //送数据口
        SendByte <<= 1;
        SCL_H;                //拉高时钟线
        I2C_delay();             //延时
        SCL_L;                //拉低时钟线
        I2C_delay();             //延时
    }
    I2C_WaitAck();
#endif
}  

/*I2C读取一个u8数据函数---------------------------------*/
uint8_t I2C_RadeByte(void)  //数据从高位到低位//
{ 
#if 1
    uint8_t i = 8;
    uint8_t ReceiveByte = 0;

    SDA_H;				
    while(i--)
    {
        ReceiveByte<<=1;      
        SCL_L;
        I2C_delay();
        SCL_H;
        I2C_delay();	
        if(SDA_read)
        {
            ReceiveByte|=0x01;
        }
    }
    SCL_L;
    return ReceiveByte;
#else
    u8 i;
    u8 dat = 0;

    SDA_H;                    //使能内部上拉,准备读取数据,
    for (i=0; i<8; i++)         //8位计数器
    {
        dat <<= 1;
        SCL_H;                //拉高时钟线
        I2C_delay();             //延时
        if(SDA_read)
        {
            dat |= 1;             //读数据
        }
        else
        {
            dat |= 0;
        }              
        SCL_L;                //拉低时钟线
        I2C_delay();             //延时
    }
    return dat;
#endif
} 
         
/*I2C向指定设备指定地址写入u8数据-----------------------*/
void Single_WriteI2C(uint8_t REG_Address,uint8_t REG_data)//单字节写入
{
	if(!I2C_Start())return;
	I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
	if(!I2C_WaitAck()){I2C_Stop(); return;}
	I2C_SendByte(REG_Address );   //设置低起始地址      
	I2C_WaitAck();    
	I2C_SendByte(REG_data);
	I2C_WaitAck();   
	I2C_Stop(); 
	//DelayMs(5); //qqqqqqqq
        bsp_DelayMS(5);
}

/*I2C向指定设备指定地址读出u8数据-----------------------*/
uint8_t Single_ReadI2C(uint8_t REG_Address)//读取单字节
{   
#if 1
  uint8_t REG_data;     	
    if(!I2C_Start())
        return FALSE;
    I2C_SendByte(SlaveAddress); //设置高起始地址+器件地址 
    if(!I2C_WaitAck())
    {
        I2C_Stop();
        return FALSE;
    }
    I2C_SendByte((u8) REG_Address);   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(SlaveAddress+1);
    I2C_WaitAck();
    REG_data= I2C_RadeByte();
    I2C_NoAck();
    I2C_Stop();
    return REG_data;
#else
	u8 REG_data;
	I2C_Start();                          //起始信号
	I2C_SendByte(SlaveAddress);           //发送设备地址+写信号
	I2C_SendByte(REG_Address);            //发送存储单元地址，从0开始	
	I2C_Start();                          //起始信号
	I2C_SendByte(SlaveAddress+1);         //发送设备地址+读信号
	REG_data=I2C_RadeByte();              //读出寄存器数据
	I2C_Ack(1);   
	I2C_Stop();                           //停止信号
  return REG_data; 
#endif
}


//******************************************************
//连续读出QMC5883内部角度数据，地址范围0x00~0x05
//******************************************************
void Multiple_Read_QMC5883(void)
{   
    u8 i;
    I2C_Start();                          //起始信号
    I2C_SendByte(SlaveAddress);          //发送设备地址+写信号
    I2C_WaitAck();
    I2C_SendByte(0x00);                   //发送存储单元地址，从0x00开始
    I2C_WaitAck();
    I2C_Start();                          //起始信号
    I2C_SendByte(SlaveAddress+1);        //发送设备地址+读信号
    I2C_WaitAck();
    for (i=0; i<6; i++)                      //连续读取6个地址数据，存储中BUF
    {
        BUF[i+1] = I2C_RadeByte();          //BUF[0]存储数据
        if (i == 5)
        {
           I2C_Ack(1);                //最后一个数据需要回非应答NOACK
        }
        else
        {
          I2C_Ack(0);                 //应答ACK
        }
   }
    I2C_Stop();                           //停止信号
   // DelayMs(5); //qqqqqq
    bsp_DelayMS(5);
}
u8 i2ctest(void)
{ 
    return Single_ReadI2C(0x09);
}

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/





