674 lines
12 KiB
C
674 lines
12 KiB
C
#include "bl24c512.h"
|
||
#include "include.h"
|
||
|
||
|
||
|
||
static u32 last_write_time;
|
||
bool I2C_eeprom_write_byte( u16 addr, u8 data);
|
||
bool I2C_eeprom_Read_byte(u16 addr, u8 *data);
|
||
|
||
void eeprom_da_mode(bool in_mode)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_InitStructure.GPIO_Pin = SDA_PIN;
|
||
GPIO_InitStructure.GPIO_Mode = (in_mode == TRUE) ? GPIO_Mode_IN_FLOATING : GPIO_Mode_Out_OD;
|
||
GPIO_Init(SDA_PIN_PORT, &GPIO_InitStructure );
|
||
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_InitStructure.GPIO_Pin = SCL_PIN;
|
||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||
GPIO_Init(SCL_PIN_PORT , &GPIO_InitStructure );
|
||
}
|
||
|
||
|
||
/*************************************************************
|
||
函数功能:延时连个指令周期
|
||
函数名称:delayedus
|
||
函数返回:无返回值。
|
||
函数参数:延时时间
|
||
**************************************************************/
|
||
void delayed_ms(u8 n)
|
||
{
|
||
u32 dy;
|
||
u8 i;
|
||
for(i=0;i<n;i++)
|
||
{
|
||
dy=3200;
|
||
while(dy!=0)
|
||
{dy--;}
|
||
}
|
||
}
|
||
|
||
|
||
void delayedus(u8 n)
|
||
{
|
||
u8 i;
|
||
for(i=0;i<n;i++);
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:I2C总线复位。
|
||
函数名称:I2C_Reset。
|
||
函数返回:无返回值。
|
||
函数参数:无参数
|
||
**************************************************************/
|
||
void I2C_Reset(void)
|
||
{
|
||
eeprom_da_mode(SDA_MODE_IN);
|
||
|
||
while(1)
|
||
{
|
||
SCL_LOW();
|
||
delayedus(1);
|
||
SCL_HIGH();
|
||
if( GET_SDA() ==1 )
|
||
{
|
||
break;
|
||
}
|
||
delayedus(1);
|
||
}
|
||
eeprom_da_mode(SDA_MODE_OUT);
|
||
}
|
||
|
||
|
||
void bl24c512_init(void)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
||
RCC_APB2PeriphClockCmd(SDA_PIN_CLK | SCL_PIN_CLK , ENABLE);
|
||
|
||
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
|
||
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_InitStructure.GPIO_Pin = SDA_PIN;
|
||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
|
||
GPIO_Init(SDA_PIN_PORT , &GPIO_InitStructure );
|
||
|
||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||
GPIO_InitStructure.GPIO_Pin = SCL_PIN;
|
||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
||
GPIO_Init(SCL_PIN_PORT , &GPIO_InitStructure );
|
||
|
||
//I2C_Reset();
|
||
}
|
||
|
||
|
||
/*************************************************************
|
||
函数功能:产生起始位。
|
||
函数名称:I2C_GenerateSTART。
|
||
函数返回:无返回值。
|
||
函数参数:无参数
|
||
**************************************************************/
|
||
void BL24C512I2C_GenerateSTART(void)
|
||
{
|
||
SDA_HIGH();//eeprom_da(1);
|
||
SCL_HIGH();//eeprom_clk(1);
|
||
delayedus(2);
|
||
SDA_LOW();//eeprom_da(0);
|
||
delayedus(2);
|
||
SCL_LOW();//eeprom_clk(0);
|
||
delayedus(2);
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:产生停始位。
|
||
函数名称:I2C_GenerateSTOP。
|
||
函数返回:无返回值。
|
||
函数参数:无参数
|
||
**************************************************************/
|
||
void BL24C512_I2C_GenerateSTOP(void)
|
||
{
|
||
SDA_LOW();//eeprom_da(0);
|
||
delayedus(2);
|
||
SCL_HIGH();//eeprom_clk(1);
|
||
SDA_LOW();//eeprom_da(0);
|
||
delayedus(2);
|
||
SDA_HIGH();//eeprom_da(1);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
void self_test_eeprom(void)
|
||
{
|
||
char testBuf[] = "test eeprom";
|
||
char buf[15] = {0};
|
||
|
||
I2C_eeprom_write_buf(32896, (u8*)testBuf, sizeof(testBuf));
|
||
I2C_eeprom_read_buf( 32896, (u8*)buf, sizeof(testBuf));
|
||
|
||
if (cmp_datas((u8*)buf, (u8*)testBuf, sizeof(testBuf)))
|
||
{
|
||
printf("OK\r\n");
|
||
}
|
||
else
|
||
{
|
||
printf("ERROR\r\n");
|
||
}
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:检测应答。
|
||
函数名称:I2C_check_ack。
|
||
函数返回:返回值是应答状态。
|
||
函数参数:无参数。
|
||
**************************************************************/
|
||
unsigned char I2C_check_ack(void)
|
||
{
|
||
unsigned char ack=0;
|
||
eeprom_da_mode(SDA_MODE_IN);
|
||
SCL_HIGH();//eeprom_clk(1);
|
||
delayedus(1);
|
||
if(GET_SDA() ==1)
|
||
{
|
||
ack=0;
|
||
}
|
||
else
|
||
{
|
||
ack=1;
|
||
}
|
||
SCL_LOW();//eeprom_clk(0);
|
||
delayedus(1);
|
||
eeprom_da_mode(SDA_MODE_OUT);
|
||
return ack;
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:发送一个应答位。
|
||
函数名称:I2c_send_ack。
|
||
函数返回:无返回值。
|
||
函数参数:无。
|
||
**************************************************************/
|
||
void I2c_send_ack(void)
|
||
{
|
||
SDA_LOW();//eeprom_da(0);
|
||
delayedus(1);
|
||
SCL_LOW();//eeprom_clk(0);
|
||
delayedus(1);
|
||
SCL_HIGH();//eeprom_clk(1);
|
||
delayedus(1);
|
||
SCL_LOW();//eeprom_clk(0);
|
||
SDA_HIGH();//eeprom_da(1);
|
||
}
|
||
/*************************************************************
|
||
函数功能:发送一个NO应答。
|
||
函数名称:I2c_send_no_ack。
|
||
函数返回:无返回值。
|
||
函数参数:无。
|
||
*************************************************************/
|
||
void I2c_send_no_ack(void)
|
||
{
|
||
SDA_HIGH();//eeprom_da(1);
|
||
delayedus(1);
|
||
SCL_LOW();//eeprom_clk(0);
|
||
delayedus(1);
|
||
SCL_HIGH();//eeprom_clk(1);
|
||
delayedus(1);
|
||
SCL_LOW();//eeprom_clk(0);
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:I2C发送一个字节。
|
||
函数名称:I2c_send_byte。
|
||
函数返回:无返回值。
|
||
函数参数:无。
|
||
*************************************************************/
|
||
void I2c_send_byte(unsigned char data )
|
||
{
|
||
unsigned char i;
|
||
SCL_LOW(); //eeprom_clk(0);//clk 0
|
||
for(i=0;i<8;i++)
|
||
{
|
||
if((data&0x80)==0x80)
|
||
{
|
||
SDA_HIGH();//eeprom_da(1);
|
||
}
|
||
else
|
||
{
|
||
SDA_LOW(); //eeprom_da(0);
|
||
}
|
||
SCL_HIGH(); //eeprom_clk(1);//clk 1
|
||
delayedus(1);
|
||
SCL_LOW(); //eeprom_clk(0);//clk 0
|
||
delayedus(1);
|
||
data<<=1;
|
||
}
|
||
delayedus(90);
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:I2C接收一个字节。
|
||
函数名称:I2c_receive_byte。
|
||
函数返回:无返回值。
|
||
函数参数:无。
|
||
**************************************************************/
|
||
unsigned char I2c_receive_byte(void)
|
||
{
|
||
unsigned char i;
|
||
unsigned char rda=0;
|
||
eeprom_da_mode(SDA_MODE_IN);
|
||
|
||
SCL_LOW(); //eeprom_clk(0);//clk 0
|
||
delayedus(1);
|
||
for(i=0;i<8;i++)
|
||
{
|
||
rda<<=1;
|
||
SCL_HIGH(); //eeprom_clk(1);//clk 1
|
||
delayedus(1);
|
||
if(GET_SDA() ==1 )
|
||
{
|
||
rda|=0x01;
|
||
}
|
||
else
|
||
{
|
||
rda&=0xFE;
|
||
}
|
||
|
||
SCL_LOW(); //eeprom_clk(0);//clk 0
|
||
delayedus(1);
|
||
}
|
||
eeprom_da_mode(SDA_MODE_OUT);
|
||
|
||
return rda;
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM检测EEPROM是否空闲,可以进行读写
|
||
函数名称:poll_busy。
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr ,对应写入数据data。
|
||
**************************************************************/
|
||
bool poll_busy(void)
|
||
{
|
||
|
||
BL24C512I2C_GenerateSTART();
|
||
|
||
I2c_send_byte(BL24C512ADDR);
|
||
|
||
if(I2C_check_ack()== 1)
|
||
{
|
||
BL24C512_I2C_GenerateSTOP();
|
||
return TRUE;
|
||
}
|
||
else
|
||
{
|
||
BL24C512_I2C_GenerateSTOP();
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
void wait_eeprom_free(void)
|
||
{
|
||
while( last_write_time + 6/portTICK_RATE_MS > xTaskGetTickCount() );
|
||
|
||
while (1)
|
||
{
|
||
if (poll_busy())
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM任意地址写一字节。
|
||
函数名称:I2C_eeprom_write_byte。
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr ,对应写入数据data。
|
||
**************************************************************/
|
||
bool I2C_eeprom_write_byte( u16 addr, u8 data)
|
||
{
|
||
unsigned char addrlow;
|
||
unsigned char addrhigh;
|
||
|
||
|
||
addrlow=(unsigned char)addr;
|
||
addrhigh=(unsigned char)(addr>>8);
|
||
|
||
wait_eeprom_free();
|
||
|
||
BL24C512I2C_GenerateSTART();
|
||
I2c_send_byte(BL24C512ADDR);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrhigh);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrlow);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(data);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
BL24C512_I2C_GenerateSTOP();
|
||
|
||
last_write_time = xTaskGetTickCount();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM任意地址读一字节。
|
||
函数名称:I2C_eeprom_Read_byte。
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr。
|
||
**************************************************************/
|
||
bool I2C_eeprom_Read_byte(u16 addr, u8 *data)
|
||
{
|
||
unsigned char devaddr=0;
|
||
unsigned char addrlow=0;
|
||
unsigned char addrhigh=0;
|
||
|
||
addrlow=(unsigned char)addr;
|
||
addrhigh=(unsigned char)(addr>>8);
|
||
|
||
wait_eeprom_free();
|
||
|
||
BL24C512I2C_GenerateSTART();
|
||
I2c_send_byte(BL24C512ADDR);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrhigh);
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrlow);
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
devaddr=(BL24C512ADDR| 0X01);
|
||
BL24C512I2C_GenerateSTART();
|
||
|
||
I2c_send_byte(devaddr);
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
*data=I2c_receive_byte();
|
||
I2c_send_no_ack();
|
||
delayedus(1);
|
||
BL24C512_I2C_GenerateSTOP();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM写入数组,只能写入小于128byte数据,并且不能超过页范围
|
||
函数名称:I2C_eeprom_write_buf
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr。
|
||
**************************************************************/
|
||
bool I2C_eeprom_write_page(u16 addr, u8 * buf, u8 length)
|
||
{
|
||
unsigned char addrlow;
|
||
unsigned char addrhigh;
|
||
|
||
|
||
addrlow=(unsigned char)addr;
|
||
addrhigh=(unsigned char)(addr>>8);
|
||
|
||
wait_eeprom_free();
|
||
|
||
BL24C512I2C_GenerateSTART();
|
||
I2c_send_byte(BL24C512ADDR);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrhigh);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
I2c_send_byte(addrlow);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
for (u8 i = 0; i < length; i++)
|
||
{
|
||
I2c_send_byte(buf[i]);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
BL24C512_I2C_GenerateSTOP();
|
||
|
||
last_write_time = xTaskGetTickCount();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM写入数组,只能写入小于128byte数据,并且不能超过页范围
|
||
函数名称:I2C_eeprom_write_buf
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr。
|
||
**************************************************************/
|
||
bool I2C_eeprom_write_buf(u16 startAddr, u8 * buf, u16 length)
|
||
{
|
||
bl24c512_init();
|
||
|
||
u16 current_startAddr = startAddr;
|
||
u8 first_page_byte = EEPROM_PAGE_SIZE - (startAddr % EEPROM_PAGE_SIZE);
|
||
u8 * current_data_ptr = buf;
|
||
u16 left_length = length;
|
||
u16 integrated_Pages;
|
||
u16 end_page_byte;
|
||
|
||
if (length > first_page_byte)
|
||
{
|
||
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, first_page_byte))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
current_startAddr = current_startAddr + first_page_byte;
|
||
current_data_ptr += first_page_byte;
|
||
left_length = length - first_page_byte;
|
||
integrated_Pages = left_length / EEPROM_PAGE_SIZE;
|
||
end_page_byte = left_length % EEPROM_PAGE_SIZE;
|
||
|
||
|
||
for (u16 i = 0; i < integrated_Pages; i++)
|
||
{
|
||
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, EEPROM_PAGE_SIZE))
|
||
{
|
||
return FALSE;
|
||
}
|
||
current_startAddr += EEPROM_PAGE_SIZE;
|
||
current_data_ptr += EEPROM_PAGE_SIZE;
|
||
}
|
||
|
||
if (end_page_byte > 0)
|
||
{
|
||
if (!I2C_eeprom_write_page(current_startAddr, current_data_ptr, end_page_byte))
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(!I2C_eeprom_write_page(startAddr, buf, length))
|
||
{
|
||
return FALSE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
/*************************************************************
|
||
函数功能:EEPROM读出数组
|
||
函数名称:I2C_eeprom_write_buf
|
||
函数返回:无返回值。
|
||
函数参数:EEPROM的地址addr。
|
||
**************************************************************/
|
||
bool I2C_eeprom_read_buf(u16 addr, u8 * buf, u16 length)
|
||
{
|
||
unsigned char devaddr;
|
||
|
||
if (length == 0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
wait_eeprom_free();
|
||
|
||
bl24c512_init();
|
||
|
||
if (I2C_eeprom_Read_byte(addr, buf) == FALSE)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
length--;
|
||
|
||
if (length > 0)
|
||
{
|
||
devaddr=(BL24C512ADDR| 0X01);
|
||
|
||
BL24C512I2C_GenerateSTART();
|
||
|
||
I2c_send_byte(devaddr);
|
||
|
||
if(I2C_check_ack()==0)
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
for (u16 i = 0; i < length; i++)
|
||
{
|
||
buf[i+ 1] = I2c_receive_byte();
|
||
|
||
if (i < length - 1)
|
||
{
|
||
I2c_send_ack();
|
||
}
|
||
}
|
||
|
||
I2c_send_no_ack();
|
||
BL24C512_I2C_GenerateSTOP();
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|