/*********文件名:i2c_ee.h**********/
/* Define to prevent recursive inclusion ------------------------------------ */
#ifndef __I2C_EE_H
#define __I2C_EE_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported macro ------------------------------------------------------------*/
#define ADDR_24CXX 0xA0
#define SCLH GPIOB->BSRR = GPIO_Pin_6
#define SCLL GPIOB->BRR = GPIO_Pin_6
#define SDAH GPIOB->BSRR = GPIO_Pin_7
#define SDAL GPIOB->BRR = GPIO_Pin_7
#define SCLread GPIOB->IDR & GPIO_Pin_6
#define SDAread GPIOB->IDR & GPIO_Pin_7
/* Exported functions ------------------------------------------------------- */
void I2C_EE_Init(void);
uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte);
uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte);
#endif /* __I2C_EE_H */
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/*********文件名:i2c_ee.c**********/
#include "i2c_ee.h"
enum ENUM_TWI_REPLY
{
TWI_NACK=0
,TWI_ACK=1
};
enum ENUM_TWI_BUS_STATE
{
TWI_READY=0
,TWI_BUS_BUSY=1
,TWI_BUS_ERROR=2
};
void I2C_EE_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// Configure I2C1 pins: SCL and SDA
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void TWI_delay(void)
{
uint8_t i=10; //i=10延时1.5us//这里可以优化速度 ,经测试最低到5还能写入
while(i--);
}
/**************************************************************************
延时
ms:延时的毫秒数
CYCLECOUNTER / 72000000
***************************************************************************/
void DelayMs(uint16_t ms)
{
uint16_t iq0;
uint16_t iq1;
for(iq0 = ms; iq0 > 0; iq0--)
{
for(iq1 = 11998; iq1 > 0; iq1--); // ( (6*iq1+9)*iq0+15 ) / 72000000
}
}
uint8_t TWI_Start(void)
{
SDAH;
SCLH;
TWI_delay();
if(!SDAread)return TWI_BUS_BUSY; //SDA线为低电平则总线忙,退出
SDAL;
TWI_delay();
if(SDAread) return TWI_BUS_ERROR; //SDA线为高电平则总线出错,退出
SCLL;
TWI_delay();
return TWI_READY;
}
/*void TWI_Stop(void)
{
SCLL;
TWI_delay();
SDAL;
TWI_delay();
SCLH;
TWI_delay();
SDAH;
TWI_delay();
}*/
void TWI_Stop(void)
{
SDAL;
SCLL;
TWI_delay();
SCLH;
TWI_delay();
SDAH;
TWI_delay();
}
void TWI_Ack(void)
{
SCLL;
TWI_delay();
SDAL;
TWI_delay();
SCLH;
TWI_delay();
SCLL;
TWI_delay();
}
void TWI_NoAck(void)
{
SCLL;
TWI_delay();
SDAH;
TWI_delay();
SCLH;
TWI_delay();
SCLL;
TWI_delay();
}
uint8_t TWI_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
SCLL;
TWI_delay();
SDAH;
TWI_delay();
SCLH;
TWI_delay();
if(SDAread)
{
SCLL;
return 0;
}
SCLL;
return 1;
}
void TWI_SendByte(uint8_t SendByte) //数据从高位到低位//
{
uint8_t i=8;
while(i--)
{
SCLL;
TWI_delay();
if(SendByte&0x80)
SDAH;
else
SDAL;
SendByte<<=1;
TWI_delay();
SCLH;
TWI_delay();
}
SCLL;
}
uint8_t TWI_ReceiveByte(void) //数据从高位到低位//
{
uint8_t i=8;
uint8_t ReceiveByte=0;
SDAH;
while(i--)
{
ReceiveByte <<= 1;
SCLL;
TWI_delay();
SCLH;
TWI_delay();
if(SDAread)
{
ReceiveByte |= 0x01;
}
}
SCLL;
return ReceiveByte;
}
//返回:3写入成功;0写器件地址出错,1总线忙,2出错
//写入1字节数据 SendByte:待写入数据 WriteAddress:待写入地址
uint8_t TWI_WriteByte(uint8_t SendByte, uint8_t WriteAddress)
{
uint8_t i;
uint16_t j;
i = TWI_Start();
if(i)
return i;
TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址 写入:地址最低位是0,读取:地址最低位是1
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(WriteAddress); //设置起始地址
TWI_WaitAck();
TWI_SendByte(SendByte); //写数据
TWI_WaitAck();
TWI_Stop();
//注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
DelayMs(12); //写入延时 12ms 写周期大于10ms即可
return 3;
}
//返回:0写器件地址出错,1总线忙,2出错,
//读出1字节数据
//ReadAddress:待读出地址
uint8_t TWI_ReadByte( uint8_t ReadAddress)
{
uint8_t i,temp;
i = TWI_Start();
if(i)
return i;
TWI_SendByte((ADDR_24CXX & 0xFE));//写器件地址,先执行一次伪写操作
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(ReadAddress); //设置起始地址
TWI_WaitAck();
TWI_Start();
TWI_SendByte((ADDR_24CXX & 0xFE)|0x01); //读器件地址 写入:地址最低位是0,读取:地址最低位是1
TWI_WaitAck();
//*pDat = TWI_ReceiveByte();
temp = TWI_ReceiveByte();
TWI_NoAck();
TWI_Stop();
return temp;//返回的如果是0,1,2则与错误代码相同了,再考虑一下
}
/***************************************************************************
向24c256中写多个字节
psrc_data:指向要写入数据数组的指针
adr:24c256中要写入数据的首地址
nbyte:写入的字节数
返回值: 0:执行完毕;1:执行出现错误
形参中:C02只有一个地址adr;C256中有高位地址hadr和低位地址ladr
***************************************************************************/
uint8_t I2C_EE_BufferWrite(uint8_t *psrc_data,uint8_t adr,uint8_t nbyte)
{
uint8_t i;
for(;nbyte!=0;nbyte--)
{
i = TWI_Start();
if(i)
return i;
TWI_SendByte( ADDR_24CXX & 0xFE);//写器件地址
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(adr); //设置起始地址
TWI_WaitAck();
TWI_SendByte(*psrc_data); //写数据
TWI_WaitAck();
psrc_data++; //指向待写数据的指针加1
adr++; //对24C08的操作地址加1
TWI_Stop();
//注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
DelayMs(12); //写入延时 12ms 写周期大于10ms即可
}
return 0;
}
/***************************************************************************
从24c02读多个字节
pdin_data:指向要保存读出数据的数组的指针
adr:24c02中要读出数据的首地址
nbyte:读出的字节数
返回值: 0:执行完毕;1:执行出现错误
***************************************************************************/
uint8_t I2C_EE_BufferRead(uint8_t *pdin_data,uint8_t adr,uint8_t nbyte)
{
uint8_t i;
i = TWI_Start();
if(i)
return i;
TWI_SendByte((ADDR_24CXX & 0xFE));//写器件地址,先执行一次伪写操作
if(!TWI_WaitAck())
{
TWI_Stop();
return 0;
}
TWI_SendByte(adr); //设置起始地址
TWI_WaitAck();
TWI_Start();
TWI_SendByte((ADDR_24CXX & 0xFE)|0x01); //读器件地址 写入:地址最低位是0,读取:地址最低位是1
TWI_WaitAck();
while(nbyte!=1) //读入前(nbyte-1)个字节
{
*pdin_data = TWI_ReceiveByte(); //循环从24C02中读数据,存入pdin_data所指的存储器中
TWI_Ack(); //IIC应答
pdin_data++; //指向存储读入数据的存储器指针加1
nbyte--; //剩余要读入的字节减1
};
*pdin_data = TWI_ReceiveByte(); //读入最后一个字节
TWI_NoAck(); //IIC无应答操作
TWI_Stop();
return 0;
}
/*
void TWI_24CXX_Write(uint8_t* pDat, uint8_t nAddr, uint8_t nLen)
{
uint16_t i;
for(i=0;i
转自:http://blog.csdn.net/xfcylyf/article/details/7982271