/*******************************************************************************
* 文件名 :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