// 该代码用于测试没问题
#define I2C_SCL_PORT GPIOB
#define I2C_SCL_Pin GPIO_Pin_8
#define I2C_SDA_PORT GPIOB
#define I2C_SDA_Pin GPIO_Pin_9
#define OUTPUT 0
#define INPUT 1
static void I2C_Tail(void); //发送结束标志
static void I2C_Head(unsigned short Addrs); // 发送起始标志
static void hal_I2C_Config(void); // 模拟I2C配置函数
static void hal_I2C_SCL_SET(unsigned char i); // 设置时钟引脚
static void hal_I2C_SDA_SET(unsigned char i); // 设置数据引脚
static void hal_I2C_Start(void); // 起始标志
static void hal_I2C_Stop(void); // 结束标志
static void I2C_Delay(unsigned short t);
static void I2C_ACK(void); // 有ACK应答
static void I2C_NOACK(void); // 无ACK应答
static void I2C_SendByte(unsigned char data); // 写一个byte数据时序
static void I2C_WriteByte(unsigned short Addr, unsigned char data); // 发送一个byte
static unsigned char I2C_RecvByte(void); // 读一个字节时序
static unsigned char I2C_WaitAck(void); // 返回0,无应答数据 。返回1,有应答数据
void hal_I2C_SDA_IO_SET(unsigned char IOMode); // OUTPUT 或者 INPUT
unsigned char hal_IC_SDA_INPUT(void);
unsigned char I2C_ReadByte(unsigned short Addr); // 读一个字节数据
void hal_eeprom_Init(void)
{
hal_I2C_Config();
}
unsigned char I2C_ReadByte(unsigned short Addr)
{
unsigned char dat;
hal_I2C_Start();
I2C_SendByte(0xA0);
I2C_WaitAck();
I2C_SendByte((Addr>>8)&0xFF);
I2C_WaitAck();
I2C_SendByte(Addr&0xFF);
I2C_WaitAck();
hal_I2C_Start();
I2C_SendByte(0xA1); // 发送 1010 0001 最低位的1代表从该芯片读取数据
I2C_WaitAck();
dat = I2C_RecvByte();
I2C_NOACK();
hal_I2C_Stop();
return dat;
}
static unsigned char I2C_RecvByte(void)
{
unsigned char i = 0;
unsigned char RecvByte = 0;
hal_I2C_SCL_SET(0);
I2C_Delay(1);
hal_I2C_SDA_SET(1);
hal_I2C_SDA_IO_SET(INPUT);
for(; i < 8; i++)
{
RecvByte<<=1;
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
if(hal_IC_SDA_INPUT()) {
RecvByte |= 0x01;
}
hal_I2C_SCL_SET(0);
}
hal_I2C_SDA_IO_SET(OUTPUT);
I2C_Delay(1);
return RecvByte;
}
void hal_I2C_Read( unsigned short Addrs, unsigned char *pBuf, unsigned short Len)
{
unsigned short i = 0;
I2C_Head(Addrs);
hal_I2C_Start();
I2C_SendByte(0xA1); // 发送 1010 0001 最低位的1代表从该芯片读取数据
I2C_WaitAck();
for( i = 0; i < Len; i++)
{
pBuf[i] = I2C_RecvByte();
if(i == Len - 1) I2C_NOACK();
else I2C_ACK();
}
hal_I2C_Stop();
}
static void I2C_WriteByte(unsigned short Addr, unsigned char data)
{
hal_I2C_Start(); // 发送有效数据起始标志
// 该芯片最低位的一个bit位代表读/写:0 代表写入数据 || 1 代表读出数据
I2C_SendByte(0xA0); // 发送需要通信的硬件地址(对应的硬件手册上有!!!!!)
I2C_WaitAck();
I2C_SendByte((Addr>>8)&0xFF); // 发送写入的地址(高字节地址)
I2C_WaitAck();
I2C_SendByte(Addr&0xFF); // 发送写入的地址(低字节地址)
I2C_WaitAck();
I2C_SendByte(data);
I2C_WaitAck();
hal_I2C_Stop(); // 发送有效数据结束标志
I2C_Delay(20000);
}
static unsigned char I2C_WaitAck(void)
{
hal_I2C_SDA_SET(1);
hal_I2C_SDA_IO_SET(INPUT); // 设置SDA引脚为输入引脚
hal_I2C_SCL_SET(1);
I2C_Delay(1);
if(hal_IC_SDA_INPUT()) { // 该引脚为高电平,代表无应答
hal_I2C_SDA_IO_SET(OUTPUT); // 设置SDA引脚为输出引脚
return 0;
}
hal_I2C_SCL_SET(0);
hal_I2C_SDA_IO_SET(OUTPUT);
I2C_Delay(1);
return 1;
}
static void I2C_Head(unsigned short Addrs)
{
hal_I2C_Start(); // 发送有效数据起始标志
// 该芯片最低位的一个bit位代表读/写:0 代表写入数据 || 1 代表读出数据
I2C_SendByte(0xA0); // 发送需要通信的硬件地址(对应的硬件手册上有!!!!!)
I2C_WaitAck();
I2C_SendByte((Addrs>>8)&0xFF); // 发送写入的地址(高字节地址)
I2C_WaitAck();
I2C_SendByte(Addrs&0xFF); // 发送写入的地址(低字节地址)
I2C_WaitAck();
}
static void I2C_Tail(void)
{
hal_I2C_Stop(); // 发送有效数据结束标志
I2C_Delay(20000);
}
void hal_I2C_Write(unsigned short Addrs, unsigned char* pBuf, unsigned short Len)
{
unsigned short tmp = 0;
unsigned short i = 0, j = 0;
unsigned short page = 0;
unsigned short size;
if(Addrs%EEPROM_PAGE_SIZE)
{
tmp = EEPROM_PAGE_SIZE-(Addrs%EEPROM_PAGE_SIZE); // 拿到当前页还有多少字节可写入
if(tmp > Len)
{
tmp = Len; // 后续写入操作,需要tmp来做循环因子
}
}
// 先将数据写入当前页
if(tmp)
{
I2C_Head(Addrs);
// 正式写入数据
for(i = 0; i < tmp; i++)
{
I2C_SendByte(pBuf[i]);
I2C_WaitAck();
}
I2C_Tail();
}
Len -= tmp; // 将已经发送过的数据个数减掉
Addrs += tmp; // 将写入的地址更新
page = Len/EEPROM_PAGE_SIZE; // int整形除法,只会得到整数
size = Len%EEPROM_PAGE_SIZE; // 不足一页还有几个字节
for(i = 0; i < page; i++)
{
I2C_Head(Addrs);
for(j = 0; j < EEPROM_PAGE_SIZE; j++)
{
I2C_SendByte(pBuf[tmp + j]);
I2C_WaitAck();
}
I2C_Tail();
Addrs += EEPROM_PAGE_SIZE;
tmp += EEPROM_PAGE_SIZE;
}
if(size)
{
I2C_Head(Addrs);
for(i = 0; i < size; i++)
{
I2C_SendByte(pBuf[tmp + i]);
I2C_WaitAck();
}
I2C_Tail();
}
}
static void I2C_SendByte(unsigned char data)
{
unsigned char i = 0;
for(; i < 8; i++)
{
hal_I2C_SCL_SET(0);
I2C_Delay(1);
if(data&0x80){
hal_I2C_SDA_SET(1);
} else {
hal_I2C_SDA_SET(0);
}
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
data<<=1;
}
hal_I2C_SCL_SET(0);
I2C_Delay(1);
hal_I2C_SDA_SET(1);
I2C_Delay(1);
}
static void I2C_ACK(void)
{
hal_I2C_SCL_SET(0);
I2C_Delay(1);
hal_I2C_SDA_SET(0); // SDA数据线置低,进行数据位应答。
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
hal_I2C_SCL_SET(0);
I2C_Delay(1);
}
static void I2C_NOACK(void)
{
hal_I2C_SCL_SET(0);
I2C_Delay(1);
hal_I2C_SDA_SET(1); // SDA数据线置高,不进行数据应答。
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
hal_I2C_SCL_SET(0);
I2C_Delay(1);
}
static void hal_I2C_Start(void)
{
hal_I2C_SDA_SET(1);
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
hal_I2C_SDA_SET(0);
I2C_Delay(1);
}
static void hal_I2C_Stop(void)
{
hal_I2C_SDA_SET(0);
I2C_Delay(1);
hal_I2C_SCL_SET(1);
I2C_Delay(1);
hal_I2C_SDA_SET(1);
I2C_Delay(1);
}
static void hal_I2C_Config(void)
{
GPIO_InitTypeDef GPIO_Struct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_Struct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Struct.GPIO_Pin = I2C_SCL_Pin | I2C_SDA_Pin;
GPIO_Init(GPIOB, &GPIO_Struct);
hal_I2C_SDA_SET(1);
hal_I2C_SCL_SET(1);
}
void hal_I2C_SDA_IO_SET(unsigned char IOMode)
{
if(0 == IOMode) {
GPIO_InitTypeDef GPIO_Struct;
GPIO_Struct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Struct.GPIO_Pin = I2C_SDA_Pin;
GPIO_Init(GPIOB, &GPIO_Struct);
}
if(1 == IOMode) {
GPIO_InitTypeDef GPIO_Struct;
GPIO_Struct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Struct.GPIO_Pin = I2C_SDA_Pin;
GPIO_Init(GPIOB, &GPIO_Struct);
}
}
static void hal_I2C_SDA_SET(unsigned char i)
{
if(i) {
GPIO_SetBits(I2C_SDA_PORT,I2C_SDA_Pin);
} else {
GPIO_ResetBits(I2C_SDA_PORT,I2C_SDA_Pin);
}
}
static void hal_I2C_SCL_SET(unsigned char i)
{
if(i) {
GPIO_SetBits(I2C_SCL_PORT,I2C_SCL_Pin);
} else {
GPIO_ResetBits(I2C_SCL_PORT,I2C_SCL_Pin);
}
}
static void I2C_Delay(unsigned short t)
{
unsigned short i=50,j,c;
c = t;
for(j=0; j<c; j++)
{
while(i)
{
i--;
}
}
}
unsigned char hal_IC_SDA_INPUT(void)
{
return GPIO_ReadInputDataBit(I2C_SDA_PORT, I2C_SDA_Pin);
}
|