/****************************************************************************************
* 文 件 名: IIC.c
* 作 者:
* 开始日期: 2018-3-30
* 版本日志:
* 说 明:
*****************************************************************************************/
#include "IIC.h"
void (*IIC_[IIC_NUM][2])(unsigned char x) =
{
{ IIC_1_SCL, IIC_1_SDA },
{ IIC_2_SCL, IIC_2_SDA },
{ IIC_3_SCL, IIC_3_SDA },
{ IIC_4_SCL, IIC_4_SDA },
{ IIC_5_SCL, IIC_5_SDA },
{ IIC_6_SCL, IIC_6_SDA },
{ IIC_7_SCL, IIC_7_SDA },
{ IIC_8_SCL, IIC_8_SDA },
{ IIC_9_SCL, IIC_9_SDA },
{ IIC_10_SCL, IIC_10_SDA},
{ IIC_11_SCL, IIC_11_SDA}
};
void (*IIC_SDA_[IIC_NUM][2])(void) =
{
{ IIC_1_SDA_IN, IIC_1_SDA_OUT },
{ IIC_2_SDA_IN, IIC_2_SDA_OUT },
{ IIC_3_SDA_IN, IIC_3_SDA_OUT },
{ IIC_4_SDA_IN, IIC_4_SDA_OUT },
{ IIC_5_SDA_IN, IIC_5_SDA_OUT },
{ IIC_6_SDA_IN, IIC_6_SDA_OUT },
{ IIC_7_SDA_IN, IIC_7_SDA_OUT },
{ IIC_8_SDA_IN, IIC_8_SDA_OUT },
{ IIC_9_SDA_IN, IIC_9_SDA_OUT },
{ IIC_10_SDA_IN, IIC_10_SDA_OUT},
{ IIC_11_SDA_IN, IIC_11_SDA_OUT}
};
unsigned char (*IIC_READ_SDA[IIC_NUM])(void) =
{
IIC_1_READ_SDA,
IIC_2_READ_SDA,
IIC_3_READ_SDA,
IIC_4_READ_SDA,
IIC_5_READ_SDA,
IIC_6_READ_SDA,
IIC_7_READ_SDA,
IIC_8_READ_SDA,
IIC_9_READ_SDA,
IIC_10_READ_SDA,
IIC_11_READ_SDA
};
#define IIC_(ch,who,value) (*IIC_[ch][who])(value) //ch is IIC channel, who is SDA or SCL, value can be 0 or 1
#define IIC_SDA_(ch,mode) (*IIC_SDA_[ch][mode])() //ch is IIC channel, mode is IN or OUT
#define IIC_READ_SDA(ch) (*IIC_READ_SDA[ch])() //ch is IIC channel,
#define TIME1 20
#define TIME2 20
void IIC_delay(unsigned char delay)
{
while(delay--);
}
/* **************************************************************************************
* 函 数 名: IIC_START
* 功能说明: 起始信号
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
void IIC_START(IIC_Channel Channel)
{
(*IIC_SDA_[Channel][OUT])(); //SDA OUTPUT
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(1); //SDA = 1
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(0); //SDA = 0
IIC_delay(TIME1);
//钳住IIC总线,准备接受数据或者发送数据
(*IIC_[Channel][SCL])(0); //SCL = 0
IIC_delay(TIME1);
}
/* **************************************************************************************
* 函 数 名: IIC_STOP
* 功能说明: 停止信号
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
void IIC_STOP(IIC_Channel Channel)
{
(*IIC_SDA_[Channel][OUT])(); //SDA OUTPUT
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(0); //SDA = 0
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(1); //SDA = 1
IIC_delay(TIME1);
}
/* **************************************************************************************
* 函 数 名: IIC_WaitAck
* 功能说明: 等待应答信号
* 形 参: Channel,对应IIC通道
* 返 回 值: 1:表示没应答
0: 表示有应答
* 备 注: 无
*****************************************************************************************/
unsigned char IIC_WaitAck(IIC_Channel Channel)
{
unsigned int wait_time = 500;
unsigned char read_sda;
(*IIC_[Channel][SDA])(1); //SDA = 1
(*IIC_SDA_[Channel][IN])(); //SDA INPUT
IIC_delay(TIME1);
while(wait_time--)
{
read_sda = (*IIC_READ_SDA[Channel])(); //READ SDA
if(!read_sda)break;
}
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME1);
(*IIC_[Channel][SCL])(0); //SCL = 0
return read_sda;
}
/* **************************************************************************************
* 函 数 名: IIC_Ack
* 功能说明: IIC应答信号
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
void IIC_Ack(IIC_Channel Channel)
{
(*IIC_SDA_[Channel][OUT])(); //SDA OUTPUT
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(0); //SDA = 0
IIC_delay(TIME1);
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME1);
(*IIC_[Channel][SCL])(0); //SCL = 0
IIC_delay(TIME1);
}
/* **************************************************************************************
* 函 数 名: IIC_NAck
* 功能说明: 不应答
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
void IIC_NAck(IIC_Channel Channel)
{
(*IIC_SDA_[Channel][OUT])(); //SDA OUTPUT
IIC_delay(TIME1);
(*IIC_[Channel][SDA])(1); //SDA = 1
IIC_delay(TIME1);
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME1);
(*IIC_[Channel][SCL])(0); //SCL = 0
IIC_delay(TIME1);
}
/* **************************************************************************************
* 函 数 名: IIC_ChackDevice
* 功能说明: 检测设备的存在
* 形 参: Channel,对应IIC通道
* 返 回 值: 0:为有
1:为无
* 备 注: 无
*****************************************************************************************/
unsigned char IIC_ChackDevice(IIC_Channel Channel)
{
unsigned char uAck;
IIC_START(Channel);
IIC_SendByte(Channel,IIC_DEV_ADDR | IIC_WR);//发送从设备的地址(7位),检测设备是否存在
uAck = IIC_WaitAck(Channel);
IIC_STOP(Channel);
return uAck;
}
/* **************************************************************************************
* 函 数 名: IIC_SendByte
* 功能说明: 发送8位一字节数据给IIC总线
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
void IIC_SendByte(IIC_Channel Channel,unsigned char Byte)
{
unsigned char bit_index;
(*IIC_SDA_[Channel][OUT])(); //SDA OUTPUT
IIC_delay(TIME1);
for(bit_index=0;bit_index<8;bit_index++)
{
if(Byte & 0x80) (*IIC_[Channel][SDA])(1); //SDA = 1
else (*IIC_[Channel][SDA])(0); //SDA = 0
Byte <<= 1;
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME2);
(*IIC_[Channel][SCL])(0); //SCL = 0
IIC_delay(TIME2);
}
}
/* **************************************************************************************
* 函 数 名: IIC_ReadByte
* 功能说明: 读取IIC总线上的数据8位一字节
* 形 参: Channel,对应IIC通道
* 返 回 值: 无
* 备 注: 无
*****************************************************************************************/
unsigned char IIC_ReadByte(IIC_Channel Channel)
{
unsigned char bit_index;
unsigned char read_data;
(*IIC_[Channel][SDA])(1); //SDA = 1
(*IIC_SDA_[Channel][IN])(); //SDA INPUT
IIC_delay(TIME1);
read_data=0;
for(bit_index=0;bit_index<8;bit_index++)
{
read_data <<= 1;
if( (*IIC_READ_SDA[Channel])() ) read_data++;
(*IIC_[Channel][SCL])(1); //SCL = 1
IIC_delay(TIME2);
(*IIC_[Channel][SCL])(0); //SCL = 0
IIC_delay(TIME2);
}
return read_data;
}
/* ********************************************************************************************************
* 函 数 名: IIC_ReadBytes
* 功能说明: 从串行EEPROM指定地址处开始读取若干数据
* 形 参: Channel,对应IIC通道
ReadAddr: 读地址
* *ReadData: 地址内容
* 返 回 值: 0 表示失败,1表示成功
* 备 注: 无
********************************************************************************************************* */
unsigned char IIC_ReadBytes(IIC_Channel Channel,unsigned short ReadAddr,unsigned char *ReadData)
{
/* 第1步:发起I2C总线启动信号 */
IIC_START(Channel);
/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */
IIC_SendByte(Channel,IIC_DEV_ADDR | IIC_WR); /* 此处是写指令 */
/* 第3步:发送ACK */
if (IIC_WaitAck(Channel) == 1)goto cm