/**
********************************************************************
* 文件名 EEPROM_24LC256.c
* 作 者 ChipON_AE/FAE_Group
* 版 本 V2.1
* 日 期 2019-11-16
* 描 述 该文件提供了EERPOM读写功能函数等相关函数。
*
*********************************************************************
*/
#include "system_init.h"
#include "EEPROM_24LC256.h"
#include "Usart.h"
I2C_SFRmap* I2C_Choose;
//延时函数 局部变量用volatile声明,否则可能会被优化
void Delay(volatile uint32_t cnt)
{
while(cnt--);
}
/**
* 描述 eeprom 写入单字节数据。
* 输入 write_address:eeprom 16位寄存器地址
* p_buffer: 写入数据,取值为10位数据。
* 返回 无。
*/
void eeprom_byte_write(uint16_t write_address,uint32_t p_buffer)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(write_address>>8)& 0xff; //高8位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送高位地址*/
I2C_SendData(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送低位地址*/
I2C_SendData(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送数据*/
I2C_SendData(I2C_Choose, p_buffer); //发送8位数据
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模块
}
/**
* 描述 eeprom 写入多字节数据。
* 输入 write_address:eeprom 16位寄存器地址
* p_buffer: 写入数据指针
* number_of_byte:写入数据长度
* 返回 无。
*/
void eeprom_buffer_write(uint16_t Write_address,uint8_t *p_buffer,uint16_t number_of_byte)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff; //高8位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/* 循环写数据操作 */
while(number_of_byte--){
I2C_SendData8(I2C_Choose, *p_buffer); //发送8位数据
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
/* 指向下一个所要写的字节 */
p_buffer++;
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
}
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述 eeprom 读出单字节数据。
* 输入 write_address:eeprom 16位寄存器地址
* p_buffer: 读出数据,取值为8位数据。
* 返回 无。
*/
void eeprom_byte_read(uint16_t Write_address,uint8_t p_buffer)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff;//低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff; //高8位寄存器地址
I2C_Cmd(I2C_Choose,TRUE);
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送要读寄存器高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送要读寄存器低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
I2C_Cmd(I2C_Choose,FALSE); //关I2C模块
I2C_Clear_Start_Flag(I2C_Choose); //清I2C起始标志位SIF位
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始信号稳定
/*发送读指令*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS|0x01);//发送从机地址及读操作
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成ISIF会置1
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后完成清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待读取Buff完成ISIF会置1
if(I2C_Get_Receive_Buff_Flag(I2C_Choose)) //判断Buff是否为满
{
I2C_Ack_DATA_Config(I2C_Choose,I2C_ACKDATA_ACK);//回复ACK
p_buffer = I2C_ReceiveData(I2C_Choose);
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后读完后清标志位ISIF位
}
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述 eeprom 读出多字节数据。
* 输入 write_address:eeprom 16位寄存器地址
* p_buffer: 读出数据指针
* number_of_byte:读出数据长度
* 返回 无。
*/
void eeprom_buffer_read(uint16_t Write_address,uint8_t *p_buffer,uint16_t number_of_byte)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff; //高8位寄存器地址
I2C_Cmd(I2C_Choose,TRUE); //使能I2C3模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送要读寄存器高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送要读寄存器低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
I2C_Cmd(I2C_Choose,FALSE); //关I2C模块
I2C_Clear_Start_Flag(I2C_Choose); //清I2C起始标志位SIF位
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //打开I2C模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送读指令*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS|0x01);//发送从机地址及读操作
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成ISIF会置1
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后完成清标志位ISIF位
while(number_of_byte)
{
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待读取Buff完成ISIF会置1
if(I2C_Get_Receive_Buff_Flag(I2C_Choose)) //判断Buff是否为满
{
*p_buffer = I2C_ReceiveData(I2C_Choose);
I2C_Ack_DATA_Config(I2C_Choose,I2C_ACKDATA_ACK);//回复ACK
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后读完后清标志位ISIF位
p_buffer++; /* 指向下一个被读取的字节将被保存的位置 */
/* 递减读取字节计数器 */
number_of_byte--;
}
}
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述 先写64个字节数据并读出64个字节数据进行比较。
* 输入 无
* 返回 1 :数据对比匹配。
* 0 :数据对比不匹配。
*/
uint8_t AT24LC256_TEST(void)
{
static volatile uint16_t i;
static volatile uint16_t j;
i=0;
j=0;
/* 初始化i2c写缓冲区 */
for(i = 0;i < BUFFER_SIZE;i++)
{
i2c_buffer_write[i]=i;
}
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
/* EEPROM 数据写入 */
eeprom_buffer_write(EEP_FIRST_PAGE,i2c_buffer_write,sizeof(i2c_buffer_write));
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
/* EEPROM 数据读取 */
eeprom_buffer_read(EEP_FIRST_PAGE,i2c_buffer_read,sizeof(i2c_buffer_read));
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
for(j = 0;j < BUFFER_SIZE;j++)
{
if(i2c_buffer_read[j] != i2c_buffer_write[j])
{
return I2C_FAIL;
}
}
return I2C_OK;
}