/******************************** (C) COPYRIGHT 2015 Seven ********************************
* @Function: EEPROM Driver
* @Author: 张其睿
* @Data: 2015.12.24
* @Version Log:
* -----------------------------------------------------------------------------------------
* 2015/12/24 V1.0 Seven 自适应各型号的EEPROM,用户只需修改 EEPROM_ADDR,EEPROM_TYPE
******************************************************************************************/
#include "eeprom.h"
#include <rtthread.h>
#include "stdlib.h"
#include "stdio.h"
/******************************************************************************************
* @Function:Debug option
*******************************************************************************************/
//#define EEPROM_DEBUG_ENABLE
#ifdef EEPROM_DEBUG_ENABLE
#define EEPROM_DEBUGF(format,...) rt_kprintf(""__FILE__",%d -> "format" \n",__LINE__,##__VA_ARGS__)
#define EEPROM_DEBUG(format,...) rt_kprintf(format,##__VA_ARGS__)
#else
#define EEPROM_DEBUG(format,...)
#endif
/******************************************************************************************
* @Function:
*******************************************************************************************/
//请根据实际情况配置以下6个参数
#define EEPROM_ADDR 0xA0 //eeprom Address:0xA0
#define EEPROM_TYPE (16) //eeprom Type:24C16
#define EEPROM_SCL_PIN GPIO_Pin_5 //I2C SCL
#define EEPROM_SDA_PIN GPIO_Pin_6 //I2C SDA
#define EEPROM_PORT GPIOD //I2C GPIO PORT
#define EEPROM_CLOCK RCC_APB2Periph_GPIOD //I2C GPIO CLOCK
//以下若无特殊要求不用理会
#define EEPROM_REG_MAX (128 * EEPROM_TYPE)
#define EEPROM_DELAY 1
#define EEPROM_WRITE_DELAY 500
#define EEPROM_TIMEOUT 200
//页大小,连续写超过页大小时会从页开始的地方重新写(覆盖前面的数据)
#if(EEPROM_TYPE < 4) //24C01 24C02
#define EEPROM_PAGE_SIZE 8
#elif(EEPROM_TYPE <= 16) //24C04 24C08 24C16
#define EEPROM_PAGE_SIZE 16
#elif(EEPROM_TYPE > 16)
#define EEPROM_PAGE_SIZE 32 //24C32 24C64 24C128 ...
#endif
#define EEPROM_SCL_H() EEPROM_PORT->BSRR = EEPROM_SCL_PIN
#define EEPROM_SCL_L() EEPROM_PORT->BRR = EEPROM_SCL_PIN
#define EEPROM_SDA_H() EEPROM_PORT->BSRR = EEPROM_SDA_PIN
#define EEPROM_SDA_L() EEPROM_PORT->BRR = EEPROM_SDA_PIN
#define EEPROM_SDA_In() //{EEPROM_PORT->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define EEPROM_SDA_Out() //{EEPROM_PORT->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
#define EEPROM_SDA_Read() (EEPROM_PORT->IDR & EEPROM_SDA_PIN)
/******************************************************************************************
* @Description:Error Code
*******************************************************************************************/
#define EEPROM_ADDR_NOACK 0x01
#define EEPROM_REG_NOACK 0x02
#define EEPROM_SEND_NOACK 0x03
#define EEPROM_ADDRESS_ERROR 0x10
#define EEPROM_DEVICE_ERROR 0x20
/******************************************************************************************
* @Description: I2C DELAY
* @Parameter: [None]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_Delay(uint32_t n)
{
uint16_t tmp;
while(n--)
{
tmp = 140;
while(tmp--);
}
}
/******************************************************************************************
* @Description: I2C Start
* @Parameter: [None]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_I2C_Start(void)
{
//if(!EEPROM_SDA_Read())return 1; //SDA线为低电平则总线忙,退出
EEPROM_SDA_Out();
EEPROM_SDA_H();
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SDA_L();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_L();
EEPROM_Delay(EEPROM_DELAY);
}
/******************************************************************************************
* @Description: I2C Stop
* @Parameter: [None]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_I2C_Stop(void)
{
EEPROM_SDA_Out();
EEPROM_SCL_L();
EEPROM_SDA_L();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SDA_H();
}
/******************************************************************************************
* @Description: Wait Acknowledgement
* @Parameter: [None]
* @Return: [Status:0->ACK 1->NOACK]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static uint8_t EEPROM_I2C_WaitACK(void)
{
uint8_t timeout;
EEPROM_SDA_In();
EEPROM_SDA_H();
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
/* 等待从器件响应 */
timeout = 0;
while( EEPROM_SDA_Read() && timeout < EEPROM_TIMEOUT)
{
timeout++;
EEPROM_Delay(EEPROM_DELAY);
}
/* 超时处理 */
if(timeout >= EEPROM_TIMEOUT){EEPROM_I2C_Stop();return 1;}
/* 响应成功 */
EEPROM_SCL_L();
return 0;
}
/******************************************************************************************
* @Description: Send Acknowledgement
* @Parameter: [None]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_I2C_SendACK(void)
{
EEPROM_SDA_Out(); //输出状态
EEPROM_SCL_L();
EEPROM_SDA_L();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_L();
EEPROM_SDA_H();
}
/******************************************************************************************
* @Description: Send No Acknowledgement
* @Parameter: [None]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_I2C_SendNoACK(void)
{
EEPROM_SDA_Out();
EEPROM_SCL_L();
EEPROM_SDA_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_L();
}
/******************************************************************************************
* @Description: Send One Byte via I2C
* @Parameter: [Data]
* @Return: [None]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static void EEPROM_I2C_SendTo(uint8_t Data)
{
uint8_t i=8;
EEPROM_SDA_Out(); //设置为输出状态
EEPROM_SCL_L();
while (i--)
{
/* 发送数据 */
if( Data & 0x80)EEPROM_SDA_H();else EEPROM_SDA_L();
Data <<= 1;
EEPROM_SCL_H();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_L();
EEPROM_Delay(EEPROM_DELAY);
}
EEPROM_SDA_H();
}
/******************************************************************************************
* @Description: Receive One Byte via I2C
* @Parameter: [None]
* @Return: [Receive Data]
* @Description: 2015/12/24 张其睿
*******************************************************************************************/
static uint8_t EEPROM_I2C_ReceiveFrom(void)
{
uint8_t i=8;
uint8_t Data=0;
EEPROM_SDA_In(); //设置为输入状态
while (i--)
{
Data <<= 1;
EEPROM_SCL_L();
EEPROM_Delay(EEPROM_DELAY);
EEPROM_SCL_H();
if( EEPROM_SDA_Read() ) Data |= 0x0