/*
 * TWI.h
 *
 * Created: 2015/10/30 14:48:59
 *  Author: Administrator
 */ 
/*******************************************************************
********************************************************************
**注意事项:在使用硬件查询方式和软件模拟方式进行IIC通信,每次读写数据之间***
**必须延时5ms,否者数据读操作会失败;硬件中断方式读写之间不需要延时时间;*****
********************************************************************
********************************************************************/

#ifndef TWI_H_
#define TWI_H_
#include "config.h"

硬件中断模式;
//#define TWI_IIC_MODE 0
硬件查询模式;
//#define TWI_IIC_MODE 1
//软件模拟方式;
#define TWI_IIC_MODE 2

#define TWI_START 0x08
#define TWI_REP_START 0x10
#define TWI_ARB_LOST 0x38

/*************************************************************
****************主机发送***************************************
**************************************************************/
#define TWI_MT_SLA_W_ACK 0x18
#define TWI_MT_SLA_W_NACK 0x20
#define TWI_MT_DATA_ACK 0x28
#define TWI_MT_DATA_NACK 0x30

/*************************************************************
****************主机接收***************************************
**************************************************************/
#define TWI_MR_SLA_R_ACK             0x40
#define TWI_MR_SLA_R_NACK           0x48
#define TWI_MR_DATA_ACK           0x50
#define TWI_MR_DATA_NACK             0x58

#define TWI_NO_INFO 0xF8
#define TWI_BUS_ERROR 0x00

#define TWI_TWCR_STATE (TWCR&0x0F)
#define TWI_NO_STATUS         0xF8

//数据缓存空间的大小;
#define TWI_BUFFER_SIZE 64

//数据返回;
#define TWI_OK 0x00
#define TWI_ERROR_NODEV                 0x01

//使能TWI中断;
#define Enable_Interrupt_TWI() TWCR|=(1<<TWIE)
//不使能TWI中断;
#define Disable_Interrupt_TWI() TWCR&=~(1<<TWIE)
//清零TWINT、清零start状态、使能TWI.发出START 信号;
#define TWI_Start() (TWCR=TWI_TWCR_STATE|(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
//发送停止条件;
#define TWI_Stop() (TWCR=TWI_TWCR_STATE|(1<<TWINT)|(1<<TWEA)|(1<<TWSTO))
//等待TWI 总线操作完成;
#define TWI_Wait() {while (!(TWCR & (1<<TWINT)));}
//启动发送;
#define TWI_Enable_Send() TWCR=(TWI_TWCR_STATE|(1<<TWINT))
#define TWI_Enable_Rev() TWSR=(1<<TWINT)|(TWEA)
//接受应答回复;
#define TWI_ReceACK() TWCR=(TWI_TWCR_STATE|(1<<TWINT)|(1<<TWEA)|(1<<TWEN))
#define TWI_ReceNACK() TWCR=(TWI_TWCR_STATE|(1<<TWINT)|(1<<TWEN))

//总线状态;
#define TWI_STATUS (TWSR&TWI_NO_STATUS)

void TWI_Init(void);
U8 TWI_BitRate(U16 BitRateKHZ);
U8 TWI_GetReceByte(void);
void TWI_SendByte(U8 SendByte);
void TWI_RecByteAck(U8 AckFlag);
void TWI_WriteToDevice(U8 DeviceAddr,U8 length,U8 *pData);
void Fill_Data(U8 length,U8 *pData);
void TWI_StartTransmition(void);
void TWI_ReadFromDevice(U8 DeviceAddr,U8 length);
/******************************中断方式***********************/

/*******************************查询方式
 ***********************/
U8 TWI_IIC_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
U8 TWI_IIC_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength);
U8 TWI_IIC_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
U8 TWI_IIC_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr,U8 *pData,U8 DataLength);
U8  TWI_ReciveDATA_NACK(U8 *pdata);
U8  TWI_ReciveDATA_ACK(U8 *pdata);
/********************************************************************************
*************通过I/O口模拟IIC时序************************************************
********************************************************************************/

//SDA--PC4   SCL--PC5

//IIC管脚定义;
#define SDA_Pin PC4
#define SCL_Pin PC5

#define SDA_OUT DDRC|=(1<<SDA_Pin)
#define SDA_IN DDRC&=~(1<<SDA_Pin)

#define SDA_LOW PORTC&=~(1<<SDA_Pin);_delay_us(IIC_DELAY_TIME)
#define SDA_HIGH PORTC|=(1<<SDA_Pin);_delay_us(IIC_DELAY_TIME)
#define SDA_Read PINC&=(1<<SDA_Pin)

#define SCL_OUT DDRC|=(1<<SCL_Pin)
#define SCL_IN DDRC&=~(1<<SCL_Pin)

#define SCL_LOW PORTC&=~(1<<SCL_Pin);_delay_us(IIC_DELAY_TIME)
#define SCL_HIGH PORTC|=(1<<SCL_Pin);_delay_us(IIC_DELAY_TIME)
#define SCL_Read PINC&=(1<<SCL_Pin)

#define IIC_CLOCK_FREQUENT 100

#if ((IIC_CLOCK_FREQUENT>400)||(IIC_CLOCK_FREQUENT==0))
#error "IIC_CLOCK_FREQUENT overflow!!!"
#elif (IIC_CLOCK_FREQUENT>250)
#define IIC_DELAY_TIME 2
#else
#define IIC_DELAY_TIME (500/IIC_CLOCK_FREQUENT)
#endif

void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(U8 Wdata);
U8 IIC_ReadAck(void);
void IIC_Send_ACK_Or_NACK(U8 ACK_Or_NACK);
U8 IIC_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
U8 IIC_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr,U8 *pData,U8 DataLength);
U8 IIC_ReceiveByte(void);
U8 IIC_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
U8 IIC_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr, U8 *pData,U8 DataLength);

/******************************模拟方式***********************/
void IIC_TWI_Init(void);
void IIC_TWI_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
void IIC_TWI_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength);
void IIC_TWI_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength);
void IIC_TWI_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength);

#endif /* TWI_H_ */

/*
 * TWI.c
 *
 * Created: 2015/10/30 14:48:50
 *  Author: Administrator
 */ 
#include "TWI.h"
/**************************************
**********发送缓存区*******************
***************************************/
U8 TWI_SendData[TWI_BUFFER_SIZE];
//发送完成标志位;
U8 TWI_Write_Finish=0;

/**************************************
**********发送缓存区*******************
**************************************/
U8 TWI_ReceData[TWI_BUFFER_SIZE];
//读取完成标志位;
U8 TWI_Read_Finish=0;

//定义传输数据长度;
U8 TWI_DataLength=0;
U8 TWI_Index=0;
//定义IIC设备的地址;
U8 IIC_DeviceAddr=0;

/***************************************
**********功 能: TWI初始化***********
**********输入参数: 无 ***********
**********返回 值: 无 ***********
****************************************/
void TWI_Init(void)
{
//设置设备的IIC接口的上拉使能;
PORTC=0xff;
//设备IIC的时钟频率;
TWBR=TWI_BitRate(100);
//释放SDA总线;
TWDR=0xff;
}
/***************************************
**********功 能: TWI时钟设置 ********
**********输入参数: 设置速率 ********
**********返回 值: TWBR的值   ********
****************************************/
U8 TWI_BitRate(U16 BitRateKHZ)
{
if ((F_CPU/1000)<(BitRateKHZ*36))
{
return 10;

else
{
return (U8)((((F_CPU/1000)/BitRateKHZ)-16)/2);
}
}
/***************************************
**********功 能: 接受的数据  ******
**********输入参数: 无  ******
**********返回 值: TWDR中的数据  ******
****************************************/
U8 TWI_GetReceByte(void)
{
return (TWDR);
}

/****************************************
**********功 能: 单字节发送数据 ******
**********输入参数: 发送的数据   ******
**********返回 值: 无   ******
****************************************/
void TWI_SendByte(U8 SendByte)
{
TWDR=SendByte;
TWI_Enable_Send();
}
/****************************************
**********功 能: 接收后是否应答  ******
**********输入参数: 1 应答;0 不应答 ****
**********返回 值: 无   ******
****************************************/
void TWI_RecByteAck(U8 AckFlag)
{
if (AckFlag)
{
//Ack=true,接受数据完成应答回复;
TWI_ReceACK();
}
else
{
//接收完成后不应答;
TWI_ReceNACK();
}
}
/*****************************************************************************
**********功 能: 主机中断模式发送数据 **************************************
**********输入参数: DeviceAddr 器件地址;length 数据长度 ;*pData 发送数据 ****
**********返回 值: 无 **************************************
*******************************************************************************/
void TWI_WriteToDevice(U8 DeviceAddr,U8 length,U8 *pData)
{
//关闭中断;
Disable_Interrupt_TWI();
TWI_DataLength=length;
//数据填充缓存空间;
Fill_Data(length,pData);
//设备写地址;
IIC_DeviceAddr=(DeviceAddr&0xFE);
//启动传输;
TWI_StartTransmition();
//等待写操作完成;
while(!TWI_Write_Finish)
wdt_reset();
//清楚写操作标志;
TWI_Write_Finish=0;
//发送停止条件;
TWI_Stop();
//关闭中断;
Disable_Interrupt_TWI();
}
/****************************************************
**********功 能: 将发送的数据填充缓存空间 *********
**********输入参数: length 数据长度;*pData 数据 ****
**********返回 值: 无   ******************
******************************************************/
void Fill_Data(U8 length,U8 *pData)
{
for (U8 i=0;i<length;i++)
{
TWI_SendData[i]=*(pData+i);
}
}
/****************************************************
**********功 能: 启动数据传输   ******************
**********输入参数: 无   ******************
**********返回 值: 无   ******************
******************************************************/
void TWI_StartTransmition(void)
{
//启动数据传输;
TWI_Start();
//使能TWI中断;
Enable_Interrupt_TWI();
}
/*****************************************************************************
**********功 能: 主机中断模式读取数据 **************************************
**********输入参数: DeviceAddr 器件地址;length 数据长度 *********************
**********返回 值: 无 **************************************
*******************************************************************************/
void TWI_ReadFromDevice(U8 DeviceAddr,U8 length)
{
Disable_Interrupt_TWI();
//要读取的数据的长度;
TWI_DataLength=length;
//读数据地址;
IIC_DeviceAddr=(DeviceAddr|0x01);
//启动传输;
TWI_StartTransmition();
//等待读取完成;
while(!TWI_Read_Finish);
//清除IIC读标志位;
TWI_Read_Finish=0;
//发送停止条件;
TWI_Stop();
//关闭TWI中断;
Disable_Interrupt_TWI();
}

/***********************************************************************
**************中断函数**************************************************
************************************************************************/
#ifdef __GNUC__
SIGNAL(TWI_vect)
#else
#pragma vector=TWI_vect
__interrupt void TWI_ISR(void)
#endif
{
switch (TWI_STATUS)
{
// 主机START信号传输完成;
case TWI_START:
// 主机重新开始信号传输完成;
case TWI_REP_START:
//发送IIC器件地址;
TWI_SendByte(IIC_DeviceAddr);
break;
// 使能TWI总线, 使能TWI中断, 发送RESTART信号;
case TWI_ARB_LOST:
//启动TWI;
TWI_Start();
break;
  /************************************************
  *****主机发送模式,发送数据*************************
  *************************************************/
  // 主机发送-->从机地址及读写标志传输完成并收到ACK信号;
  case TWI_MT_SLA_W_ACK:
  // 主机发送-->数据传输完成并收到ACK信号;
  case TWI_MT_DATA_ACK:
if (TWI_Index<TWI_DataLength)
{
//发送数据;
TWI_SendByte(TWI_SendData[TWI_Index]);
//加载下一个数据;
TWI_Index++;

else
{
//清楚数组指向,为接受准备;
TWI_Index=0;
TWI_Write_Finish=1;
}
break;
  /************************************************
  *****主机接收模式,接收数据*************************
  *************************************************/
  // 主机接收模式下-->发送完成SLA+R 并收到ACK信号;
  case TWI_MR_SLA_R_ACK:
if (TWI_Index<(TWI_DataLength-1))
{
//接收到数据后应答;
TWI_RecByteAck(1);

else
{
//接收到数据后不应答;
TWI_RecByteAck(0);
}
break;
// 主机接收模式下-->收到一个字节数据并发送完ACK信号;
case TWI_MR_DATA_ACK:
TWI_ReceData[TWI_Index]=TWI_GetReceByte();
TWI_Index++;
break;
// 主机接收模式下收到数据,发送了NACK信号;
case TWI_MR_DATA_NACK:
//存储最后一组数据;
TWI_ReceData[TWI_Index]=TWI_GetReceByte();
//清楚数组指向,为下一组数据准备;
TWI_Index=0;
//接收完成标志;
TWI_Read_Finish=1;
//停止通信;
TWI_Stop();
break;
/************************************************
  *****主机接收和发送模式,其他错误状态*************************
  *************************************************/
// 主机发送模式发送从机地址后无应答;
case TWI_MR_SLA_R_NACK:
// 主机发送模式下数据传输完成无应答;
case TWI_MT_DATA_NACK:
// 主机接收模式发送从机地址后无应答;
case TWI_MT_SLA_W_NACK:
//释放总线;
TWI_Stop();
break;

// 总线错误;
case TWI_BUS_ERROR:
TWI_Stop();
break;
default:
TWCR = (1<<TWEN)|                          // 使能TWI总线,释放TWI端口;
(0<<TWIE)|(0<<TWINT)|                      // 禁止中断;
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           //
(0<<TWWC); //

}
}

/******************************中断方式***********************/

/********************************************************************************
***********************查询方式*************************************************
*********************************************************************************/

/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******
**********返回 值: 0 写入失败,1 写入成功  **********************************
*******************************************************************************/
U8 TWI_IIC_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
TWI_Start();
TWI_Wait();
if (TWI_STATUS!=TWI_START)
{
TWI_Stop();
return 0;
}
//发送器件地址;
TWI_SendByte(DeviceAddr&0xFE);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_SLA_W_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}
//发送数据;
for (i=0;i<DataLength;i++)
{
TWI_SendByte(*pData);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_DATA_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}
pData++;
}
TWI_Stop();
return 1;
}
/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据存储的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 0 写入失败,1 写入成功  **********************************
*******************************************************************************/
U8 TWI_IIC_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength)
{
U8 i=0;
TWI_Start();
TWI_Wait();
if (TWI_STATUS!=TWI_START)
{
TWI_Stop();
return 0;
}
//发送器件地址;
TWI_SendByte(DeviceAddr&0xFE);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_SLA_W_ACK)
{
TWI_Stop();
return 0;
}
//发送数据地址;
TWI_SendByte(DataAddr);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_DATA_ACK)
{
TWI_Stop();
return 0;
}
//发送数据;
for (i=0;i<DataLength;i++)
{
TWI_SendByte(*pData);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_DATA_ACK)
{
TWI_Stop();
return 0;
}
pData++;
}
TWI_Stop();
return 1;
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******
**********返回 值: 0 读出失败,1 读出成功  **********************************
*******************************************************************************/
U8 TWI_IIC_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
//U8 ACK_NACK=0;
TWI_Start();
TWI_Wait();
if (TWI_STATUS!=TWI_START)
{
TWI_Stop();
return 0;
}
//发送器件地址;
TWI_SendByte(DeviceAddr|0x01);
TWI_Wait();
if (TWI_STATUS!=TWI_MR_SLA_R_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}
for (i=0;i<DataLength-1;i++)
{
if (TWI_ReciveDATA_ACK(pData+i)==0)
{
return 0;
}
}
//读取数据时,最后1字节的数据读取完成以后发送NAK而不是ACK
if(TWI_ReciveDATA_NACK(pData+i)==0)
{
return 0;
}
TWI_Stop();
return 1;
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据读出的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 0 读出失败,1 读出成功  **********************************
*******************************************************************************/
U8 TWI_IIC_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
//U8 ACK_NACK=0;
TWI_Start();
TWI_Wait();
if (TWI_STATUS!=TWI_START)
{
TWI_Stop();
return 0;
}
//发送器件地址;
TWI_SendByte(DeviceAddr&0xFE);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_SLA_W_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}
//发送数据地址;
TWI_SendByte(DataAddr);
TWI_Wait();
if (TWI_STATUS!=TWI_MT_DATA_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}
TWI_Start();
TWI_Wait();
if ((TWI_STATUS!=TWI_START)&&(TWI_STATUS!=TWI_REP_START))
{
TWI_Stop();
return 0;
}
TWI_SendByte(DeviceAddr|0x01);
TWI_Wait();
if (TWI_STATUS!=TWI_MR_SLA_R_ACK)
{
//没有应答结束通信;
TWI_Stop();
return 0;
}

for (i=0;i<DataLength-1;i++)
{
if (TWI_ReciveDATA_ACK(pData+i)==0)
{
return 0;
}
}
//读取数据时,最后1字节的数据读取完成以后发送NAK而不是ACK
if(TWI_ReciveDATA_NACK(pData+i)==0)
{
return 0;
}
TWI_Stop();
return 1;
}
/*********************************************************************************
*****功能:接收数据,不发应答信号***************************************************
*****输入参数:存储接收到的数据buffer***********************************************
****输出参数:0:接收失败;1接收成功************************************************
*********************************************************************************/
U8  TWI_ReciveDATA_NACK(U8 *pdata)
{
TWI_ReceNACK();
TWI_Wait();
if (TWI_STATUS!=TWI_MR_DATA_NACK)
{
return 0;
}
*pdata=TWI_GetReceByte();
return 1;
}
/******************************************************************************
*****功能:接收数据,发应答信号***************************************************
*****输入参数:存储接收到的数据buffer*********************************************
****输出参数:0:接收失败;1接收成功***********************************************
*******************************************************************************/
U8  TWI_ReciveDATA_ACK(U8 *pdata)
{
TWI_ReceACK();
TWI_Wait();
if (TWI_STATUS!=TWI_MR_DATA_ACK)
{
return 0;
}
*pdata=TWI_GetReceByte();
return 1;
}
/********************************************************************************
***********************模拟IIC SDA--PC4   SCL--PC5********************************
*********************************************************************************/
/************注意:模拟IIC读和写数据之间必须有5ms的延时时****************************/

/*****************************************************************************
**********功 能: 模拟IIC初始化 ********************************************
**********输入参数:  无  ********************************************
**********返回 值: 无  ********************************************
*******************************************************************************/
void IIC_Init(void)
{
//设置为输出模式;
SDA_OUT;
SCL_OUT;
//设置输出为高;
SDA_HIGH;
SCL_HIGH;
}

/*****************************************************************************
**********功 能: 模拟IIC启动  ********************************************
**********输入参数:  无  ********************************************
**********返回 值: 无  ********************************************
*******************************************************************************/
void IIC_Start(void)
{
//设置为输出模式;
SDA_OUT;
SCL_OUT;
//钳住I2C总线,避免Start和Stop信号;
SCL_LOW;
//发送起始条件的数据信号;
SDA_HIGH;
SCL_HIGH;
//发送起始信号;
SDA_LOW;
//钳住I2C总线,准备发送或接收数据
SCL_LOW;

}
/*****************************************************************************
**********功 能: 模拟IIC停止  ********************************************
**********输入参数:  无  ********************************************
**********返回 值: 无  ********************************************
*******************************************************************************/
void IIC_Stop(void)
{
//设置为输出模式;
SDA_OUT;
SCL_OUT;
//钳住I2C总线,避免Start和Stop信号;
SCL_LOW;
//发送结束条件的数据信号;
SDA_LOW;
SCL_HIGH;
SDA_HIGH;
}
/*****************************************************************************
**********功 能: 读取应答信号  ********************************************
**********输入参数:  无         ****************************************
**********返回 值: SDA_Read 1不应答,SDA_Read 0应答 **********************************
*******************************************************************************/
U8 IIC_ReadAck(void)
{
U8 ACK_NACK = 0;
U8 i=0;
SCL_OUT;
SCL_LOW;
//设置SDA为输入;
SDA_IN;
SCL_HIGH;
for (i=255;i>0;i--)
{
if (SDA_Read)
{
ACK_NACK=1;
SCL_LOW;
return ACK_NACK;
}
}
SCL_LOW;
return ACK_NACK=0;
}

/*****************************************************************************
**********功 能: 发送数据  ********************************************
**********输入参数: 要发送的数据  ****************************************
**********返回 值: 无  **********************************
*******************************************************************************/
void IIC_SendByte(U8 Wdata)
{
U8 Bitcnt=0;
SDA_OUT;
SCL_OUT;
for (Bitcnt=0;Bitcnt<8;Bitcnt++)
{
SCL_LOW;
if (Wdata&0x80)
{
SDA_HIGH;
}
else
{
SDA_LOW;
}
Wdata<<=1;
SCL_HIGH;
}
}
/*****************************************************************************
**********功 能: 发送应答    *******************************************
**********输入参数: 1不应答,0应答 ********************************************
**********返回 值: 无 ******************************************
*******************************************************************************/
void IIC_Send_ACK_Or_NACK(U8 ACK_Or_NACK)
{
SDA_OUT;
SCL_OUT;
SCL_LOW;
if (ACK_Or_NACK)
{
//无应答信号;
SDA_HIGH;

else
{
//应答信号;
SDA_LOW;
}
SCL_HIGH;
SCL_LOW;
}

/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******  
**********返回 值: 0 写入失败,1 写入成功  **********************************
*******************************************************************************/
U8 IIC_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
IIC_Start();
IIC_SendByte(DeviceAddr&0xFE);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
for (i=0;i<DataLength;i++)
{
//发送数据;
IIC_SendByte(*pData);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
pData++;
}
IIC_Stop();
return 1;
}

/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据存储的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 0 写入失败,1 写入成功  **********************************
*******************************************************************************/
U8 IIC_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
//启动总线;
IIC_Start();
//发送器件地址;
IIC_SendByte(DeviceAddr);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
//发送数据地址;
IIC_SendByte(DataAddr);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
for (i=0;i<DataLength;i++)
{
//发送数据;
IIC_SendByte(*pData);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
pData++;
}
IIC_Stop();
return 1;
}
/*****************************************************************************
**********功 能: 接收数据函数 ******************************************
**********输入参数: 无 ******************************************
**********返回 值: 接收到的数据 ******************************************
*******************************************************************************/
U8 IIC_ReceiveByte(void)
{
U8 Bitcnt=0;
U8 RevData=0;
SCL_OUT;
//将SDA设置为输入;
SDA_IN;
//SDA_LOW;
for (Bitcnt=0;Bitcnt<8;Bitcnt++)
{
//置时钟线为低,准备接收数据位;
SCL_LOW;
//上拉使;
SDA_HIGH;
//置时钟线为高使数据线上数据有效;
SCL_HIGH;
RevData=RevData<<1;
if (SDA_Read)
{
RevData+=1;

else
{
RevData+=0;
}
}
return RevData;
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******
**********返回 值: 0 读出失败,1 读出成功  **********************************
*******************************************************************************/
U8 IIC_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
U8 i=0;
U8 ACK_NACK=1;
IIC_Start();
IIC_SendByte(DeviceAddr|0x01);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}
for (i=0;i<DataLength;i++)
{
//接收的数据;
*pData=IIC_ReceiveByte();
if (i==(DataLength-1))
{
ACK_NACK=1;

else
{
pData++;
ACK_NACK=0;
}
//发送应答或不应答信号;
IIC_Send_ACK_Or_NACK(ACK_NACK);
}
IIC_Stop();
return 1;
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据读出的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 0 读出失败,1 读出成功  **********************************
*******************************************************************************/
U8 IIC_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr, U8 *pData,U8 DataLength)
{
U8 i=0;
U8 ACK_NACK=1;
IIC_Start();
IIC_SendByte(DeviceAddr&0xFE);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}

IIC_SendByte(DataAddr);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}

IIC_Start();
IIC_SendByte(DeviceAddr|0x01);
if (IIC_ReadAck())
{
//没有应答,结束通信;
IIC_Stop();
return 0;
}

for (i=0;i<DataLength;i++)
{
//接收的数据;
*pData=IIC_ReceiveByte();
if (i==(DataLength-1))
{
ACK_NACK=1;
}
else
{
pData++;
ACK_NACK=0;
}
//发送应答h或不应答信号;
IIC_Send_ACK_Or_NACK(ACK_NACK);
}
IIC_Stop();
return 1;
}

/******************************模拟方式***********************/

/*****************************************************************************
**********功 能: 硬件还是软件模拟的IIC通信的初始化 ***************************
**********输入参数:  无  ********************************************
**********返回 值: 无  ********************************************
*******************************************************************************/
void IIC_TWI_Init(void)
{
if (TWI_IIC_MODE==0)
{
Enable_interrupt();
TWI_Init();

else if (TWI_IIC_MODE==1)
{
TWI_Init();
}
else
{
IIC_Init();
}
}
/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******
**********返回 值: 无                     **********************************
*******************************************************************************/
void IIC_TWI_WriteToDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
if (TWI_IIC_MODE==0)
{
TWI_WriteToDevice(DeviceAddr,DataLength,pData);
}
else if (TWI_IIC_MODE==1)
{
TWI_IIC_WriteToDevice(DeviceAddr,pData,DataLength);
}
else
{
IIC_WriteToDevice(DeviceAddr,pData,DataLength);
}
}
/*****************************************************************************
**********功 能: 向设备写入数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据存储的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 无                     **********************************
*******************************************************************************/
void IIC_TWI_WriteToDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength)
{
if (TWI_IIC_MODE==0)
{
//TWI_WriteToDevice(DeviceAddr,DataLength,*pData);
}
else if (TWI_IIC_MODE==1)
{
TWI_IIC_ReadFromDeviceByAddr(DeviceAddr,DataAddr,pData,DataLength);
}
else
{
IIC_WriteToDeviceByAddr(DeviceAddr,DataAddr,pData,DataLength);
}
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,pdata 数据,DataLength 数据长度 ******
**********返回 值: 无                     **********************************
*******************************************************************************/
void IIC_TWI_ReadFromDevice(U8 DeviceAddr,U8 *pData,U8 DataLength)
{
if (TWI_IIC_MODE==0)
{
TWI_ReadFromDevice(DeviceAddr,DataLength);
}
else if (TWI_IIC_MODE==1)
{
TWI_IIC_ReadFromDevice(DeviceAddr,pData,DataLength);
}
else
{
IIC_ReadFromDevice(DeviceAddr,pData,DataLength);
}
}
/*****************************************************************************
**********功 能: 从设备读出数据  ****************************************
**********输入参数: DeviceAddr 设备地址,DataAddr 数据读出的地址 **************
******************   pdata 数据,DataLength 数据长度  *************************
**********返回 值: 无                     **********************************
*******************************************************************************/
void IIC_TWI_ReadFromDeviceByAddr(U8 DeviceAddr,U8 DataAddr ,U8 *pData,U8 DataLength)
{
if (TWI_IIC_MODE==0)
{
//TWI_ReadFromDevice(DeviceAddr,DataLength);
}
else if (TWI_IIC_MODE==1)
{
TWI_IIC_ReadFromDeviceByAddr(DeviceAddr,DataAddr,pData,DataLength);
}
else
{
IIC_ReadFromDeviceByAddr(DeviceAddr,DataAddr,pData,DataLength);
}
}

Atmega的TWI通信,包含模拟IIC,硬件查询方式,以及硬件方式收发程序相关推荐

  1. 模拟IIC与硬件IIC的区别!

    模拟IIC与硬件IIC的区别! 一:模拟IIC与硬件IIC定义? 模拟I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形. 硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所 ...

  2. 中微SC8F5771模拟IIC通信——指令运行速度的探索(附编译软件与烧录软件)

    文章目录 一.中微单片机烧录与使用 编译软件 烧录软件 下载地址 烧录软件 二.模拟IIC 三.逻辑分析仪下的时序 一.中微单片机烧录与使用 编译软件 中微所使用编译软件为SCMCU_IDE,不过个人 ...

  3. STC12C5A60S2使用模拟IIC通信与AT24C02芯片编程

    文章目录 一.前言 二.IIC通讯详解 2-1.IC协议简介 2-2.常用的IIC通讯设备 2-3.IIC物理层特点 2-4.IIC协议层特点 2-4-1.IIC基本读写过程 2-4-2.通讯起始和停 ...

  4. MSP430杂谈--AD7745硬件IIC驱动与模拟IIC驱动

    和上一篇AD7793类似,项目中也涉及到利用AD7745读取电容值,来测环境湿度.编写了基于MSP430的AD7745的硬件IIC驱动和模拟IIC驱动,分享给大家. AD7745硬件IIC驱动完整版下 ...

  5. 51单片机(IO模拟IIC通信)

    单片机作为主机 sbit SDA = P1^0; sbit SCL = P1^1; IIC数据操作:在iic总线上,数据伴随时钟脉冲,一位一位的传送的,数据位由高到低传送,每位数据占一个时钟脉冲.在时 ...

  6. STM32基于软件模拟IIC进行AHT21B温湿度采集

    STM32基于软件模拟IIC进行AHT21B温湿度采集 一. IIC简介 1.1 IIC简介 1.2 实现方式 1.3 实现方式对比 二. AHT21B简介 2.1 简介 2.2 产品特点 2.3 外 ...

  7. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)

    版权声明:本文为博主原创文章,允许转载,但希望标注转载来源. https://blog.csdn.net/qq_38410730/article/details/80312357 IIC的基本介绍 I ...

  8. 模拟IIC——关于模拟IIC的IO口的配置选取推挽输出还是开漏输出,以及是否需要更改IO口输入输出模式和是否需要对IO配置上拉

    在使用模拟IIC的时候,观看别人的程序的时候发现了程序之间的一些不一样的地方 ----------------------------------代码1------------------------ ...

  9. STM32模拟IIC读取PCF8563

    作者第一次开写博客,本着学习的态度,附上自己总结的代码,希望大家多多指点! 一.首先是对于PCF8563芯片的介绍与使用说明: PCF8563 是PHILIPS 公司推出的一款工业级内含I2C 总线接 ...

最新文章

  1. 2 模版_你还只会套PPT模版吗? | 大学生PPT进阶指南(附免费资源amp;教程)
  2. 机器翻译pascal程序
  3. C++实现有序表折半查找
  4. how to execute tcode during startup
  5. [渝粤教育] 中国地质大学 大学英语(2) 复习题
  6. .net core consul 服务配置 服务发现 服务健康检测 服务变更加载
  7. 马上开课 | 临床基因组学数据分析实战助力解析Case,快速发表文章
  8. 【论文笔记】DeepWalk:大型社会表示的在线学习
  9. 一加7 Pro卖到断货 刘作虎:最快速度满足中国用户需求
  10. 超过 40 款很有用而且很新的 jQuery 插件
  11. vue学习代码理解v-for数组遍历和对象遍历以及事件处理
  12. html样式超出出现滚动条,CSS 设置的高度超出屏幕高度为什么没出现滚动条?
  13. java、python什么意思_java和python是什么
  14. debian 系统配置网易镜像源
  15. 注塑模介绍、设计中文语音多媒体教学光盘 1CD
  16. 实用​Android开源项目及库​
  17. 腾讯笔试题——猴子吃桃(PythonC语言实现)
  18. 720P、1080P、4K是什么意思?
  19. mac下面如何修改只读文件
  20. 浏览器代理服务器没有响应解决方案

热门文章

  1. NodeMCU检测Flash按键实现长按触发(用于进入设计好的配置模式)(C++开发)
  2. 2021-08-28web培训作业2(sql实战注入尝试getshell,googlehacking,数据库拿到账户信息登录后台管理,fck的upload)
  3. 看图学维修mp3之电源篇65Z8\65Z5
  4. COSCon'22 杭州会场回顾 | 谁说开源人只懂代码不懂玩?
  5. 完美的扎克伯格,倒霉的Facebook
  6. java使用二维数组和控制台实现五子棋单机版
  7. H5人脸实名认证-百度云版
  8. 群晖nas给linux共享空间,群晖NAS - 存储空间不足的解决方法
  9. three.js加载obj模型和材质
  10. 【loj3054】【hnoi2019】鱼