- /**
- ********************************************************************
- * 文件名 EEPROM_24LC256.c
- * 作 者 ChipON_AE/FAE_Group
- * 版 本 V2.1
- * 日 期 2019-11-16
- * 描 述 该文件提供了EERPOM读写功能函数等相关函数。
- *
- *********************************************************************
- */
- #include "system_init.h"
- #include "EEPROM_24LC256.h"
- #define I2C_Buffer_Addr 0x40000D08 //I2C0 Buffer 地址
- I2C_SFRmap* I2C_Choose; //定义I2C变量,取值 为I2C0_SFR~I2C3_SFR
- //延时函数 局部变量用volatile声明,否则可能会被优化
- void Delay(volatile uint32_t cnt)
- {
- while(cnt--);
- }
- void delay_ms(volatile uint32_t nms)
- {
- volatile uint32_t i,j;
- for(i=0;i<nms;i++)
- {
- j=800;
- while(j--);
- }
- }
- /**
- * 描述 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--;
- }
- // if(number_of_byte==1)
- // {
- // I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
- // I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后读完后清标志位ISIF位
- // }
- }
- /*停止位*/
- 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模组
- }
- /**
- * 描述 I2C_DMA 初始化。
- * 输入 无
- *
- * 返回 无。
- */
- void I2C_DMA_Init(void)
- {
- uint32_t *I2C_write_ADDR=&i2c_buffer_write[0];
- DMA_InitTypeDef I2C_DMAStruct;
- //注意:DMA传感完成标志产生是在传输完成倒数第一个时就会置位
- I2C_DMAStruct.m_Number = WRITE_BUFFER_SIZE+1;/* 配置 传输数据个数: WRITE_BUFFER_SIZE+1 */
- I2C_DMAStruct.m_Direction = DMA_MEMORY_TO_PERIPHERAL;/* 配置 DMA传输方向: 内存到外设*/
- I2C_DMAStruct.m_Priority = DMA_CHANNEL_LOWER;/* 配置 DMA通道优先级:低优先级 */
- I2C_DMAStruct.m_PeripheralDataSize = DMA_DATA_WIDTH_8_BITS;/* 配置 外设数据位宽:8位宽 */
- I2C_DMAStruct.m_MemoryDataSize = DMA_DATA_WIDTH_8_BITS;/* 配置 存储器数据位宽:8位宽 */
- I2C_DMAStruct.m_PeripheralInc = FALSE;/* 配置 外设地址增量模式使能: 不使能 */
- I2C_DMAStruct.m_MemoryInc = TRUE;/* 配置 存储器地址增量模式使能: 使能 */
- I2C_DMAStruct.m_Channel = DMA_CHANNEL_4;/* 配置 DMA通道选择:通道4 */
- I2C_DMAStruct.m_BlockMode = DMA_TRANSFER_BYTE; /* 配置 数据块传输模式: */
- I2C_DMAStruct.m_LoopMode = TRUE;/* 配置 循环模式使能: 禁止 */
- I2C_DMAStruct.m_PeriphAddr = I2C_Buffer_Addr;/* 配置 外设起始地址:等待发送的数据的起始地址 */
- I2C_DMAStruct.m_MemoryAddr = I2C_write_ADDR;/* 配置 内存起始地址:接收数据的内存空间的起始地址 */
- DMA_Reset(DMA0_SFR);
- DMA_Configuration(DMA0_SFR, &I2C_DMAStruct);
- }
- void DMA_I2C_Enable(FunctionalState NewState)
- {
- I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
- I2C_Transmit_DMA_INT_Enable(I2C_Choose,NewState); //使能 I2C0发送DMA中断
- DMA_Channel_Enable(DMA0_SFR,DMA_CHANNEL_4,NewState); //配置使能DMA0 通道4
- /*发送*/
- I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
- I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清中断标志ISIF
- I2C_Generate_START(I2C_Choose,TRUE); //开起始信号
- while(!DMA_Get_Finish_Transfer_INT_Flag(DMA0_SFR,DMA_CHANNEL_4)); //等待DMA传输完成
- if(!I2C_Get_Transmit_Buff_Flag(I2C_Choose)) //读取Buff状态,为空则释放总线
- {
- /*停止位*/
- I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
- I2C_Clear_INTERRUPT_Flag(I2C_Choose); ////清中断标志ISIF
- }
- 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_DMA(void)
- {
- volatile uint16_t i;
- i2c_buffer_write[0]=EEPROM_I2C_ADDRESS; // EEPROM I2C 地址定义
- i2c_buffer_write[1]=EEPROM_ADDH; // EEPROM I2C 高8位寄存器地址定义
- i2c_buffer_write[2]=EEPROM_ADDL; // EEPROM I2C 低8位寄存器地址定义
- /* 初始化i2c写缓冲区 */
- for(i = 3;i < WRITE_BUFFER_SIZE;i++)
- {
- i2c_buffer_write[i]=i-3; //0~0X3F
- }
- Delay(0XFFFF);
- Delay(0XFFFF);
- /* 使用DMA 写EERPOM 数据*/
- I2C_DMA_Init(); //初始化I2C DMA
- DMA_I2C_Enable(TRUE); //使能DMA 通道及I2C触发DMA
- Delay(0XFFFF);
- Delay(0XFFFF);
- Delay(0XFFFF);
- I2C_Transmit_DMA_INT_Enable(I2C0_SFR,FALSE); //关 I2C0发送DMA中断
- DMA_Channel_Enable(DMA0_SFR,DMA_CHANNEL_4,FALSE); //关DMA0 通道4
- 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);
- ///写入的EEPROM数据和读出的EERPOM数据对比
- for(i = 0;i < READ_BUFFER_SIZE;i++)
- {
- if(i2c_buffer_read[i] != i2c_buffer_write[i+3])
- {
- return I2C_FAIL;
- }
- }
- return I2C_OK;
- }