I2C软件模拟驱动

/*******************************************************************************
 * 文件名  :i2c_software.h
 * 描述    :软件IIC驱动配置头文件
 * 作者    :huangqi
 * 时间    : 2014/12/5
 * 版本    : V0.0.1
********************************************************************************/

#ifndef   I2C_SOFTWARE_H_
#define   I2C_SOFTWARE_H_

#include "stm8l15x.h"
#include "pin.h"
#include "time_delay.h"

typedef enum
{
    I2C_ACK_NO,
    I2C_ACK_YES,
}t_I2c_Ack_status;

typedef struct t_i2c_software_source  //用来描述一个软件模拟的I2C属性的结构
{
    const t_pin_source*     I2C_SCL;
    const t_pin_source*     I2C_SDA;
}t_i2c_software_source;

extern t_i2c_software_source I2c_Software_Source;

void drv_I2c_Delay(uint16_t time);
void drv_I2c_Software_Init(t_i2c_software_source* i2c_software_source);
void drv_I2c_Software_Start(t_i2c_software_source* i2c_software_source);
void drv_I2c_Software_Stop(t_i2c_software_source* i2c_software_source);
void drv_I2c_Software_AckNak(t_i2c_software_source* i2c_software_source,t_I2c_Ack_status Ack_Status);
uint8_t drv_I2c_Software_WaitAck(t_i2c_software_source* i2c_software_source);
void drv_I2c_Software_SendByte(t_i2c_software_source* i2c_software_source,uint8_t value);
uint8_t drv_I2c_Software_ReadByte(t_i2c_software_source* i2c_software_source);


#if 0
void Soft_I2c_SendByte(t_i2c_software_source* i2c_software_source,uint8_t WriteRegAddr,uint8_t Data);
uint8_t Soft_I2c_ReadByte(t_i2c_software_source* i2c_software_source,uint8_t ReadRegAddr);
#endif
#endif

/********************************************************************************
 * 文件名  :i2c_software.c
 * 描述    :软件IIC驱动配置文件
 * 作者    :huangqi
 * 时间    : 2014/12/5
 * 版本    : V0.0.1
*******************************************************************************/

#include "i2c_software.h"

/*******************************************************************************
 * 名称: drv_I2c_Delay
 * 功能: 软件模拟I2C延时函数    16MHz系统时针
 * 形参: time:延时的微秒数
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
void drv_I2c_Delay(uint16_t time)
{
    u8 i=0;
    do
    {
      for(i=0;i<5;i++)
      {
          //nop();
      }
    }while(time--);
}

/*******************************************************************************
 * 名称: drv_I2c_SclHigh
 * 功能: 软件模拟I2C设置SCL引脚拉高函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static void drv_I2c_SclHigh(t_i2c_software_source* i2c_software_source)
{
    drv_Gpio_SetBits(i2c_software_source->I2C_SCL);
}

/*******************************************************************************
 * 名称: drv_I2c_SclLow
 * 功能: 软件模拟I2C复位SCL引脚拉低函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static void drv_I2c_SclLow(t_i2c_software_source* i2c_software_source)
{
    drv_Gpio_ResetBits(i2c_software_source->I2C_SCL);
}

/*******************************************************************************
 * 名称: drv_I2c_SdaHigh
 * 功能: 软件模拟I2C设置SDA引脚拉高函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static void drv_I2c_SdaHigh(t_i2c_software_source* i2c_software_source)
{
    drv_Gpio_SetBits(i2c_software_source->I2C_SDA);
}

/*******************************************************************************
 * 名称: drv_I2c_SdaLow
 * 功能: 软件模拟I2C复位SDA引脚函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static void drv_I2c_SdaLow(t_i2c_software_source* i2c_software_source)
{
    drv_Gpio_ResetBits(i2c_software_source->I2C_SDA);
}

#if 0
/*******************************************************************************
 * 名称: drv_I2c_SclReadBit
 * 功能: 软件模拟I2C读SCL引脚值函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static t_pin_bit drv_I2c_SclReadBit(t_i2c_software_source* i2c_software_source)
{
    return drv_Gpio_ReadInputDataBit(i2c_software_source->I2C_SCL);
}
#endif

/*******************************************************************************
 * 名称: drv_I2c_SdaReadBit
 * 功能: 软件模拟I2C读SDA引脚值函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static t_pin_bit drv_I2c_SdaReadBit(t_i2c_software_source* i2c_software_source)
{
    return drv_Gpio_ReadInputDataBit(i2c_software_source->I2C_SDA);
}

/*******************************************************************************
 * 名称: drv_I2c_Software_DataInOut
 * 功能: 软件模拟I2C设置SDA引脚输入或输出模式函数
 * 形参: I2C结构体i2c_software_source
         InOut:输入或输出标志  ENABLE:输入  DISABLE:输出
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
static void drv_I2c_Software_DataInOut(t_i2c_software_source* i2c_software_source,FunctionalState InOut)
{
    if(InOut)
    {
        GPIO_Init(i2c_software_source->I2C_SDA->GPIO_Type,i2c_software_source->I2C_SDA->GPIO_Pin,GPIO_Mode_In_FL_No_IT);
    }
    else
    {
        GPIO_Init(i2c_software_source->I2C_SDA->GPIO_Type,i2c_software_source->I2C_SDA->GPIO_Pin,GPIO_Mode_Out_PP_Low_Slow);
    }
}

/*******************************************************************************
 * 名称: drv_I2c_Software_Init
 * 功能: 软件模拟I2C初始化函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
void drv_I2c_Software_Init(t_i2c_software_source* i2c_software_source)
{
    drv_Gpio_Init(i2c_software_source->I2C_SCL);
    drv_Gpio_Init(i2c_software_source->I2C_SDA);
    drv_I2c_SclHigh(i2c_software_source);
    drv_I2c_SdaHigh(i2c_software_source);
}

/*******************************************************************************
 * 名称: drv_I2c_Software_Start
 * 功能: 软件模拟I2C启动函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 标准的I2C协议I2C起始条件:SCL为高时,SDA由高变低
 ******************************************************************************/
void drv_I2c_Software_Start(t_i2c_software_source* i2c_software_source)
{
    drv_I2c_Software_DataInOut(i2c_software_source,DISABLE);    //将SDA设置为输出模式

    drv_I2c_SdaHigh(i2c_software_source);
    drv_I2c_SclHigh(i2c_software_source);
    drv_I2c_Delay(2);
    drv_I2c_SdaLow(i2c_software_source);
    drv_I2c_Delay(2);
    drv_I2c_SclLow(i2c_software_source);
}

/*******************************************************************************
 * 名称: drv_I2c_Software_Stop
 * 功能: 软件模拟I2C停止函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 标准的I2C协议I2C停止条件:SCL为高时,SDA由低变高
 ******************************************************************************/
void drv_I2c_Software_Stop(t_i2c_software_source* i2c_software_source)
{
    drv_I2c_Software_DataInOut(i2c_software_source,DISABLE);    //将SDA设置为输出模式

    drv_I2c_SclHigh(i2c_software_source);
    drv_I2c_SdaLow(i2c_software_source);
    drv_I2c_Delay(2);
    drv_I2c_SdaHigh(i2c_software_source);
    drv_I2c_Delay(2);
}

/*******************************************************************************
 * 名称: drv_I2c_Software_AckNak
 * 功能: 软件模拟I2C应答函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 无
 * 说明: 根据标准的I2C协议,从I2C从器件读1个byte后
         也就是在第9个CLK的时候,I2C主设备的SDA要变低
         表示I2C主器件已经接收完一个字节byte,I2C从器件
         继续发送数据
 ******************************************************************************/
void drv_I2c_Software_AckNak(t_i2c_software_source* i2c_software_source,t_I2c_Ack_status Ack_Status)
{
    drv_I2c_SclLow(i2c_software_source);
    drv_I2c_Software_DataInOut(i2c_software_source,DISABLE);   //将SDA设置为输出模式
    if(Ack_Status == I2C_ACK_YES)
    {
        drv_I2c_SdaLow(i2c_software_source);
        drv_I2c_Delay(2);
    }
    else
    {
        drv_I2c_SdaHigh(i2c_software_source);
        drv_I2c_Delay(2);
    }
    drv_I2c_SclHigh(i2c_software_source);
    drv_I2c_Delay(2);
    drv_I2c_SclLow(i2c_software_source);
    drv_I2c_Delay(2);
}

uint8_t drv_I2c_Software_WaitAck(t_i2c_software_source* i2c_software_source)
{
    uint8_t ucErrTime;
    drv_I2c_Software_DataInOut(i2c_software_source,ENABLE);     //将SDA设置为输入模式
    drv_I2c_SclHigh(i2c_software_source);
    drv_I2c_Delay(2);

    while(drv_I2c_SdaReadBit(i2c_software_source))
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            drv_I2c_Software_Stop(i2c_software_source);
            return 1;
        }
    }
    drv_I2c_SclLow(i2c_software_source);
    return 0;
}

/*******************************************************************************
 * 名称: drv_I2c_Software_SendByte
 * 功能: 软件模拟I2C发送一个Byte数据函数
 * 形参: I2C结构体i2c_software_source
         value:需要发送的数据
 * 返回: 发送状态   I2C_ERR:失败  FALSE:成功
 * 说明: 无
 ******************************************************************************/
void drv_I2c_Software_SendByte(t_i2c_software_source* i2c_software_source,uint8_t value)
{
    uint8_t count = 8;
    drv_I2c_Software_DataInOut(i2c_software_source,DISABLE);    //将SDA设置为输出模式
    drv_I2c_SclLow(i2c_software_source);
    while(count--)
    {
        if(value&0x80)
        {
            drv_I2c_SdaHigh(i2c_software_source);
        }
        else
        {
            drv_I2c_SdaLow(i2c_software_source);
        }
        value<<=1;
        drv_I2c_Delay(2);
        drv_I2c_SclHigh(i2c_software_source);                    //将SCL拉高
        drv_I2c_Delay(2);
        drv_I2c_SclLow(i2c_software_source);
        drv_I2c_Delay(2);
 }
}

/*******************************************************************************
 * 名称: drv_I2c_Software_RecvByte
 * 功能: 软件模拟I2C接收一个Byte数据函数
 * 形参: I2C结构体i2c_software_source
 * 返回: 接收到的数据
 * 说明: 无
 ******************************************************************************/
uint8_t drv_I2c_Software_ReadByte(t_i2c_software_source* i2c_software_source)
{
 uint8_t Data  = 0;
 uint8_t count = 8;

 drv_I2c_Software_DataInOut(i2c_software_source,ENABLE);     //将SDA设置为输入模式
 while(count--)
 {
        drv_I2c_SclLow(i2c_software_source);
        drv_I2c_Delay(2);
        drv_I2c_SclHigh(i2c_software_source);                  //将SCL拉高
  Data<<=1;
  if(drv_I2c_SdaReadBit(i2c_software_source))             //读SDA引脚值
  {
   Data|=1;
  }
        drv_I2c_Delay(2);
        drv_I2c_SclLow(i2c_software_source);                    //将SCL拉低
 }
 return Data;
}

#if 0

/*******************************************************************************
 * 名称: drv_I2c_Software_SendData
 * 功能: 软件模拟I2C发送多个数据函数
 * 形参: I2C结构体i2c_software_source
         Slave_Addr:从设备地址
         Dest_WriteAddr:目的地寄存器地址
         pdata:发送缓存区
         length:需要发送的数据的长度
 * 返回: 发送状态   I2C_ERR:失败  FALSE:成功
 * 说明: 无
 ******************************************************************************/


uint8_t drv_I2c_Software_SendData(t_i2c_software_source* i2c_software_source,uint16_t Dest_WriteAddr,uint8_t *pdata,uint8_t length)
{
    uint8_t AddressHigh,AddressLow,RegHigh,RegLow,i;

    AddressHigh = (i2c_software_source->Slave_Addr) >> 8;
    AddressLow  = i2c_software_source->Slave_Addr;
    RegHigh     = Dest_WriteAddr >> 8;
    RegLow      = Dest_WriteAddr;

    drv_I2c_Software_Start(i2c_software_source);
    if(AddressHigh)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,AddressHigh))
        {
            return FALSE;
        }
    }
    if(!drv_I2c_Software_SendByte(i2c_software_source,AddressLow))
    {
        return FALSE;
    }
    if(RegHigh)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,RegHigh))
        {
            return FALSE;
        }
    }
    if(!drv_I2c_Software_SendByte(i2c_software_source,RegLow))
    {
        return FALSE;
    }
    for(i = 0;i < length;i++)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,*(pdata+i)))
        return FALSE;
    }
    drv_I2c_Software_Stop(i2c_software_source);
    return TRUE;
}

/*******************************************************************************
 * 名称: drv_I2c_Software_SendData
 * 功能: 软件模拟I2C发送多个数据函数
 * 形参: I2C结构体i2c_software_source
         Slave_Addr:从设备地址
         Dest_WriteAddr:目的地寄存器地址
         pdata:发送缓存区
         length:需要发送的数据的长度
 * 返回: 发送状态   I2C_ERR:失败  FALSE:成功
 * 说明: 无
 ******************************************************************************/
bool drv_I2c_Software_RecvData(t_i2c_software_source* i2c_software_source,uint16_t Dest_WriteAddr,uint8_t *pdata,uint8_t length)
{
    uint8_t AddressHigh,AddressLow,RegHigh,RegLow,i;

    AddressHigh = (i2c_software_source->Slave_Addr) >> 8;
    AddressLow  = i2c_software_source->Slave_Addr;
    RegHigh     = Dest_WriteAddr >> 8;
    RegLow      = Dest_WriteAddr;

    drv_I2c_Software_Start(i2c_software_source);
    if(AddressHigh)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,AddressHigh))
        {
            return FALSE;
        }
    }
    if(!drv_I2c_Software_SendByte(i2c_software_source,AddressLow))
    {
        return FALSE;
    }
    if(RegHigh)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,RegHigh))
        {
            return FALSE;
        }
    }
    if(!drv_I2c_Software_SendByte(i2c_software_source,RegLow))
    {
        return FALSE;
    }

    drv_I2c_Software_Start(i2c_software_source);
    if(AddressHigh)
    {
        if(!drv_I2c_Software_SendByte(i2c_software_source,AddressHigh+1))
        {
            return FALSE;
        }
    }
    if(!drv_I2c_Software_SendByte(i2c_software_source,AddressLow+1))
    {
        return FALSE;
    }
    for(i=0;i     {
        *(pdata+i) = drv_I2c_Software_RecvByte(i2c_software_source);
    }

    drv_I2c_Software_Stop(i2c_software_source);
    return TRUE;
}


/*******************************************************************************
 * 名称: Soft_I2c_SendByte
 * 功能: stm8l软件模拟I2C发送函数
 * 形参: i2c_software_source:I2C资源结构体
         WriteRegAddr:需要发送的寄存器地址
         Data:写入的数据
 * 返回: 无
 * 说明: 无
 ******************************************************************************/
void Soft_I2c_SendByte(t_i2c_software_source* i2c_software_source,uint8_t WriteRegAddr,uint8_t Data)
{
    drv_I2c_Software_Start(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,i2c_software_source->Slave_Addr);
    drv_I2c_Software_AckNak(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,WriteRegAddr);
    drv_I2c_Software_AckNak(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,Data);
    drv_I2c_Software_AckNak(i2c_software_source);
    drv_I2c_Software_Stop(i2c_software_source);
}

/*******************************************************************************
 * 名称: Soft_I2c_ReadByte
 * 功能: stm8l软件模拟I2C读数据函数
 * 形参: i2c_software_source:I2C资源结构体
         ReadRegAddr:需要读取数据的寄存器地址
 * 返回: 读出的数据
 * 说明: 无
 ******************************************************************************/
uint8_t Soft_I2c_ReadByte(t_i2c_software_source* i2c_software_source,uint8_t ReadRegAddr)
{
    uint8_t Data;
    drv_I2c_Software_Start(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,i2c_software_source->Slave_Addr);
    drv_I2c_Software_AckNak(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,ReadRegAddr);
    drv_I2c_Software_AckNak(i2c_software_source);

    drv_I2c_Software_Start(i2c_software_source);
    drv_I2c_Software_SendByte(i2c_software_source,(i2c_software_source->Slave_Addr)|0x01);
    drv_I2c_Software_AckNak(i2c_software_source);
    Data = drv_I2c_Software_ReadByte(i2c_software_source);
    drv_I2c_Software_AckNak(i2c_software_source);
    drv_I2c_Software_Stop(i2c_software_source);
    return Data;
}
#endif

 

 

 

你可能感兴趣的:(I2C软件模拟驱动)